尝试与另一个应用程序进行 IPC 时,客户端应用程序中的 bindService() 失败
bindService() in client app fails when trying to do IPC with another app
我想获得一些使用 AIDL 的 android IPC 的经验。我想看看是否可以在两个不同的 android 应用程序之间进行通信。
我的问题是,在第二个应用程序中调用 bindService
与第一个应用程序的 FactorialService
通信时,服务总是失败。我的第一个应用 activity MainActivity
尝试调用 bindService
时总是记录 bindService
returns false
的事实。另外,第二个应用程序(客户端应用程序)的 MainActivity
(实现 ServiceConnection
)永远不会调用其回调方法 onServiceConnected
。
因此,在 第一个应用程序 中运行名为 FactorialService
的服务
我定义了一个
接口,IFactorialService.aidl
:
package com.simonlbc.factorialcommon;
import com.simonlbc.factorialcommon.FactorialRequest;
import com.simonlbc.factorialcommon.FactorialResponse;
interface IFactorialService {
FactorialResponse fact(in FactorialRequest r);
}
FactorialRequest
包含一个输入数字(比如 n)。 fact
returns n!
以及其他信息。
在同一个应用程序中我创建了一个 class IFactorialServiceImplem
实现该 aidl 接口。
package com.example.simonlbc.factorialservice;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.SystemClock;
import com.simonlbc.factorialcommon.FactorialResponse;
import com.simonlbc.factorialcommon.FactorialRequest;
public class IFactorialServiceImplem extends com.simonlbc.factorialcommon.IFactorialService.Stub {
public long recursiveFact(int n) {
if (n < 0)
throw new IllegalArgumentException("input fa");
if (n == 1 || n == 0)
return 1;
else {
return n * recursiveFact(n-1);
}
}
public long iterativeFact(int n) {
long res = 1;
for (int i = 1; i <= n; i++)
res *= i;
return res;
}
public FactorialResponse fact(FactorialRequest r) {
long timeInMillis = SystemClock.uptimeMillis();
long result = 0;
switch(r.getChoice()) {
case RECURSIVE:
result = recursiveFact(r.getInNb());
break;
case ITERATIVE:
result = iterativeFact(r.getInNb());
}
timeInMillis = SystemClock.uptimeMillis() - timeInMillis;
return new FactorialResponse(result, timeInMillis);
}
}
然后我创建了一个 Service
,用于将 IFactorialService
实例传达给可能的客户:
package com.example.simonlbc.factorialservice;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
import com.simonlbc.factorialcommon.IFactorialService;
public class FactorialService extends Service {
private IFactorialServiceImplem s = null;
private static final String TAG = "FactorialService";
@Override
public void onCreate() {
super.onCreate();
s = new IFactorialServiceImplem();
Log.d(TAG, "onCreate'd");
}
@Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "onBind()'d");
return this.s;
}
@Override
public boolean onUnbind(Intent intent) {
Log.d(TAG, "onUnbind()'d");
return super.onUnbind(intent);
}
@Override
public void onDestroy() {
Log.d(TAG, "onDestroy()'d");
s = null;
super.onDestroy();
}
}
- 第一个 "service" 应用程序的清单如下:
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<service
android:name=".FactorialService">
<!--
android:enabled="true"
android:exported="true"
android:process=":remote"
-->
<intent-filter>
<action android:name="com.example.simonlbc.factorialservice.FactorialService" />
</intent-filter>
</service>
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
第一个应用程序包含一个启动器 activity,它可以简单地启动服务:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_service);
curPackage = getString(R.string.packageService);
MainActivity.this.startService(
new Intent()
.setAction(curPackage + ".FactorialService")
.setPackage(curPackage)
);
}
我的第二个应用程序的启动器activity例如:
public class MainActivity extends Activity implements View.OnClickListener, ServiceConnection
我想要 MainActivity
第二个应用程序
与第一个应用程序通信 IFactorialService
。在onResume我
尝试绑定第一个应用程序的服务:
@Override
protected void onResume() {
super.onResume();
Intent i = new Intent();
i.setAction("com.example.simonlbc.factorialservice.FactorialService");
i.setPackage("com.example.simonlbc");
if (!super.bindService(i, this, BIND_AUTO_CREATE))
Log.w(TAG, "Failed to bind our service!!!");
}
但似乎bindService
失败了。事实上,每次我暂停应用程序并 return 到它,或启动它。显示"Failed to bind our service!!!"。
请注意,这两个应用共享一个 Android 库模块,其中包含所需 aidl 文件的定义。
你看到任何能让 bindService()
工作的东西吗?
为什么要使用 super.bindservice()
?相反,你能试试这个 getApplicationContext().bindservice()
此外,如果这也不起作用,请尝试对您的代码进行以下修改:
Intent i = new Intent("com.example.simonlbc.factorialservice.FactorialService");
if(getApplicationContext().startService(i) != null){
if (!getApplicationContext().bindService(i, serviceConnection, 0))
Log.w(TAG, "Failed to bind our service!!!");
}
其中 seriveConnection
是服务连接的对象(我不喜欢将 this
用于 ServiceConnection
)。此外,您的服务应该设置正确的 Action
,否则它不会启动
我想获得一些使用 AIDL 的 android IPC 的经验。我想看看是否可以在两个不同的 android 应用程序之间进行通信。
我的问题是,在第二个应用程序中调用 bindService
与第一个应用程序的 FactorialService
通信时,服务总是失败。我的第一个应用 activity MainActivity
尝试调用 bindService
时总是记录 bindService
returns false
的事实。另外,第二个应用程序(客户端应用程序)的 MainActivity
(实现 ServiceConnection
)永远不会调用其回调方法 onServiceConnected
。
因此,在 第一个应用程序 中运行名为 FactorialService
我定义了一个
接口,IFactorialService.aidl
:package com.simonlbc.factorialcommon; import com.simonlbc.factorialcommon.FactorialRequest; import com.simonlbc.factorialcommon.FactorialResponse; interface IFactorialService { FactorialResponse fact(in FactorialRequest r); }
FactorialRequest
包含一个输入数字(比如 n)。 fact
returns n!
以及其他信息。
在同一个应用程序中我创建了一个 class
IFactorialServiceImplem
实现该 aidl 接口。package com.example.simonlbc.factorialservice; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.os.SystemClock; import com.simonlbc.factorialcommon.FactorialResponse; import com.simonlbc.factorialcommon.FactorialRequest; public class IFactorialServiceImplem extends com.simonlbc.factorialcommon.IFactorialService.Stub { public long recursiveFact(int n) { if (n < 0) throw new IllegalArgumentException("input fa"); if (n == 1 || n == 0) return 1; else { return n * recursiveFact(n-1); } } public long iterativeFact(int n) { long res = 1; for (int i = 1; i <= n; i++) res *= i; return res; } public FactorialResponse fact(FactorialRequest r) { long timeInMillis = SystemClock.uptimeMillis(); long result = 0; switch(r.getChoice()) { case RECURSIVE: result = recursiveFact(r.getInNb()); break; case ITERATIVE: result = iterativeFact(r.getInNb()); } timeInMillis = SystemClock.uptimeMillis() - timeInMillis; return new FactorialResponse(result, timeInMillis); } }
然后我创建了一个
Service
,用于将IFactorialService
实例传达给可能的客户:package com.example.simonlbc.factorialservice; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.util.Log; import com.simonlbc.factorialcommon.IFactorialService; public class FactorialService extends Service { private IFactorialServiceImplem s = null; private static final String TAG = "FactorialService"; @Override public void onCreate() { super.onCreate(); s = new IFactorialServiceImplem(); Log.d(TAG, "onCreate'd"); } @Override public IBinder onBind(Intent intent) { Log.d(TAG, "onBind()'d"); return this.s; } @Override public boolean onUnbind(Intent intent) { Log.d(TAG, "onUnbind()'d"); return super.onUnbind(intent); } @Override public void onDestroy() { Log.d(TAG, "onDestroy()'d"); s = null; super.onDestroy(); } }
- 第一个 "service" 应用程序的清单如下:
<application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"> <service android:name=".FactorialService"> <!-- android:enabled="true" android:exported="true" android:process=":remote" --> <intent-filter> <action android:name="com.example.simonlbc.factorialservice.FactorialService" /> </intent-filter> </service> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application>
第一个应用程序包含一个启动器 activity,它可以简单地启动服务:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_service); curPackage = getString(R.string.packageService); MainActivity.this.startService( new Intent() .setAction(curPackage + ".FactorialService") .setPackage(curPackage) ); }
我的第二个应用程序的启动器activity例如:
public class MainActivity extends Activity implements View.OnClickListener, ServiceConnection
我想要
MainActivity
第二个应用程序
与第一个应用程序通信IFactorialService
。在onResume我 尝试绑定第一个应用程序的服务:@Override protected void onResume() { super.onResume(); Intent i = new Intent(); i.setAction("com.example.simonlbc.factorialservice.FactorialService"); i.setPackage("com.example.simonlbc"); if (!super.bindService(i, this, BIND_AUTO_CREATE)) Log.w(TAG, "Failed to bind our service!!!"); }
但似乎bindService
失败了。事实上,每次我暂停应用程序并 return 到它,或启动它。显示"Failed to bind our service!!!"。
请注意,这两个应用共享一个 Android 库模块,其中包含所需 aidl 文件的定义。
你看到任何能让 bindService()
工作的东西吗?
为什么要使用 super.bindservice()
?相反,你能试试这个 getApplicationContext().bindservice()
此外,如果这也不起作用,请尝试对您的代码进行以下修改:
Intent i = new Intent("com.example.simonlbc.factorialservice.FactorialService");
if(getApplicationContext().startService(i) != null){
if (!getApplicationContext().bindService(i, serviceConnection, 0))
Log.w(TAG, "Failed to bind our service!!!");
}
其中 seriveConnection
是服务连接的对象(我不喜欢将 this
用于 ServiceConnection
)。此外,您的服务应该设置正确的 Action
,否则它不会启动