В моем приложении есть следующий манифест:
<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)
И что мне делать в этом случае, я не знаю: (