2011-08-12 74 views
2

我對Android編程和Java一般都很陌生,但作爲一個系統級的C編碼器我有豐富的經驗。我想創建一個API或庫,可供我計劃開發的一套Android應用程序使用,並且經過大量研究後,確定綁定服務是Android的一種方式(我通常會創建一個.so或者.dll)。如果這個假設是錯誤的,那麼我的整個問題很可能就沒有意義了。bindService部隊關閉

無論如何,我在一個項目中創建了我的服務框架,並在另一個項目中創建了一個活動來測試服務。我調用Toast來調用服務的handleMessage()方法,以查看它是否正在工作,然後向我的活動添加兩個按鈕:一個用於綁定服務,另一個用於解除綁定。由於無法看到我的服務,因此無法運行我的活動大約一個小時後,我想出瞭如何讓Eclipse從活動中查看服務的源代碼,並認爲我很順利。然後我開始了這個活動。

一切看起來不錯。兩個按鈕,一個綁定,一個解除綁定。但是,當我按下綁定按鈕時,它強制關閉應用程序。我使用調試器來查看發生了什麼,並強制關閉我的活動中的bindService()調用。當然,bindService()調用是從另一個在同一行上創建一個新Intent()的示例中複製的,所以我分離出了​​兩行代碼,它是真的當我嘗試創建Intent 。

這裏是我的活動代碼:

package net.william.android.myAPI.tester; 

import net.william.android.myAPI.MyApiService; 
import android.app.Activity; 
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.view.View; 
import android.widget.Toast; 

public class MyApiTester extends Activity 
{ 
    boolean mIsBound = false; 

    private ServiceConnection mConnection = new ServiceConnection() 
    { 
     public void onServiceConnected(ComponentName className, IBinder service) 
     { 
      Toast.makeText(FaceClientTester.this, "Remote Service Connected", Toast.LENGTH_SHORT).show(); 
     } 

     public void onServiceDisconnected(ComponentName className) 
     { 
      Toast.makeText(FaceClientTester.this, "Remote Service Disconnected", Toast.LENGTH_SHORT).show(); 
     } 
    }; 

    public void doBindService(View view) 
    { 
     if (!mIsBound) 
     { 
      Toast.makeText(this, "Binding Service", Toast.LENGTH_SHORT).show(); 
      Intent myIntent = new Intent(MyApiTester.this, MyApiService.class); 
      bindService(myIntent, mConnection, Context.BIND_AUTO_CREATE); 
      mIsBound = true; 
     } 
    } 

    public void doUnbindService(View view) 
    { 
     if (mIsBound) 
     { 
      unbindService(mConnection); 
      mIsBound = false; 
      Toast.makeText(this, "Service Unbound", Toast.LENGTH_SHORT).show(); 
     } 
    } 

    @Override 
    public void onCreate(Bundle savedInstanceState) 
    { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 
     return; 
    } 
} 

這是我的服務代碼:

package net.william.android.myAPI 

import android.app.Service; 
import android.content.Intent; 
import android.os.Handler; 
import android.os.IBinder; 
import android.os.Message; 
import android.os.Messenger; 
import android.widget.Toast; 

public class MyApiService extends Service 
{ 
    static final int API_FN_1 = 101; 
    static final int API_FN_2 = 102; 

    class MyApiHandler extends Handler 
    { 
     @Override 
     public void handleMessage(Message msg) 
     { 
      switch (msg.what) 
      { 
       case API_FN_1: 
        ApiFn1(); 
        break; 
       case API_FN_2: 
        ApiFn2(); 
        break; 
       default: 
        super.handleMessage(msg); 
        break; 
      } 
     } 
    } 

    final Messenger myMessenger = new Messenger(new MyApiHandler()); 

    @Override 
    public void onCreate() 
    { 
     Toast.makeText(this, "Service Started", Toast.LENGTH_SHORT).show(); 
    } 

    @Override 
    public void onDestroy() 
    { 
     Toast.makeText(this, "Service Stopped", Toast.LENGTH_SHORT).show(); 
    } 

    @Override 
    public IBinder onBind(Intent intent) 
    { 
     Toast.makeText(this, "Service Bound", Toast.LENGTH_SHORT).show(); 
     return myMessenger.getBinder(); 
    } 

    private void ApiFn1() 
    { 
     Toast.makeText(this, "API Function 1", Toast.LENGTH_SHORT).show(); 
     return; 
    } 

    private void ApiFn2() 
    { 
     Toast.makeText(this, "API Function 2", Toast.LENGTH_SHORT).show(); 
     return; 
    } 
} 

我改變了一些東西的名字,但是這是真的肉我代碼到目前爲止。只是一堆Toast的電話,以便我希望能看到事情正在發揮作用。

我在主題上找到的所有教程都完全忽略了清單。昨晚我試圖調整顯示選項,認爲這可能與它有關,但無濟於事。無論如何,對於完整性,以下是該活動的清單代碼:

<?xml version="1.0" encoding="utf-8"?> 
<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
    package="net.william.android.myAPI.tester" 
    android:versionCode="1" 
    android:versionName="1.0"> 
    <uses-sdk android:minSdkVersion="10" /> 
    <application android:icon="@drawable/icon" android:label="@string/app_name"> 
     <activity android:name=".MyApiTester" android:label="@string/app_name"> 
      <intent-filter> 
       <action android:name="android.intent.action.MAIN" /> 
       <category android:name="android.intent.category.LAUNCHER" /> 
      </intent-filter> 
     </activity> 
    </application> 
</manifest> 

和服務:

<?xml version="1.0" encoding="utf-8"?> 
<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
    package="net.william.android.myAPI" 
    android:versionCode="1" 
    android:versionName="1.0"> 
    <uses-sdk android:minSdkVersion="10" /> 
    <application android:icon="@drawable/icon" android:label="@string/app_name"> 
     <service android:name=".MyApiService"></service> 
    </application> 
</manifest> 

我嘗試添加了<service>塊內的下面,但它沒」不像是會有所幫助:

  <intent-filter> 
       <action android:name="net.william.android.myAPI.MyApiService" /> 
      </intent-filter> 

無論如何,這是我的第一篇文章到您的論壇,所以我道歉,如果有過多或過少的信息,或者如果我錯過了一些非常簡單的解決辦法在那裏索姆在網絡上的任何地方。我大部分時間都在閱讀關於Google服務的所有文檔,並在論壇發帖之後閱讀文章,因此在這一點上,我可以輕鬆忽略某些內容。預先感謝任何有時間幫助的人!

+0

我建議發佈從logcat的堆棧跟蹤並指出哪些特定在上面的代碼行中與崩潰排隊。我真的不推薦使用'Toast'進行批量診斷,部分原因是*我們無法看到它們;使用'Log'上的方法將自己的信息添加到LogCat中。你指出你的代碼「在我嘗試創建Intent時會死掉」,但是我覺得很難相信,因爲一個Intent構造函數不能真正崩潰。這就是爲什麼堆棧跟蹤並指出崩潰的具體行是重要的。 – CommonsWare

+0

@CommonsWare - 它死於上面的意圖行。 LogCat說:「找不到類net.william.android.myAPI.MyApiService',從方法net.william.android.myAPI.tester.MyApiTester.doBindService」引用。 – William

+0

然後它說「無法解析Lnet/william/android/myAPI/tester/MyApiTester;中的const-class 16(Lnet/william/android/myAPI/MyApiService;)」。 – William

回答

1

如果這些將作爲兩個單獨的APK文件分發,如通過您的一對清單所示,則不能使用將Java類作爲參數的構造函數Intent。事實上,這甚至編譯表明你的項目設置有點可怕 - 從構建時間的角度來看,你的客戶不應該在你的服務範圍內。

<intent-filter>添加到您的<service>廣告中,您希望如何連接,並在您的客戶端使用該結構創建Intent

例如,在此對sampleprojects,服務有:

<service android:name=".BshService"> 
    <intent-filter> 
     <action android:name="com.commonsware.android.advservice.IScript" /> 
    </intent-filter> 
</service> 

,因此客戶端使用:

new Intent("com.commonsware.android.advservice.IScript") 
+0

非常感謝!正如你從我原來的帖子看到的那樣,昨天晚上我已經把''添加到了我的清單中,但是沒有將'Intent'構造函數改爲使用字符串而不是類定義。首先編譯它的原因是因爲Eclipse昨天晚上試圖爲我修復錯誤,並將服務項目的引用添加到測試器項目中,以便它進行編譯。我不是Eclipse的狂熱粉絲,因爲我覺得它爲我*做了很多努力。無論如何,我真的很感謝你的幫助! – William

+0

P.S.,我沒有註冊,所以我無法將您的評分從0提高,但同樣感謝您。 – William

+0

@William:「Eclipse昨天晚上試圖修復這個錯誤,並在服務項目中添加了一個引用到測試項目中的引用,它讓它編譯」 - 是的,有時候Eclipse太過聰明,只有我們自己的好處。 :-)很高興它爲你工作! – CommonsWare