在 onCreate() 中的 bindService() 之后不调用 onBind() 和 onServiceConnected()
onBind() and onServiceConnected() are not called after bindService() in onCreate()
我遵循了 Google 的开发人员服务文档站点上的教程,但可能遗漏了一些内容。我能够正确地启动和停止服务,但现在我正在尝试绑定到服务,我收到 NullPointerException,因为在 bindService() 之后没有调用 onBind() 和 onServiceConnected()。我在 Whosebug 上阅读了 10 多个问题,其中 none 个问题有所帮助。
我的清单的一部分:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.waveplayer">
<application
<service android:name="com.example.waveplayer.ServiceMain"
android:exported="false"
android:description="@string/service_description"
android:enabled="true"/>
</application>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
</manifest>
用于在 OnCreate() 上启动服务的代码:
Intent intent = new Intent(getApplicationContext(), ServiceMain.class);
startService(intent);
getApplicationContext().bindService(intent, connection, BIND_AUTO_CREATE);
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName className, IBinder service) {
ServiceMain.ServiceMainBinder binder = (ServiceMain.ServiceMainBinder) service;
serviceMain = binder.getService();
serviceMainBound = true;
}
@Override
public void onServiceDisconnected(ComponentName arg0) {
serviceMainBound = false;
}
};
还有我的服务代码:
private Looper serviceMainLooper;
private ServiceMainHandler serviceMainHandler;
private final IBinder serviceMainBinder = new ServiceMainBinder();
private final class ServiceMainHandler extends Handler {
public ServiceMainHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
}
}
@Override
public void onCreate() {
super.onCreate();
HandlerThread thread = new HandlerThread("ServiceMainStartArguments",
Process.THREAD_PRIORITY_BACKGROUND);
thread.start();
serviceMainLooper = thread.getLooper();
serviceMainHandler = new ServiceMainHandler(serviceMainLooper);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
// For each start request, send a message to start a job and deliver the
// start ID so we know which request we're stopping when we finish the job
Message msg = serviceMainHandler.obtainMessage();
msg.arg1 = startId;
serviceMainHandler.sendMessage(msg);
Intent notificationIntent = new Intent(this, ServiceMain.class);
PendingIntent pendingIntent =
PendingIntent.getActivity(this, 0, notificationIntent, 0);
String CHANNEL_ID = "ServiceMain";
RemoteViews notificationLayout = new RemoteViews(getPackageName(), R.layout.notification_song_pane);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
.setPriority(NotificationCompat.PRIORITY_MAX)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setStyle(new NotificationCompat.DecoratedCustomViewStyle())
.setCustomContentView(notificationLayout)
.setContentIntent(pendingIntent);
startForeground(CHANNEL_ID.hashCode(), builder.build());
return START_STICKY;
}
public class ServiceMainBinder extends Binder {
ServiceMain getService() {
return ServiceMain.this;
}
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return serviceMainBinder;
}
@Override
public void onDestroy() {
saveFile();
Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show();
}
事实证明,在 UI 线程清除 Activity 中的代码之前,服务不会被创建,因此在 onStart()
之前我无法访问它我的方法Activity。这就是 onServiceConnected()
回调方法的用途。此时服务已创建,Activity 可以访问该服务。
我遵循了 Google 的开发人员服务文档站点上的教程,但可能遗漏了一些内容。我能够正确地启动和停止服务,但现在我正在尝试绑定到服务,我收到 NullPointerException,因为在 bindService() 之后没有调用 onBind() 和 onServiceConnected()。我在 Whosebug 上阅读了 10 多个问题,其中 none 个问题有所帮助。
我的清单的一部分:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.waveplayer">
<application
<service android:name="com.example.waveplayer.ServiceMain"
android:exported="false"
android:description="@string/service_description"
android:enabled="true"/>
</application>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
</manifest>
用于在 OnCreate() 上启动服务的代码:
Intent intent = new Intent(getApplicationContext(), ServiceMain.class);
startService(intent);
getApplicationContext().bindService(intent, connection, BIND_AUTO_CREATE);
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName className, IBinder service) {
ServiceMain.ServiceMainBinder binder = (ServiceMain.ServiceMainBinder) service;
serviceMain = binder.getService();
serviceMainBound = true;
}
@Override
public void onServiceDisconnected(ComponentName arg0) {
serviceMainBound = false;
}
};
还有我的服务代码:
private Looper serviceMainLooper;
private ServiceMainHandler serviceMainHandler;
private final IBinder serviceMainBinder = new ServiceMainBinder();
private final class ServiceMainHandler extends Handler {
public ServiceMainHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
}
}
@Override
public void onCreate() {
super.onCreate();
HandlerThread thread = new HandlerThread("ServiceMainStartArguments",
Process.THREAD_PRIORITY_BACKGROUND);
thread.start();
serviceMainLooper = thread.getLooper();
serviceMainHandler = new ServiceMainHandler(serviceMainLooper);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
// For each start request, send a message to start a job and deliver the
// start ID so we know which request we're stopping when we finish the job
Message msg = serviceMainHandler.obtainMessage();
msg.arg1 = startId;
serviceMainHandler.sendMessage(msg);
Intent notificationIntent = new Intent(this, ServiceMain.class);
PendingIntent pendingIntent =
PendingIntent.getActivity(this, 0, notificationIntent, 0);
String CHANNEL_ID = "ServiceMain";
RemoteViews notificationLayout = new RemoteViews(getPackageName(), R.layout.notification_song_pane);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
.setPriority(NotificationCompat.PRIORITY_MAX)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setStyle(new NotificationCompat.DecoratedCustomViewStyle())
.setCustomContentView(notificationLayout)
.setContentIntent(pendingIntent);
startForeground(CHANNEL_ID.hashCode(), builder.build());
return START_STICKY;
}
public class ServiceMainBinder extends Binder {
ServiceMain getService() {
return ServiceMain.this;
}
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return serviceMainBinder;
}
@Override
public void onDestroy() {
saveFile();
Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show();
}
事实证明,在 UI 线程清除 Activity 中的代码之前,服务不会被创建,因此在 onStart()
之前我无法访问它我的方法Activity。这就是 onServiceConnected()
回调方法的用途。此时服务已创建,Activity 可以访问该服务。