• After 15+ years, we've made a big change: Android Forums is now Early Bird Club. Learn more here.

Apps Trouble with TCP Client/Server

Jo_Han_Solo

Newbie
Hey guys,

I wrote this basic TCP Client in Android with a C++ Server running in Linux.

Now the thing is this worked through Ethernet with a Rooted Samsung Note 2, however, with a brand spanking new Samsung Galaxy Note 8, it no longer works. Everything works great on the Rooted Note 2. But when I try to open up the connection to the server on the Note 8 the app crashes.

Granted the Note 8 phone is not rooted, however, I didn't think it would be necessary since it supports Ethernet natively.

Basically my question is, does any of you guys have any experience with sockets and TCP communications on the Note 8 through an Ethernet connection, or have any idea of what might be causing the app to crash when I try to connect on the Note 8?

The server still establishes the connection in C++, but each time it does the app crashes on Android.

Cheers!
 
Can you possibly connect your device to a computer and run the app directly to it from Android Studio?
This way you can see the logs and stack trace. If the app crashed there will be a stack trace.
 
Can you possibly connect your device to a computer and run the app directly to it from Android Studio?
This way you can see the logs and stack trace. If the app crashed there will be a stack trace.

The problem here is that I'm using the OTG cable for the ethernet adapter in order to communicate with the linux server,. I would have to set them both to a shared wifi connection and then run it through wifi through android studio in order to see the stack trace.

It is something I've thought about doing and if I do decide to go down that road I'll post the stack trace here.

EDIT: Sorted out the WIFI thing and here's the error messages when the app crashes:
10-31 08:17:58.624 11031-11031/HIDDENONPURPOSE.another_attempt E/AndroidRuntime: FATAL EXCEPTION: main
Process: "HIDDEN ON PURPOSE", PID: 11031
android.os.NetworkOnMainThreadException
at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1303)
at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:111)
at java.net.SocketOutputStream.write(SocketOutputStream.java:157)
at sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:221)
at sun.nio.cs.StreamEncoder.implFlushBuffer(StreamEncoder.java:291)
at sun.nio.cs.StreamEncoder.implFlush(StreamEncoder.java:295)
at sun.nio.cs.StreamEncoder.flush(StreamEncoder.java:141)
at java.io. OutputStreamWriter.flush(OutputStreamWriter.java:229)
at java.io.BufferedWriter.flush(BufferedWriter.java:254)
at java.io.PrintWriter.newLine(PrintWriter.java:482)
at java.io.PrintWriter.println(PrintWriter.java:629)
at java.io.PrintWriter.println(PrintWriter.java:740)
at au.com.whateverwebsite.cam_tcp_ss.TCPClient.sendMessage(TCPClient.java:34)
at au.com.whateverwebsite.cam_tcp_ss.StreamActivity$1.run(StreamActivity.java:95)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6823)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1557)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1445)
 
Last edited:
Actually this problem was solved by adding the following lines to the MainActivity:

StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);

So if anyone else encounters a similar issue. This might help you.
 
You haven't solved the problem there, you've just masked the initial problem, and you could still be in for severe difficulties at run time.

NetworkOnMainThreadException is thrown for a reason. That's because you have some code on the main thread which is trying to establish a network connection (open a socket?)
That's very bad because if there's a blocking situation on that setup, or any block during network writes, then your whole app will freeze up, because you've blocked the main thread, and that handles all UI events.
The proper way to perform network activity in an Android app, is to use a background thread to do it.
 
You haven't solved the problem there, you've just masked the initial problem, and you could still be in for severe difficulties at run time.

NetworkOnMainThreadException is thrown for a reason. That's because you have some code on the main thread which is trying to establish a network connection (open a socket?)
That's very bad because if there's a blocking situation on that setup, or any block during network writes, then your whole app will freeze up, because you've blocked the main thread, and that handles all UI events.
The proper way to perform network activity in an Android app, is to use a background thread to do it.

Yeah see that's the thing though, I'm already using a background thread, there is no networking being done in the main thread as far as I can tell, and since there were no errors being thrown on the Note 2 and it was working perfectly fine (after I fixed the threading issue on that phone) it seems to me like it really was that strict mode command that was screwing it up somehow.

Because, prior to that being in there, if I was really just "masking" the problem, then shouldn't the "NetworkOnMainThreadException" be thrown even on the Note 2? Because on that device no errors were being thrown.
 
Okay but there's a lot of it.

Main Activity:
Code:
public class MainActivity extends AppCompatActivity {
    public static Button button;
    [USER=1021285]@override[/USER]
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
        StrictMode.setThreadPolicy(policy);

        setContentView(R.layout.activity_main);
        button = (Button) findViewById(R.id.UGVCam);
        //button.setEnabled(true);
    }

    protected void onResume(){
        super.onResume();
        button.setEnabled(true);
    }
    /*
    protected void onRestart(){
        super.onRestart();
        button.setEnabled(true);
    }*/

    [USER=1021285]@override[/USER]
    public boolean onGenericMotionEvent(MotionEvent event) {
        if(Dpad.isDpadDevice(event)){
            return true;
        }
        return true;
    }

    [USER=1021285]@override[/USER]
    public boolean onKeyDown(int keyCode, KeyEvent event)
    {
        if(keyCode == KeyEvent.KEYCODE_BACK){
            Toast.makeText(this, "Press HOME to EXIT!", Toast.LENGTH_SHORT).show();
            return true;
        }
        return true;
    }

    public void SwitchScreen(View view){
        Intent intent = new Intent(getApplicationContext(), StreamActivity.class);
        startActivity(intent);
        button.setEnabled(false);
    }
}

StreamActivity:
Code:
public class StreamActivity extends AppCompatActivity implements IVLCVout.Callback {
    //Lib VLC Defined Variables
    public final static String TAG = "LibVLCAndroidSample/VideoActivity";
    private SurfaceView mSurface;
    private SurfaceHolder holder;
    // media player
    private LibVLC libvlc;
    private MediaPlayer mMediaPlayer = null;
    private int mVideoWidth;
    private int mVideoHeight;
    private final static int VideoSizeChanged = -1;

    //Game Controller
    private ListView mList;
    private ArrayList<String> arrayList;
    private MyCustomAdapter mAdapter;
    private TCPClient mTcpClient;

    public String message = "!CB_DP:0.0";
    public String LTmessage = "!LS_LT:0.0";
    public String RTmessage = "!RS_RT:0.0";
    public String Xmessage = "!LS_LR:0.0";
    public String X2message = "!LS_UD:0.0";
    public String Ymessage = "!RS_LR:0.0";
    public String Y2message = "!RS_UD:0.0";
    //public String ConMessage = "!IS_CO:0.0";

    /*
    public String message = null;
    public String LTmessage = null;
    public String RTmessage = null;
    public String Xmessage = null;
    public String X2message = null;
    public String Ymessage = null;
    public String Y2message = null;
    */

    Dpad mDpad = new Dpad();
    Handler handler = new Handler();
    Handler handler2 = new Handler();
    public int delay = 50;
    public int delay2 = 20;

    /*************
     * Activity
     *************/

    [USER=1021285]@override[/USER]
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
        StrictMode.setThreadPolicy(policy);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
        setContentView(R.layout.activity_stream);

        //ArrayList LocalIDs = getGameControllerIds();

        mSurface = (SurfaceView) findViewById(R.id.surface);
        holder = mSurface.getHolder();
        setSize(mVideoWidth,mVideoHeight);

        //GAME CONTROLLER SECTION:
        arrayList = new ArrayList<String>();
        mAdapter = new MyCustomAdapter(this, arrayList);
        new connectTask().execute("");
        handler.postDelayed(new Runnable() {
            [USER=1021285]@override[/USER]
            public void run() {
                mTcpClient.sendMessage(Xmessage);
                mTcpClient.sendMessage(Ymessage);
                //Toast.makeText(StreamActivity.this, "Yeah Boiiii", Toast.LENGTH_SHORT).show();
                handler.postDelayed(this,delay);
            }
        },delay);

        handler2.postDelayed(new Runnable() {
            [USER=1021285]@override[/USER]
            public void run() {
                mTcpClient.sendMessage(X2message);
                mTcpClient.sendMessage(Y2message);
                //Toast.makeText(StreamActivity.this, "Yeah Boiiii", Toast.LENGTH_SHORT).show();
                handler2.postDelayed(this,delay2);
            }
        },delay);
    }

    [USER=1021285]@override[/USER]
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        setSize(mVideoWidth, mVideoHeight);
    }

    [USER=1021285]@override[/USER]
    protected void onResume() {
        super.onResume();
        createPlayer();
        //mTcpClient.sendMessage("!IS_CO:YES");
    }

    [USER=1021285]@override[/USER]
    protected void onPause() {
        super.onPause();
        releasePlayer();
        mTcpClient.stopClient();
    }

    [USER=1021285]@override[/USER]
    protected void onDestroy() {
        super.onDestroy();
        releasePlayer();
        mTcpClient.stopClient();
    }

    /*************
     * Surface
     *************/
    private void setSize(int width, int height) {
        mVideoWidth = width;
        mVideoHeight = height;
        if (mVideoWidth * mVideoHeight <= 1)
            return;

        if (holder == null || mSurface == null)
            return;

        // get screen size
        int w = getWindow().getDecorView().getWidth();
        int h = getWindow().getDecorView().getHeight();
        //int w = this.getResources().getDisplayMetrics().widthPixels;
        //int h = this.getResources().getDisplayMetrics().heightPixels;

        // getWindow().getDecorView() doesn't always take orientation into
        // account, we have to correct the values
        boolean isPortrait = getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT;
        if (w > h && isPortrait || w < h && !isPortrait) {
            int i = w;
            w = h;
            h = i;
        }

        float videoAR = (float) mVideoWidth / (float) mVideoHeight;
        float screenAR = (float) w / (float) h;

        if (screenAR < videoAR)
            h = (int) (w / videoAR);
        else
            w = (int) (h * videoAR);

        // force surface buffer size
        holder.setFixedSize(mVideoWidth, mVideoHeight);

        // set display size
        ViewGroup.LayoutParams lp = mSurface.getLayoutParams();
        lp.width = w;
        lp.height = h;
        mSurface.setLayoutParams(lp);
        mSurface.invalidate();
    }
    /*************
     * Player
     *************/

    private void createPlayer() {
        releasePlayer();
        try {
            /*
            if (media.length() > 0) {
                Toast toast = Toast.makeText(this, media, Toast.LENGTH_LONG);
                toast.setGravity(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0,
                        0);
                toast.show();
            }*/

            // Create LibVLC
            // TODO: make this more robust, and sync with audio demo
            ArrayList<String> options = new ArrayList<String>();
            options.add("--file-caching=2000");
            //options.add("--subsdec-encoding <encoding>");
            //options.add("--aout=false");
            //options.add("--avcodec-skiploopfilter");
            //options.add("--avcodec-skip-frame=4");
            //options.add("--avcodec-skip-idct=4");
            //options.add("--network-caching=2");
            //options.add("--audio-time-stretch"); // time stretching
            options.add("-vvv"); // verbosity
            libvlc = new LibVLC(this, options);
            holder.setKeepScreenOn(true);

            // Create media player
            mMediaPlayer = new MediaPlayer(libvlc);
            mMediaPlayer.setEventListener(mPlayerListener);

            // Set up video output
            final IVLCVout vout = mMediaPlayer.getVLCVout();
            vout.setVideoView(mSurface);
            vout.addCallback(this);
            vout.attachViews();
            Media m = new Media(libvlc, Uri.parse("rtsp://root:4977@192.168.127.9:554/axis-media/media.amp"));
            m.setHWDecoderEnabled(true,false);
            m.addOption(":network-caching=150");
            m.addOption(":clock-jitter=0");
            m.addOption(":clock-synchro=0");
            mMediaPlayer.setMedia(m);
            mMediaPlayer.setAspectRatio("16:9");
            mMediaPlayer.setScale(1.0f);
            mMediaPlayer.play();
        } catch (Exception e) {
            Toast.makeText(this, "Error creating player!", Toast.LENGTH_LONG).show();
        }
    }

    // TODO: handle this cleaner
    private void releasePlayer() {
        if (libvlc == null)
            return;
        mMediaPlayer.stop();
        final IVLCVout vout = mMediaPlayer.getVLCVout();
        vout.removeCallback(this);
        vout.detachViews();
        holder = null;
        libvlc.release();
        libvlc = null;

        mVideoWidth = 0;
        mVideoHeight = 0;
    }

    /*************
     * Events
     *************/
    private MediaPlayer.EventListener mPlayerListener = new MyPlayerListener(this);

    public void onNewLayout(IVLCVout vout, int width, int height, int visibleWidth, int visibleHeight, int sarNum, int sarDen) {
        if (width * height == 0)
            return;

        // store video size
        mVideoWidth = width;
        mVideoHeight = height;
        setSize(mVideoWidth, mVideoHeight);
    }

    [USER=1021285]@override[/USER]
    public void onSurfacesCreated(IVLCVout vout) {
        setSize(mVideoWidth,mVideoHeight);
    }

    [USER=1021285]@override[/USER]
    public void onSurfacesDestroyed(IVLCVout vout) {

    }
    private static class MyPlayerListener implements MediaPlayer.EventListener {
        private WeakReference<StreamActivity> mOwner;

        public MyPlayerListener(StreamActivity owner) {
            mOwner = new WeakReference<StreamActivity>(owner);
        }

        [USER=1021285]@override[/USER]
        public void onEvent(MediaPlayer.Event event) {
            StreamActivity player = mOwner.get();

            switch (event.type) {
                case MediaPlayer.Event.EndReached:
                    player.releasePlayer();
                    break;
                case MediaPlayer.Event.Playing:
                case MediaPlayer.Event.Paused:
                case MediaPlayer.Event.Stopped:
                default:
                    break;
            }
        }
    }

    public class connectTask extends AsyncTask<String, String, TCPClient> {

        [USER=1021285]@override[/USER]
        protected TCPClient doInBackground(String... message) {

            //we create a TCPClient object and
            mTcpClient = new TCPClient(new TCPClient.OnMessageReceived() {
                [USER=1021285]@override[/USER]
                //here the messageReceived method is implemented
                public void messageReceived(String message) {
                    //this method calls the onProgressUpdate
                    publishProgress(message);
                }
            });
            mTcpClient.run();

            return null;
        }

        [USER=1021285]@override[/USER]
        protected void onProgressUpdate(String... values) {
            super.onProgressUpdate(values);

            //in the arrayList we add the messaged received from server
            arrayList.add(values[0]);
            // notify the adapter that the data set has changed. This means that new message received
            // from server was added to the list
            mAdapter.notifyDataSetChanged();
        }
    }
/*
    public ArrayList getGameControllerIds() {
        ArrayList gameControllerDeviceIds = new ArrayList();
        int[] deviceIds = InputDevice.getDeviceIds();
        for (int deviceId : deviceIds) {
            InputDevice dev = InputDevice.getDevice(deviceId);
            int sources = dev.getSources();

            // Verify that the device has gamepad buttons, control sticks, or both.
            if (((sources & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD)
                    || ((sources & InputDevice.SOURCE_JOYSTICK)
                    == InputDevice.SOURCE_JOYSTICK)) {
                // This device is a game controller. Store its device ID.
                ConMessage = "!IS_CO:YES";
                mTcpClient.sendMessage(ConMessage);
                if (!gameControllerDeviceIds.contains(deviceId)) {
                    gameControllerDeviceIds.add(deviceId);
                }
            }
        }
        return gameControllerDeviceIds;
    }*/

    [USER=1021285]@override[/USER]
    public boolean onGenericMotionEvent(MotionEvent event){
        boolean handled_motion = false;
        if(Dpad.isDpadDevice(event)){
            int press = mDpad.getDirectionPressed(event);
            switch(press){
                case Dpad.LEFT:
                    message = "!CB_DP:LEFT";
                    if (mTcpClient != null) {
                        mTcpClient.sendMessage(message);
                    }
                    //DirectionPressedView.setText("Left");
                    handled_motion = true;
                    break;
                case Dpad.RIGHT:
                    message = "!CB_DP:RIGHT";
                    if (mTcpClient != null) {
                        mTcpClient.sendMessage(message);
                    }
                    //DirectionPressedView.setText("Right");
                    handled_motion = true;
                    break;
                case Dpad.DOWN:
                    message = "!CB_DP:DOWN";
                    if (mTcpClient != null) {
                        mTcpClient.sendMessage(message);
                    }
                    //DirectionPressedView.setText("Down");
                    handled_motion = true;
                    break;
                case Dpad.UP:
                    message = "!CB_DP:UP";
                    if (mTcpClient != null) {
                        mTcpClient.sendMessage(message);
                    }
                    //DirectionPressedView.setText("Up");
                    handled_motion = true;
                    break;
            }
        }



        //Handle Joystick Movements
        if ((event.getSource() & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK && event.getAction() == MotionEvent.ACTION_MOVE){
            final int historySize = event.getHistorySize();
            // Process the movements starting from the
            // earliest historical position in the batch
            for (int i = 0; i < historySize; i++) {
                // Process the event at historical position i
                processJoystickInput(event, i);
            }

            processJoystickInput(event, -1);
            handled_motion = true;
        }
        if(handled_motion){
            return true;
        }
        return super.onGenericMotionEvent(event);
    }

    public boolean onKeyDown(int keyCode, KeyEvent event){
        boolean handled = false;

        // Handle Button Presses

        if((event.getSource() & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD){
            if(event.getRepeatCount() == 0){
                // STEELSERIES CONTROLLER:

                if(keyCode == KeyEvent.KEYCODE_BUTTON_A){
                    message = "!CB_SB:A";
                    if (mTcpClient != null) {
                        mTcpClient.sendMessage(message);
                    }
                    handled = true;
                }
                else if(keyCode == KeyEvent.KEYCODE_BUTTON_B){
                    message = "!CB_SB:B";
                    if (mTcpClient != null) {
                        mTcpClient.sendMessage(message);
                    }
                    handled = true;
                }
                else if(keyCode == KeyEvent.KEYCODE_BUTTON_X){
                    message = "!CB_SB:X";
                    if (mTcpClient != null) {
                        mTcpClient.sendMessage(message);
                    }
                    handled = true;
                }
                else if(keyCode == KeyEvent.KEYCODE_BUTTON_Y){
                    message = "!CB_SB:Y";
                    if (mTcpClient != null) {
                        mTcpClient.sendMessage(message);
                    }
                    handled = true;
                }
                else if(keyCode == KeyEvent.KEYCODE_BUTTON_THUMBL){
                    message = "!CB_SB:L3";
                    if (mTcpClient != null) {
                        mTcpClient.sendMessage(message);
                    }
                    handled = true;
                }
                else if(keyCode == KeyEvent.KEYCODE_BUTTON_THUMBR){
                    message = "!CB_SB:R3";
                    if (mTcpClient != null) {
                        mTcpClient.sendMessage(message);
                    }
                    handled = true;
                }
                else if(keyCode == KeyEvent.KEYCODE_BUTTON_L1){
                    message = "!CB_SB:L1";
                    if (mTcpClient != null) {
                        mTcpClient.sendMessage(message);
                    }
                    handled = true;
                }
                else if(keyCode == KeyEvent.KEYCODE_BUTTON_R1){
                    message = "!CB_SB:R1";
                    if (mTcpClient != null) {
                        mTcpClient.sendMessage(message);
                    }
                    handled = true;
                }
                else if(keyCode == KeyEvent.KEYCODE_BUTTON_START){
                    message = "!CB_SB:START";
                    if (mTcpClient != null) {
                        mTcpClient.sendMessage(message);
                    }
                    handled = true;
                }
                else if(keyCode == KeyEvent.KEYCODE_BACK){
                    message = "!CB_SB:BACK";
                    if (mTcpClient != null) {
                        mTcpClient.sendMessage(message);
                    }
                    handled = true;
                }
                else{
                    message = "!CB_SB:SELECT";
                    if (mTcpClient != null) {
                        mTcpClient.sendMessage(message);
                    }
                    handled = true;
                }

            }
        }

        if(handled){
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }

    private void processJoystickInput(MotionEvent event, int historyPos){
        InputDevice mInputDevice = event.getDevice();
        /*
        if (x == 0){
            x = getCenteredAxis(event, mInputDevice, MotionEvent.AXIS_HAT_X, historyPos);
        }*/

        /*
        if (y == 0) {
            y = getCenteredAxis(event, mInputDevice, MotionEvent.AXIS_HAT_Y, historyPos);
        }*/

        float LeftT = getCenteredAxis(event, mInputDevice, MotionEvent.AXIS_BRAKE,historyPos);
        float RightT = getCenteredAxis(event, mInputDevice, MotionEvent.AXIS_GAS,historyPos);

        String messageLT = String.valueOf(LeftT);
        LTmessage = "!LS_LT:" + messageLT;
        if (mTcpClient != null) {
            mTcpClient.sendMessage(LTmessage);
        }

        String messageRT = String.valueOf(RightT);
        RTmessage = "!RS_RT:" + messageRT;
        if (mTcpClient != null) {
            mTcpClient.sendMessage(RTmessage);
        }


        float x = getCenteredAxis(event, mInputDevice, MotionEvent.AXIS_X, historyPos);
        float y = getCenteredAxis(event, mInputDevice, MotionEvent.AXIS_Y, historyPos);

        String messagex = String.valueOf(x);
        Xmessage = "!LS_LR:" + messagex;
        if (mTcpClient != null) {
            mTcpClient.sendMessage(Xmessage);
        }

        String messagey = String.valueOf(y);
        Ymessage = "!LS_UD:" + messagey;
        if (mTcpClient != null) {
            mTcpClient.sendMessage(Ymessage);
        }

        float x2 = getCenteredAxis(event, mInputDevice, MotionEvent.AXIS_Z, historyPos);
        float y2 = getCenteredAxis(event, mInputDevice, MotionEvent.AXIS_RZ, historyPos);

        String messagex2 = String.valueOf(x2);
        X2message = "!RS_LR:" + messagex2;
        if (mTcpClient != null) {
            mTcpClient.sendMessage(X2message);
        }

        String messagey2 = String.valueOf(y2);
        Y2message = "!RS_UD:" + messagey2;
        if (mTcpClient != null) {
            mTcpClient.sendMessage(Y2message);
        }
    }
    private static float getCenteredAxis(MotionEvent event, InputDevice device, int axis, int historyPos){
        final InputDevice.MotionRange range = device.getMotionRange(axis, event.getSource());

        if (range != null){
            final float flat = range.getFlat();
            final float value = historyPos < 0 ? event.getAxisValue(axis): event.getHistoricalAxisValue(axis,historyPos);

            if (Math.abs(value) > flat){
                return value;
            }
        }
        return 0;
    }
}

Dpad Class:
Code:
public class Dpad {

    final static int UP = 0;
    final static int LEFT = 1;
    final static int RIGHT = 2;
    final static int DOWN = 3;
    final static int CENTER = 4;

    int directionPressed = -1;

    public int getDirectionPressed(InputEvent event){
        if(!isDpadDevice(event)){
            return -1;
        }

        // If the input event is a MotionEvent, check its hat axis values.
        if (event instanceof MotionEvent) {

            // Use the hat axis value to find the D-pad direction
            MotionEvent motionEvent = (MotionEvent) event;
            float xaxis = motionEvent.getAxisValue(MotionEvent.AXIS_HAT_X);
            float yaxis = motionEvent.getAxisValue(MotionEvent.AXIS_HAT_Y);

            // Check if the AXIS_HAT_X value is -1 or 1, and set the D-pad
            // LEFT and RIGHT direction accordingly.
            if (Float.compare(xaxis, -1.0f) == 0) {
                directionPressed =  Dpad.LEFT;
            } else if (Float.compare(xaxis, 1.0f) == 0) {
                directionPressed =  Dpad.RIGHT;
            }
            // Check if the AXIS_HAT_Y value is -1 or 1, and set the D-pad
            // UP and DOWN direction accordingly.
            else if (Float.compare(yaxis, -1.0f) == 0) {
                directionPressed =  Dpad.UP;
            } else if (Float.compare(yaxis, 1.0f) == 0) {
                directionPressed =  Dpad.DOWN;
            }
        }

        // If the input event is a KeyEvent, check its key code.
        else if (event instanceof KeyEvent) {

            // Use the key code to find the D-pad direction.
            KeyEvent keyEvent = (KeyEvent) event;
            if (keyEvent.getKeyCode() == KeyEvent.KEYCODE_DPAD_LEFT) {
                directionPressed = Dpad.LEFT;
            } else if (keyEvent.getKeyCode() == KeyEvent.KEYCODE_DPAD_RIGHT) {
                directionPressed = Dpad.RIGHT;
            } else if (keyEvent.getKeyCode() == KeyEvent.KEYCODE_DPAD_UP) {
                directionPressed = Dpad.UP;
            } else if (keyEvent.getKeyCode() == KeyEvent.KEYCODE_DPAD_DOWN) {
                directionPressed = Dpad.DOWN;
            } else if (keyEvent.getKeyCode() == KeyEvent.KEYCODE_DPAD_CENTER) {
                directionPressed = Dpad.CENTER;
            }
        }
        return directionPressed;
    }

    public static boolean isDpadDevice(InputEvent event) {
        // Check that input comes from a device with directional pads.
        if ((event.getSource() & InputDevice.SOURCE_DPAD)
                != InputDevice.SOURCE_DPAD) {
            return true;
        } else {
            return false;
        }
    }
}
MyCustomAdapter Class:
public class MyCustomAdapter extends BaseAdapter {
    private ArrayList<String> mListItems;
    private LayoutInflater mLayoutInflater;

    public MyCustomAdapter(Context context, ArrayList<String> arrayList){

        mListItems = arrayList;

        //get the layout inflater
        mLayoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

    [USER=1021285]@override[/USER]
    public int getCount() {
        //getCount() represents how many items are in the list
        return mListItems.size();
    }

    [USER=1021285]@override[/USER]
    //get the data of an item from a specific position
    //i represents the position of the item in the list
    public Object getItem(int i) {
        return null;
    }

    [USER=1021285]@override[/USER]
    //get the position id of the item from the list
    public long getItemId(int i) {
        return 0;
    }

    [USER=1021285]@override[/USER]

    public View getView(int position, View view, ViewGroup viewGroup) {

        //check to see if the reused view is null or not, if is not null then reuse it
        if (view == null) {
            //view = mLayoutInflater.inflate(R.layout.list_item, null);
        }

        //get the string item from the position "position" from array list to put it on the TextView
        String stringItem = mListItems.get(position);
        //if (stringItem != null) {

            //TextView itemName = (TextView) view.findViewById(R.id.list_item_text_view);

            //if (itemName != null) {
                //set the item name on the TextView
                //itemName.setText(stringItem);
           // }
        //}

        //this method must return the view corresponding to the data at the specified position.
        return view;

    }
}

TCPClient Class:
Code:
public class TCPClient {

    private String serverMessage;
    //public static final String SERVERIP = "192.168.1.19"; //your computer IP address
    //public static final String SERVERIP = "192.168.1.26"; //your computer IP address
    public static final String SERVERIP = "192.168.127.91";
    public static final int SERVERPORT = 4444;
    private OnMessageReceived mMessageListener = null;
    private boolean mRun = false;

    PrintWriter out;
    BufferedReader in;

    /**
     *  Constructor of the class. OnMessagedReceived listens for the messages received from server
     */
    public TCPClient(OnMessageReceived listener) {
        mMessageListener = listener;
    }

    /**
     * Sends the message entered by client to the server
     * [USER=315340]@param[/USER] message text entered by client
     */
    public void sendMessage(String message){
        if (out != null && !out.checkError()) {
            out.println(message);
            out.flush();
        }
    }

    public void stopClient(){
        out.flush();
        out.close();
    }

    public void run() {

        mRun = true;

        try {
            //here you must put your computer's IP address.
            InetAddress serverAddr = InetAddress.getByName(SERVERIP);

            Log.e("TCP Client", "C: Connecting...");

            //create a socket to make the connection with the server
            Socket socket = new Socket(SERVERIP, SERVERPORT);

            try {

                //send the message to the server
                out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);

                Log.e("TCP Client", "C: Sent.");

                Log.e("TCP Client", "C: Done.");

                //receive the message which the server sends back
                in = new BufferedReader(new InputStreamReader(socket.getInputStream()));

                //in this while the client listens for the messages sent by the server
                while (mRun) {
                    serverMessage = in.readLine();

                    if (serverMessage != null && mMessageListener != null) {
                        //call the method messageReceived from MyActivity class
                        mMessageListener.messageReceived(serverMessage);
                    }
                    serverMessage = null;

                }

                Log.e("RESPONSE FROM SERVER", "S: Received Message: '" + serverMessage + "'");

            } catch (Exception e) {

                Log.e("TCP", "S: Error", e);

            } finally {
                //the socket must be closed. It is not possible to reconnect to this socket
                // after it is closed, which means a new socket instance has to be created.
                socket.close();
            }

        } catch (Exception e) {

            Log.e("TCP", "C: Error", e);

        }

    }

    //Declare the interface. The method messageReceived(String message) will must be implemented in the MyActivity
    //class at on asynckTask doInBackground
    public interface OnMessageReceived {
        public void messageReceived(String message);
    }
}
 
Last edited by a moderator:
I see you're using Handler to send messages. Looking at the documentation for the Handler class

https://developer.android.com/reference/android/os/Handler.html

The runnable will be executed on the main thread's message queue. I don't think this technique is usually used for network activity in an Android app, and as your results show, has inconsistent behaviour. Looks like one device is detecting a NetworkOnMainThread situation, whereas the other is not. Technically it is correct to throw this exception.
You may be ok, but I would have a think and see if you can find some other way to do that network activity, and have it solely confined to a background thread.
 
I see you're using Handler to send messages. Looking at the documentation for the Handler class

https://developer.android.com/reference/android/os/Handler.html

The runnable will be executed on the main thread's message queue. I don't think this technique is usually used for network activity in an Android app, and as your results show, has inconsistent behaviour. Looks like one device is detecting a NetworkOnMainThread situation, whereas the other is not. Technically it is correct to throw this exception.
You may be ok, but I would have a think and see if you can find some other way to do that network activity, and have it solely confined to a background thread.

Thanks for your help mate, I'll have a look into it and see what I can do to make it more robust.

Also, how do you post code blocks like that above? I've tried figuring it out but I'm clearly just being blind.
 
Thanks for your help mate, I'll have a look into it and see what I can do to make it more robust.

Also, how do you post code blocks like that above? I've tried figuring it out but I'm clearly just being blind.


[code]
Some code here
[/code]
 
Back
Top Bottom