0

I have code that listens to multicast send by a windows app it works perfectly fine from android 7.0 and below but on android 8.0 it works then randomly stop from 5 mins to 1 hr without throwing an exception. I am not sure if this is affected by Background Service Limitations that was introduced on Android 8.0. but I did some research and some said that it should be not affected since it is a thread here! but since it is still a background thread I am not sure.

Here my code for the Multicast Thread :

public class MulticastThread extends Thread {



final AtomicBoolean running = new AtomicBoolean(true);
final Activity mActivity;
final String multicastIP;
final int multicastPort;
final Handler handler;

protected MulticastSocket multicastSocket;
private InetAddress inetAddress;
private NetworkInterface networkInterface;

public MulticastThread(String threadName, Activity mActivity, String multicastIP, int multicastPort, Handler handler) {
    super(threadName);
    this.mActivity = mActivity;
    this.multicastIP = multicastIP;
    this.multicastPort = multicastPort;
    this.handler = handler;
}

@Override
public void run() {
    try {

        WifiManager wifiManager = (WifiManager) mActivity.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
        WifiInfo wifiInfo = wifiManager.getConnectionInfo();
        int wifiIPInt = wifiInfo.getIpAddress();
        byte[] wifiIPByte = new byte[]{
                (byte) (wifiIPInt & 0xff),
                (byte) (wifiIPInt >> 8 & 0xff),
                (byte) (wifiIPInt >> 16 & 0xff),
                (byte) (wifiIPInt >> 24 & 0xff)};
        this.inetAddress = InetAddress.getByAddress(wifiIPByte);
        this.networkInterface = NetworkInterface.getByInetAddress(inetAddress);

        this.multicastSocket = new MulticastSocket(multicastPort);
        multicastSocket.setNetworkInterface(networkInterface);
        multicastSocket.joinGroup(InetAddress.getByName(multicastIP));
        multicastSocket.setSoTimeout(100);
        multicastSocket.setTimeToLive(2);
    } catch (BindException e) {
        handler.post(new Runnable() {
            @Override
            public void run() {
                if(mActivity instanceof CameraActivity){
                    ((CameraActivity) mActivity).stopListening();
                }
            }
        });
        String error = "Error: Cannot bind Address or Port.";
        if (multicastPort < 1024)
            error += "\nTry binding to a port larger than 1024.";
        outputErrorToConsole(error);
        Log.d("ETO>>>",e+"");
    } catch (IOException e) {
        handler.post(new Runnable() {
            @Override
            public void run() {
                if(mActivity instanceof CameraActivity){
                    ((CameraActivity) mActivity).stopListening();
                }
            }
        });
        String error = "Error: Cannot bind Address or Port.\n"
                + "An error occurred: " + e.getMessage();
        outputErrorToConsole(error);
        Log.d(">>>",e+"");
    }catch (Throwable e )
    {
        Log.d(">>>",e+"");
    }
}

String getLocalIP() {
    return this.inetAddress.getHostAddress();
}

void outputErrorToConsole(final String errorMessage) {
    handler.post(new Runnable() {
        @Override
        public void run() {
            if(mActivity instanceof CameraActivity){
                ((CameraActivity) mActivity).showError(errorMessage);
            }
        }
    });
}

public void stopRunning() {
    this.running.set(false);
}

}

Here the code for the Multicast Listener:

public class MulticastListenerThread extends MulticastThread {

private DatagramPacket packet;
private long newSeqNum;
private long lastSeqNum;
AppSettings appSettings;

public MulticastListenerThread(Activity activity, String multicastIP, int multicastPort) {
    super("MulticastListenerThread", activity, multicastIP, multicastPort, new Handler());
}


@Override
public void run() {


    super.run();
    appSettings = AppSettings.getAppSettingsFromSharedPreference(mActivity);
    newSeqNum = 0;
    lastSeqNum = 0;



    this.packet = new DatagramPacket(new byte[65536], 65536);

    while (running.get()) {
        packet.setData(new byte[65536]);

        try {
            if (multicastSocket != null)
                multicastSocket.receive(packet);
            else
                break;
        } catch (IOException ignored) {
            continue;
        }

        final String data = new String(packet.getData()).trim();
        Log.i("Multicast", data);

        this.handler.post(new Runnable() {
            @Override
            public void run() {
                if (mActivity instanceof CameraActivity) {

                  //  ((CameraActivity) mActivity).log(consoleMessage);

                    String actionMessage = "";

                    long timer=0;

                    if (data.contains("seq")) {
                        if(data.contains(",")) {
                            String[] result = data.split(",");
                            String data2 = result[0];
                            timer = Long.parseLong(result[1]);
                            newSeqNum = Long.valueOf(data2.substring(data2.lastIndexOf("_") + 1));
                            String messageWithSubSeq = data2.substring(0, (data2.lastIndexOf("_seq_")));
                            actionMessage = messageWithSubSeq.substring(0, (messageWithSubSeq.lastIndexOf("_")));
                        }else {
                            // long l = Long.parseLong(str);
                            newSeqNum = Long.valueOf(data.substring(data.lastIndexOf("_") + 1));
                            String messageWithSubSeq = data.substring(0, (data.lastIndexOf("_seq_")));
                            actionMessage = messageWithSubSeq.substring(0, (messageWithSubSeq.lastIndexOf("_")));
                        }

                    }else if(data.contains("synctime"))
                    {

                        appSettings = AppSettings.getAppSettingsFromSharedPreference(mActivity);
                        appSettings.setCheckaudit(true);
                        appSettings.save(mActivity);
                        ((CameraActivity) mActivity).onSynctime();


                    }else if(data.contains("processtime"))
                    {
                        appSettings = AppSettings.getAppSettingsFromSharedPreference(mActivity);
                        appSettings.setUpload(false);
                        appSettings.save(mActivity);


                        ((CameraActivity) mActivity).onCancelUpload();
                    }




                    Log.d("Received! " , ""+data);
                }
            }
        });
    }
    if (multicastSocket != null)
        this.multicastSocket.close();
}

}

I Initialize it on the main activity with onResume using this function:

public void startListening() {

    appSettings = AppSettings.getAppSettingsFromSharedPreference(this);

    if (!isListening) {
        ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
        if (connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI).isConnected()) {
            setWifiLockAcquired(true);

            this.multicastListenerThread = new MulticastListenerThread(this,  Constants.INET_ADDRESS,
                    Constants.MULTISOCKET_PORT);





            multicastListenerThread.start();

            Log.d(">>>>>",multicastListenerThread.getPriority()+"");

            isListening = true;

        } else {
            showError("Connect to  Network");
        }


   }
}

Then I stop the threads with onDestroy:

private void stopThreads() {
    if (this.multicastListenerThread != null)
        this.multicastListenerThread.stopRunning();
    if (this.multicastSenderThread != null)
        this.multicastSenderThread.interrupt();


}
Odysseus
  • 1
  • 1
  • The question you linked to has some misleading information in it, please see my answer [here](https://stackoverflow.com/a/53460232/6759241). – greeble31 Nov 24 '18 at 16:39
  • sorry i forgot to mention that i already used "getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);" and the app is always on foreground or on screen during the sudden termination of the thread – Odysseus Nov 25 '18 at 08:13
  • I suspect you are mistaken about the thread "stopping". It's probably still running, it's just not doing what you expect it to be doing. If the thread had crashed, your entire app would've crashed. You should add more data about how you came to this conclusion. Also, you can use the debugger to "break into" all the threads at once, and you can then determine which state each thread is in. – greeble31 Nov 25 '18 at 14:23
  • No the app will not crashed even if the thread stopped but yes you may be correct that it is still running but the problem is i can send the multicast from the server then suddenly they cant received anymore but its not the same with all the phones i have more than 10 phones listening and they have different time when they will be disconnected from the multicast – Odysseus Nov 26 '18 at 04:31

0 Answers0