Правильный способ доступа к привязанной службе - PullRequest
0 голосов
/ 13 июля 2020

В моем приложении есть следующий манифест:

<manifest ...>
    <application android:name=".MyApplication">
        <activity android:name=".MainActivity">
            ...
        </activity>
        <service
            android:name=".MyService"
            android:enabled="true" />
    </application>
</manifest>

В методах моих пользовательских MyApplication и MainActivity я хочу использовать MyService (и мне не нужно IBinder из-за к MyService будет автоматически привязан, потому что это android:enabled="true" в манифесте). В MainActivity я мог бы использовать интерфейс ServiceConnection, но что я должен использовать в MyApplication для получения экземпляра MyService?

И, возможно, есть какой-то способ получить доступ к сервису напрямую, например MyApplication.getService(MyService.class) ?

РЕДАКТИРОВАТЬ

Думаю, я понял концепцию.

В MyService я должен определить класс Binder, чтобы сделать служба "boundable":

public final class MyService extends Service {
    public final class Binder extends android.os.Binder {
        public MyService getService() {
            return MyService.this;
        }
    }
    private MyService.Binder binder = new MyService.Binder();

    public MyService() {
        super();
    }

    @Override
    public IBinder onBind (Intent intent) {
        return this.binder;
    }

    @Override
    public void onStart() {
        super.onStart();
        // do stuff...
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // handle command...
        return super.onStartCommand(intent, flags, startId);
    }
}

И использовать этот класс в MyApplication в ServiceConnection:

public class MyApplication extends Application {
    private static MyService myService = null;

    private static final ServiceConnection serviceConnection = new ServiceConnection() {
        public void onServiceConnected(ComponentName name, IBinder service) {
            MyService.Binder binder = (MyService.Binder) service;
            MyApplication.myService = binder.getService();
        }
        public void onServiceDisconnected(ComponentName name) {
            MyApplication.myService = null;
        }
    };

    @Override
    public void onCreate() {
        super.onCreate();
        bindService(new Intent(getApplicationContext(), MyService.class), MyApplication.serviceConnection, BIND_AUTO_CREATE);
    }

    public static MyService getMyService() {
        return MyApplication.myService;
    }
}

И теперь я могу получить доступ к MyService из любого приложения через MyApplication.getMyService().

НО!

Если я наследую MyService, например, от androidx.media.MediaBrowserServiceCompat, это намного веселее! В этом случае я не могу использовать метод @Override onBind(), потому что он каким-то образом используется MediaBrowserServiceCompat. И я получаю NullPointerException, если я делаю:

@Override
public IBinder onBind (Intent intent) {
    return this.binder; // <<< here!
}

:

--------- beginning of crash
2020-07-13 23:43:51.652 13819-13819/com.exampler.myapplication E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.exampler.myapplication, PID: 13819
    java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.lang.String.equals(java.lang.Object)' on a null object reference
        at android.os.Binder.queryLocalInterface(Binder.java:309)
        at android.service.media.IMediaBrowserService$Stub.asInterface(IMediaBrowserService.java:31)
        at android.media.browse.MediaBrowser$MediaServiceConnection$1.run(MediaBrowser.java:959)
        at android.media.browse.MediaBrowser$MediaServiceConnection.postOrRun(MediaBrowser.java:1020)
        at android.media.browse.MediaBrowser$MediaServiceConnection.onServiceConnected(MediaBrowser.java:943)
        at android.app.LoadedApk$ServiceDispatcher.doConnected(LoadedApk.java:1453)
        at android.app.LoadedApk$ServiceDispatcher$RunConnection.run(LoadedApk.java:1481)
        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:6119)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)

И что мне делать в этом случае, я не знаю: (

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...