2015-02-06 85 views
10

我每次聲明和運行兩個服務時遇到下面的binder.proxy異常。一個服務運行在不同的進程中(私有應用程序),另一個服務運行與My Application在運行Binder實現的(默認應用程序進程)中相同的進程。獲取java.lang.ClassCastException:android.os.BinderProxy每次我聲明並運行兩個服務

的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 service android.os.BinderProxy error

java.lang.ClassCastException: android.os.BinderProxy cannot be cast to LocalBinder

但在我的情況: 我從MainApplication結合SecondService並且都在同一個進程(即默認應用程序)運行。仍然我面臨binderProxy異常在SecondService,而我的FirstService運行在一個單獨的過程中,我甚至沒有綁定。

請幫助我解決這種情況,並建議我一個儘可能好的方法,以便我可以在沒有任何崩潰的情況下實現相同的方案。

+0

您是否確認應用程序和服務在相同的過程中運行? – pskink 2015-02-06 11:44:51

+0

我沒有在android設備監視器中明確驗證它,但通過日誌,我發現我在第二個服務中崩潰,它應該在與應用程序相同的進程中運行,因爲我沒有爲它分配任何新的進程表現。 – 2015-02-07 15:39:08

+1

通常,如果一個IBinder是一個BinderProxy,這意味着另一方正在不同的過程中運行,所以... – pskink 2015-02-07 15:42:11

回答

6

發現正在做一些研究和調試後一個答案,

如果我們創建和綁定到MainApplication類中的任何服務(然後服務被綁定到整個的ApplicationContext或BaseContext),如果同一應用程序中包含有綁定等服務到活動具體語境(S),

//Declared in MainApplication 
@Override 
public void onServiceConnected(ComponentName className, IBinder service) { 
       mBinder = (LocalBinder) service; 
    } 

在OnServiceConnected(),我們將獲得粘合劑對象既服務(SecondService開始在MainApplication(與BaseContext註冊將得到當地binderObject)類和FirstService開始MainActivity(將得到android.os.binderProxyObject因此導致ClassCastException)。

  • 所以,修復這個問題人們必須啓動所有從任何活動上下文應用 服務,而不是使用任何全球 應用程序上下文。也此問題是 進程

  • 因此,我提出既SecondService和FirstService成MainActivity 背景信息,其解決了該問題的獨立

MainActivity.java

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); 

     } 
    } 
+0

「來解決這個問題,人們必須從任何活動上下文啓動所有應用程序服務,而不是使用任何全局應用程序上下文」您能解釋*爲什麼*是這種情況?只要應用程序和活動環境生活在相同的過程中,那麼應該與哪個服務綁定就無關緊要。 – tir38 2018-02-20 21:26:48

18

就遇到了這個問題(本地服務返回BinderProxy),想發佈的東西我已經找到,因爲我找到了這個網頁,而試圖調試。簡短版本作爲一個句子運行:啓動一個遠程服務在一個新的進程中創建你的Application類的第二個實例,然後它嘗試綁定到由原始Application實例啓動的本地服務,就好像它是本地服務一樣,但是由於服務在原始進程中運行,因此跨進程進行綁定,您將獲得BinderProxy而不是預期的Binder類。

關於Android服務,有幾點需要注意。每個服務都有一個指定的進程運行。如果你沒有在Android Manifest中分配一個進程,它將運行在默認進程(運行應用程序,活動等的進程)中。不提供進程名稱並不意味着它將在與綁定/啓動服務相同的進程中運行該服務。

假設我有一個MyApplication類,它試圖在啓動時綁定到兩個服務:一個服務在默認進程中運行(我們稱之爲LocalService),一個運行在單獨進程(RemoteService)中。

用戶啓動我的應用程序,該應用程序在默認進程中創建MyApplication實例。此實例然後嘗試綁定到LocalService。 Android在默認過程中創建LocalService,並將LocalService的Binder類返回到應用程序(mBinder = (LocalBinder) service;)。這很好,我們已經成功綁定到LocalService。

接下來,應用程序嘗試綁定到RemoteService。 Android使用您在Android Manifest中提供的名稱創建一個新流程。但是,在它可以創建RemoteService之前,需要爲要運行的服務創建一個應用程序。它在遠程進程中創建一個新的MyApplication實例並啓動它。

但是,在獨立進程中運行的新MyApplication實例嘗試在啓動期間綁定到LocalService。因爲LocalService在默認進程中運行,所以這是一個跨進程綁定,但MyApplication希望這是一個進程內綁定。 Android返回一個BinderProxy,第二個MyApplication實例試圖將其轉換爲LocalBinder並崩潰。有趣的部分是它崩潰在一個不同的過程,所以你的應用程序和活動可以實際上繼續運行。您將永遠無法綁定到遠程服務。

如果要使用Application上下文綁定到本地服務並使用遠程服務,則需要處理這一事實,即Android將在啓動遠程服務時在遠程進程中創建另一個應用程序。我沒有試過這樣做(我只是把我的遠程服務作爲一個本地服務),但是你可以在應用程序創建時檢查進程的名稱,如果它不是默認進程,可以不進行綁定。