我有一个Android应用程序,它指定了两个AIDL文件和一个服务。这个服务应该从另一个应用程序调用AIDL上定义的方法。我已经按照Android Documentation on AIDL实现了AIDL文件和服务(见下面的代码)。
然后,我创建了一个非常简单的客户端应用(如下所示)来绑定到服务并调用AIDL文件中定义的方法。然而,bindService总是返回false,并指出找不到Intent。以下是我尝试在客户端正确引用Intent的一些事情:
Intent intent = new Intent("a.b.c.service");
intent.setPackage("a.b.c");
---
Intent intent = new Intent("service");
intent.setPackage("a.b.c");
---
Intent intent = new Intent();
intent.setClassName("a.b.c", "a.b.c.services.MyService");
---
Intent intent = new Intent();
intent.setClassName("a.b.c.services", "a.b.c.services.MyService");
---
Intent intent = new Intent();
intent.setClassName("a.b.c", ".services.MyService");
---
Intent intent = new Intent();
intent.setAction("service");
intent.setPackage("a.b.c");
intent.setClassName("a.b.c", ".services.MyService");
---
Intent intent = new Intent();
intent.setAction("service");
intent.setClassName("a.b.c", ".services.MyService");
如果我从服务所在的同一应用程序尝试,我可以使用以下命令,它将正常工作:
Intent intent = new Intent(this, MyService.class);
但由于这是一个远程服务,我无法从客户端应用程序访问MyService类,因此无法找到任何使其工作的方法。
我想知道通过很多StackOverflow职位没有任何运气。
Android: Binding to a remote service如何使用AIDL远程服务来处理不同客户端的并发请求?Android Bind Service returns false every time
在这种情况下,我应该如何说明我的意图?
先谢了。
相关代码:
- I服务接口辅助工具**
package a.b.c;
import a.b.c.IServiceInterfaceGetStuffCallback;
interface IServiceInterface
{
void getStuff(String arg1, IServiceInterfaceGetStuffCallback callback);
}
- I服务接口获取内容回调**
package a.b.c;
interface IServiceInterfaceGetStuffCallback
{
void onGetStuffResponse(String arg1, boolean arg2, int arg3, int arg4);
}
a.b.c./services/MyService.java
public class MyService extends Service
{
private final MyService self = this;
private MyServiceHandler handler = null;
private final HandlerThread handlerThread = new HandlerThread("AidlServiceThread");
//Callbacks
private final ArrayList<IServiceInterfaceGetStuffCallback> getStuffCallbacks = new ArrayList<>();
private final int MY_SERVICE_GET_STUFF_MSG = 1;
public MyService()
{
}
@Override
public IBinder onBind(Intent intent)
{
// Handler Thread handling all callback methods
handlerThread.start();
handler = new MyServiceHandler(handlerThread.getLooper());
return mBinder;
}
IServiceInterface.Stub mBinder = new IServiceInterface.Stub()
{
@Override
public void getStuff(String arg1, IServiceInterfaceGetStuffCallback callback) throws RemoteException
{
//Register the callback internally
getStuffCallbacks.add(callback);
final int cbIndex = getStuffCallbacks.size() - 1;
getStuff((arg1, arg2, arg3, arg4) ->
{
MyServiceResponse response = new MyServiceResponse();
response.arg1 = arg1;
response.arg2 = arg2;
response.arg3 = arg3;
response.arg4 = arg4;
Message message = handler.obtainMessage();
message.arg1 = cbIndex;
message.obj = response;
message.what = MY_SERVICE_GET_STUFF_MSG;
handler.sendMessage(message);
});
}
};
private class MyServiceHandler extends Handler
{
int callbackIndex = 0;
MyServiceHandler (Looper looper)
{
super(looper);
}
@Override
public void handleMessage(Message msg)
{
callbackIndex = msg.arg1;
MyServiceHandler response = (MyServiceHandler)msg.obj;
switch (msg.what)
{
case MY_SERVICE_GET_STUFF_MSG:
{
try
{
getStuffCallbacks.get(callbackIndex).onGetStuffResponse(response.arg1, response.arg2, response.arg3, response.arg4);
}
catch (RemoteException e)
{
e.printStackTrace();
}
break;
}
default:
break;
}
}
}
private static class MyServiceResponse
{
public String arg1;
public boolean arg2;
public int arg3;
public int arg4;
}
}
- Android清单**
<?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.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
<permission
android:name="a.b.c.myservice"
android:protectionLevel="signature" />
<application
android:name=".MyApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme"
android:configChanges="orientation|screenSize|screenLayout|keyboardHidden|keyboard|colorMode|density|navigation|fontScale|layoutDirection|locale|mcc|mnc|smallestScreenSize|touchscreen|uiMode">
(...)
<service
android:name="a.b.c.services.MyService"
android:enabled="true"
android:exported="true"
android:permission="a.b.c.myservice">
<intent-filter>
<action android:name="a.b.c.myservice" />
</intent-filter>
</service>
</application>
</manifest>
Client app - MainActivity.java
public class MainActivity extends AppCompatActivity implements View.OnClickListener
{
private final String TAG = "aidltest";
MainActivity self = this;
IServiceInterface service = null;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.btn_get_stuff).setOnClickListener(this);
}
@Override
public void onClick(View view)
{
if (view.getId() == R.id.btn_get_stuff)
getStuff();
}
void getStuff()
{
Log.e(TAG, "getStuff invoked");
Intent intent = new Intent("a.b.c.myservice");
intent.setPackage("a.b.c");
boolean res = getApplicationContext().bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
Log.e(TAG, "Service binding result: " + res);
}
private ServiceConnection serviceConnection = new ServiceConnection()
{
public void onServiceConnected(ComponentName className, IBinder service)
{
// This is called when the connection with the service has been
// established, giving us the service object we can use to
// interact with the service. We are communicating with our
// service through an IDL interface, so get a client-side
// representation of that from the raw service object.
self.service = IServiceInterface.Stub.asInterface(service);
Log.e(TAG, "ServiceInterface attached");
}
public void onServiceDisconnected(ComponentName className)
{
service = null;
Log.e(TAG, "Service disconnected");
}
};
}
1条答案
按热度按时间myzjeezk1#
以下更改对我有效:
1.按如下方式调整清单:
1.运行
adb shell pm list packages
并获取您声明服务的apk的软件包id,这是在步骤3中构建Intent所需的。1.调整
getStuff
方法,如下所示: