我正在构建一个远程服务和一个客户端应用程序,目标是在Nexus 6P设备上执行API 24。我有一个在启动时自动启动的远程服务。以下是代码片段:
远程服务清单
远程服务
远程广播接收器。
远程活动(Android Studio 坚持要有一个 Activity)。
我随后有一个单独的项目,实现在不同包中的客户端活动,试图绑定到远程服务。以下是代码片段:
客户端清单
客户活动
“isServiceRunning”函数返回true,因此我知道a.b.c.MyService正在运行。bindService函数似乎成功(Logcat中没有错误),但onServiceConnected回调从未执行。
我该如何在Android目标SDK 24中从x.y.z.ClientActivity绑定到a.b.c.Myservice?
谢谢!
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="a.b.c">
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<receiver
android:name=".MyBroadcastReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<service android:name=".MyService" >
<intent-filter>
<action android:name="a.b.c.MY_INTENT" />
</intent-filter>
</service>
<activity android:name=".MyActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>
远程服务
package a.b.c;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
public class MyService extends Service
{
@Override
public IBinder onBind(Intent intent) {
return null;
// EDIT: see StackOverflow answers/comments below:
// Returning an IBinder here solves the problem.
// e.g. "return myMessenger.getBinder()" where myMessenger
// is an instance of Android's Messenger class.
}
@Override
public void onCreate() {
super.onCreate();
}
}
远程广播接收器。
package a.b.c;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
Intent serviceIntent = new Intent(context, MyService.class);
context.startService(serviceIntent);
}
}
}
远程活动(Android Studio 坚持要有一个 Activity)。
package a.b.c;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
public class MyActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_activity);
}
}
我随后有一个单独的项目,实现在不同包中的客户端活动,试图绑定到远程服务。以下是代码片段:
客户端清单
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="x.y.z">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".ClientActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>
客户活动
package x.y.z;
import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
public class ClientActivity extends AppCompatActivity
{
private final String TAG = "ClientActivity";
private ServiceConnection mMyServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d(TAG, "ServiceConnection onServiceConnected");
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.d(TAG, "ServiceConnection onServiceDisconnected");
}
};
private boolean isServiceRunning(String className) {
ActivityManager manager = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningServiceInfo serviceInfo : manager.getRunningServices(Integer.MAX_VALUE)) {
if (className.equals(serviceInfo.service.getClassName())) {
return true;
}
}
return false;
}
private void bindMyService() {
Intent intent = new Intent("a.b.c.MY_INTENT");
intent.setPackage("a.b.c");
bindService(intent, mMyServiceConnection, Context.BIND_AUTO_CREATE);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_client);
if (isServiceRunning("a.b.c.MyService")) {
bindMyService();
}
else {
Log.e(TAG, "Service is not running");
}
}
}
“isServiceRunning”函数返回true,因此我知道a.b.c.MyService正在运行。bindService函数似乎成功(Logcat中没有错误),但onServiceConnected回调从未执行。
我该如何在Android目标SDK 24中从x.y.z.ClientActivity绑定到a.b.c.Myservice?
谢谢!
intent.setPackage("a.b.c");
,然后该意图变得“明确”。Intent
是intent.setClassName("a.b.c", "a.b.c.MyService");
。在这种情况下,你明确地指定要实例化的组件(类)。如果你这样做了,就不需要在Intent
中指定ACTION,并且可以从<service>
声明中删除<intent-filter>
,因为它不再需要(<intent-filter>
仅用于隐式Intent
解析)。但是,如果您删除了<intent-filter>
,那么您将需要向<service>
声明添加android:exported="true"
,因为没有<intent-filter>
时... - David WasserService
将是私有的,不会对包名为“a.b.c”以外的应用程序可用。如果您提供一个<intent-filter>
,那么android:exported
的默认值将自动为true
,但是如果您不提供<intent-filter>
,则默认值为false
。希望这很清楚。 - David Wasser