每次我声明并运行两个服务时,我都遇到以下binder.proxy异常。一个服务在不同的进程中运行(专用于应用程序),另一项服务在与我的应用程序在同一应用程序(默认应用程序进程)中使用Binder实现运行的进程中运行。
AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.service.check" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="21" /> <application android:name="com.service.check.MainApplication" android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <service android:name="com.service.check.SecondService" android:exported="false"/> <service android:name="com.service.check.FirstService" android:process=":newProcess" > </service> </application> </manifest>
我在MainActivity上的第一个按钮上单击启动我的第一个服务:
MainActivity.java
public class MainActivity extends ActionBarActivity implements OnClickListener { private Button mLanchServiceBtn; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mLanchServiceBtn=(Button) findViewById(R.id.launch_btn); mLanchServiceBtn.setOnClickListener(this); } @Override public void onClick(View v) { //Starting first service Intent launch=new Intent(this,FirstService.class); startService(launch); } }
与MainApplication类中的第二项服务相同。
MainApplication.java
public class MainApplication extends Application { private SecondService.LocalBinder mBinder; private ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName className, IBinder service) { mBinder = (LocalBinder) service; } @Override public void onServiceDisconnected(ComponentName arg0) { } }; @Override public void onCreate() { super.onCreate(); //starting second service Intent launch=new Intent(this,SecondService.class); startService(launch); //Binding to it bindService(launch, mConnection, BIND_AUTO_CREATE); } }
FirstService.java
public class FirstService extends Service { @Override public IBinder onBind(Intent intent) { return null; } }
SecondService.java
public class SecondService extends Service{ //Service Containing Local Binder private LocalBinder mBinder=new LocalBinder(); @Override public IBinder onBind(Intent intent) { return mBinder; } class LocalBinder extends Binder{ public LocalBinder() { } } }
堆栈跟踪:
02-05 10:32:25.035: E/AndroidRuntime(1424): Process: com.service.check:newProcess, PID: 1424 02-05 10:32:25.035: E/AndroidRuntime(1424): java.lang.ClassCastException: android.os.BinderProxy cannot be cast to com.service.check.SecondService$LocalBinder 02-05 10:32:25.035: E/AndroidRuntime(1424): at com.service.check.MainApplication$1.onServiceConnected(MainApplication.java:23) 02-05 10:32:25.035: E/AndroidRuntime(1424): at android.app.LoadedApk$ServiceDispatcher.doConnected(LoadedApk.java:1101)
我引用了以下链接来整理问题,即如果我的活动和服务处于单独的流程中,则我们不应束缚自己的工作方式。
Android服务android.os.BinderProxy错误
java.lang.ClassCastException:android.os.BinderProxy无法转换为LocalBinder
但以我 为例 : 我从 MainApplication 绑定到 SecondService ,并且两者都在同一进程(即默认应用程序进程)中运行。仍然我在 SecondService中 面临binderProxy异常,并且我的 FirstService 在一个甚至没有绑定到的单独进程中运行。
请帮助我解决这种情况,并建议我一种最佳的方式,这样我就可以实现相同的方案而不会崩溃。
经过研究和调试后找到了答案,
如果我们创建任何服务并将其绑定到MainApplication类(然后将服务绑定到整个ApplicationContext或BaseContext),并且如果同一个应用程序包含绑定到特定于活动的上下文的其他服务,
//Declared in MainApplication @Override public void onServiceConnected(ComponentName className, IBinder service) { mBinder = (LocalBinder) service; }
在OnServiceConnected()中,我们将同时获取Services的绑定对象(在 MainApplication中 启动的SecondService(在BaseContext中注册)将获取本地bindObject)类和 FirstService 启动的MainActivity(将获取 android.os.binderProxyObject,从而导致ClassCastException )。
因此,要 解决* 此问题,必须从任何活动上下文而不是使用任何全局应用程序上下文启动所有应用程序服务。此外,此问题与 流程 无关 *
因此,我将SecondService和FirstService都移到了MainActivity Context中,从而解决了该问题。
private Button mLanchServiceBtn; private SecondService.LocalBinder mBinder; private ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName className, IBinder service) { mBinder = (LocalBinder) service; } @Override public void onServiceDisconnected(ComponentName arg0) { } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mLanchServiceBtn=(Button) findViewById(R.id.launch_btn); mLanchServiceBtn.setOnClickListener(this); //starting second service in activity Intent launch=new Intent(this,SecondService.class); startService(launch); //Binding to it bindService(launch, mConnection, BIND_AUTO_CREATE); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { int id = item.getItemId(); if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } @Override public void onClick(View v) { //Starting FirstService also from MainActivity Intent launch=new Intent(this,FirstService.class); startService(launch); } }