Search code examples
androidandroid-serviceandroid-handlerandroid-7.1-nougatandroid-binder

What's wrong with 7 android?


I have Service for receive udp datagramm sockets

     private void startServer(final UdpServerListener listener) {

     mStarted = true;
            mWakeLock.acquire(10 * 60 * 1000L /*10 minutes*/);
            Looper myLooper = Looper.myLooper();

            new HandlerThread("TcpServerThread") {
                @Override
                protected void onLooperPrepared() {
                    new Handler(getLooper()).post(() -> {
                        try {
                            byte[] data = new byte[8 * 1024];

                            InetAddress address = BnjUtils.getLocalIpAddress();

                            DatagramPacket datagramPacket = new DatagramPacket(data, data.length);
                            mServerSocket = new DatagramSocket(0, address);

                            final InetAddress localAddress = ((InetSocketAddress) mServerSocket.getLocalSocketAddress()).getAddress();
                            final int port = mServerSocket.getLocalPort();


                            while (mStarted) {

                                try {

                                   mServerSocket.receive(datagramPacket); // blocks until something is received
                                    /*
                                     * Send bytes to app module.
                                     */
                                    byte[] receiveData = new byte[datagramPacket.getLength()];

                                    System.arraycopy(datagramPacket.getData(), datagramPacket.getOffset(), receiveData, 0, datagramPacket.getLength());

     //POST MY DATA TO BINDER VIA HANDLE LOOPER AND LISTENER                                       
    new Handler(myLooper).post(() -> listener.onReceive(receiveData,datagramPacket.getAddress()));


                                } catch (IOException e) {
                                    new Handler(myLooper).post(() -> listener.onServerStartFailed(e));
                                }
                            }
                        } catch (SocketException e) {
                            Log.e(mTag, "Socket Exception");
                        } finally {
                            if (mServerSocket != null && !mServerSocket.isClosed()) {
                                mServerSocket.close();
                            }
                            getLooper().quitSafely();
                        }
                    });
                }
            }.start();
        }

So result data i post to listener via Binder

  //POST MY DATA TO BINDER VIA HANDLE LOOPER AND LISTENER       
 new Handler(myLooper).post(() -> listener.onReceive(receiveData,datagramPacket.getAddress()));

See my listener:

@NonNull
private UdpServerService.UdpServerListener getUdpServerServiceListener() {

    if (mUdpServerServiceListener == null) {
        mUdpServerServiceListener = new UdpServerService.UdpServerListener() {

            @Override
            public void onReceive(final byte[] bytes, final InetAddress inetAddress) {
                if (mSocketListener != null && mListenerLooper != null) {

                    //TRY TO RECEIVW MY DATA HERE
                }
            }

        };
    }
    return mUdpServerServiceListener;
}

See my service connection class with binder

private class MyServiceConnection implements ServiceConnection {

        UdpServerService.UdpServerBinder binder;

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            if (service instanceof UdpServerService.UdpServerBinder && mServerState == SERVER_STARTED) {
                binder = (UdpServerService.UdpServerBinder) service;
                binder.setListener(getUdpServerServiceListener());
                binder.startServer();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            //do something on disconnect
        }

So, it all works greate but in old devices with version 5 and 6 Android.

But in my GalaxyS7, or in My Asus Zenfone 3

with Android 7 application freezes

and does not respond user touch until it is not stopped.

Maybe triggered some limiting mechanism, but I do not know anything about it.

maybe wrong build.gradle see it

    apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'

apply plugin: 'idea'

android {
    compileSdkVersion 26

    defaultConfig {
        minSdkVersion 19
        targetSdkVersion 26
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        useLibrary 'org.apache.http.legacy'
    }

    buildTypes {

        debug {
            minifyEnabled false
            debuggable true
            signingConfig signingConfigs.debug
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }

        release {
            minifyEnabled true
            debuggable false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
        compileOptions {
            sourceCompatibility JavaVersion.VERSION_1_8
            targetCompatibility JavaVersion.VERSION_1_8
        }

    }
    packagingOptions{
        exclude 'META-INF/rxjava.properties'
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])

    implementation 'com.android.support:appcompat-v7:26.1.0'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.1'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
    //gson parser
    implementation 'com.google.code.gson:gson:2.8.0'
    //kotlin
    compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"

    // rxjava
    implementation  'io.reactivex:rxjava:1.1.6'
    implementation  'io.reactivex:rxandroid:1.2.1'
    implementation  'com.artemzin.rxjava:proguard-rules:1.1.0.0'

    compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
    compile 'io.reactivex.rxjava2:rxjava:2.0.8'

    //help to avoid  memory leaks
    implementation 'com.badoo.mobile:android-weak-handler:1.0'

    //guava for Android:
    implementation 'com.google.guava:guava:23.6-android'

}

kotlin {
    experimental {
        coroutines "enable"
    }
}

Solution

  • My solution is make this code simple, just work receive data in simple Thread, and post its data in the same thread:

     void startServer() {
                mStarted = true;
                mWakeLock.acquire(10 * 60 * 1000L /*10 minutes*/);
    
                new Thread(() -> {
                    try {
                        byte[] data = new byte[8 * 1024];//bucketful with fix size
                        InetAddress address = BnjUtils.getLocalIpAddress();
    
                        DatagramPacket datagramPacket = new DatagramPacket(data, data.length);
                        mServerSocket = new DatagramSocket(0, address);
    
                        final InetAddress localAddress = ((InetSocketAddress) mServerSocket.getLocalSocketAddress()).getAddress();
                        final int port = mServerSocket.getLocalPort();
                        mListener.onServerCreated(localAddress, port);
    
                        while (mStarted) {
                            try {
    
                                mServerSocket.receive(datagramPacket); // blocks until something is received
                                /*
                                 * Send bytes to app module.
                                 */
                                byte[] receiveData = new byte[datagramPacket.getLength()];
    
                                System.arraycopy(datagramPacket.getData(), datagramPacket.getOffset(), receiveData, 0, datagramPacket.getLength());
                                mListener.onReceive(receiveData, datagramPacket.getAddress());
    
                            } catch (IOException e) {
                                mListener.onServerStartFailed(e);
                            }
                        }
                    } catch (SocketException e) {
                        Log.e(mTag, "Socket Exception");
                    } finally {
                        if (mServerSocket != null && !mServerSocket.isClosed()) {
                            mServerSocket.close();
                        }
                    }
                }).start();
            }
    

    So now, works without freeze.