2012-04-05 11 views
4

サービスを作成しましたが、複数のアプリケーションでMessengerを使用して通信する予定です。私はAndroid Bound Services example for messengerの例を辿ってきました。 私はこのサービスをAndroidライブラリプロジェクトに入れました。他のすべてのAndroidプロジェクトはそのライブラリを使用しています。Android - このサービスの複数のインスタンスが実行されている理由

私が持っている問題は、サービスにバインドすると複数のインスタンスが実行されることです。各アプリケーションは、次のようにサービスにバインド:

// Bind to the service 
bindService(new Intent(ApplicationOneActivity.this, MessengerService.class), mConnection, Context.BIND_AUTO_CREATE); 

サービスは次のとおりです。

public class MessengerService extends Service { 
    /** Command to the service to display a message */ 
    public static final int MSG_SAY_HELLO = 0; 
    /** Command to the service to display a message from App 1 */ 
    public static final int MSG_APP1_HELLO = 1; 

    public static final int MSG_APP2_HELLO = 2; 

    public static final int MSG_APP3_HELLO = 3; 

    private int[] stat = new int[3]; 

    private Timer timer = null; 

    /** 
    * Handler of incoming messages from clients. 
    */ 
    class IncomingHandler extends Handler { 
     @Override 
     public void handleMessage(Message msg) { 
      switch (msg.what) { 
      case MSG_SAY_HELLO: 
       Toast.makeText(getApplicationContext(), "hello!", Toast.LENGTH_SHORT).show(); 
       break; 
      case MSG_APP1_HELLO: 
       Toast.makeText(getApplicationContext(), "App One says: " + msg.arg1, Toast.LENGTH_SHORT).show(); 
       stat[0] = msg.arg1; 
       break; 
      case MSG_APP2_HELLO: 
       Toast.makeText(getApplicationContext(), "App Two says: " + msg.arg1, Toast.LENGTH_SHORT).show(); 
       stat[1] = msg.arg1; 
       break; 
      case MSG_APP3_HELLO: 
       Toast.makeText(getApplicationContext(), "App Three says: " + msg.arg1, Toast.LENGTH_SHORT).show(); 
       stat[2] = msg.arg1; 
       break; 
      default: 
       super.handleMessage(msg); 
      } 
     } 
    } 

    /** 
    * Target we publish for clients to send messages to IncomingHandler. 
    */ 
    final Messenger mMessenger = new Messenger(new IncomingHandler()); 

    /** 
    * When binding to the service, we return an interface to our messenger 
    * for sending messages to the service. 
    */ 
    @Override 
    public IBinder onBind(Intent intent) { 
     Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show(); 

     return mMessenger.getBinder(); 

    } 

    @Override 
    public boolean onUnbind(Intent intent) { 
     Toast.makeText(getApplicationContext(), "unbinding", Toast.LENGTH_SHORT).show(); 
     return super.onUnbind(intent); 
    } 

    final Handler handler = new Handler() { 

     public void handleMessage(Message msg) { 
      // Create and send a message to the service, using a supported 'what' value 
      ReportAsyncTask report = new ReportAsyncTask(); 
      report.execute(""); 
     } 
    }; 


    @Override 
    public void onCreate() { 
     super.onCreate(); 

     if (timer == null) { 
      timer = new Timer(); 
      timer.schedule(new ScheduledTaskWithHandeler(), 10000); 
      Toast.makeText(getApplicationContext(), "Register Timer To Report Back ", Toast.LENGTH_SHORT).show(); 
     } 
    } 

    @Override 
    public void onDestroy() { 
     super.onDestroy(); 
     if (timer != null) { 
      timer.cancel(); 
      timer = null; 
     } 
    } 

    class ScheduledTaskWithHandeler extends TimerTask { 

     @Override 
     public void run() { 
      handler.sendEmptyMessage(0); 
     } 
    } 

    private class ReportAsyncTask extends AsyncTask<String, Void, String> { 
     @Override 
     protected String doInBackground(String... urls) { 
      String response = ""; 
      try { 
       String urlParams="device=" + URLEncoder.encode(android.os.Build.MODEL, "UTF-8") 
         + "&status="+URLEncoder.encode("App1 says " + stat[0] + ", App2 says " + stat[1] + ", App3 says " + stat[2],"UTF-8"); 
       String url = "http://192.168.43.143:8080/SimpleServlet3/monitor-servlet"; 
       HttpClient httpclient = new DefaultHttpClient(); 
       HttpGet httpget = new HttpGet(url+"?"+urlParams); 
       HttpResponse httpresponse = httpclient.execute(httpget); 
       HttpEntity entity = httpresponse.getEntity(); 
       if (entity != null) { 
        InputStream instream = entity.getContent(); 
        int l; 
        byte[] tmp = new byte[2048]; 
        while ((l = instream.read(tmp)) != -1) { 
         response += l; 
        } 
       } 
       timer.schedule(new ScheduledTaskWithHandeler(), 10000); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
      return response; 
     } 

     @Override 
     protected void onPostExecute(String result) { 
      Toast.makeText(getApplicationContext(), "Server says " + result, Toast.LENGTH_SHORT).show(); 
     } 

    } 

} 

各アプリケーションのマニフェストは、以下のより多くのようになります。

<?xml version="1.0" encoding="utf-8"?> 
<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
    package="com.example.app1" 
    android:versionCode="1" 
    android:versionName="1.0" > 

    <uses-sdk android:minSdkVersion="11" /> 

    <uses-permission android:name="android.permission.INTERNET" /> 
    <uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" /> 
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> 
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> 

    <application 
     android:icon="@drawable/spinifex" 
     android:label="@string/app_name" > 
     <activity 
      android:name=".ApplicationOneActivity" 
      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.example.services.MessengerService" 
      android:process=":remote" /> 
    </application> 

</manifest> 

何任意のアイデアを私は間違っている? Toastメッセージは結局、同じサービスの複数のインスタンスが実行されていることを示しています。私のプロジェクト構造は間違っていますか?サービスを別の図書館プロジェクトに入れないでください。

答えて

2

<service />タグは1つのAndroidManifestでのみ宣言する必要があります。他のアプリでは完全なコンポーネント名でバインドする必要があります。 のような:また

Intent intent = new Intent(); 
intent.setClassName(
    "com.example.app1" /* your package which contains service */, 
    "com.example.services.MessengerService" /* service name */ 
); 

bindService(intent, mConnection, Context.BIND_AUTO_CREATE); 

、あなたがandroid:process=":remote"を行うとき、あなたはプロセスが現在のアプリケーションにプライベートであることをAndroidに伝えます。

+0

サービスはAndroidライブラリプロジェクトでのみ宣言できますか、それともアプリケーションの1つに含まれている必要がありますか? – Ali

+0

私はそれがアプリの1つでより良いと思う。 – pepyakin

+0

アンドロイドのドキュメントによると、プロセスは ':'で始まり、それはアプリケーションにとってはプライベートなものですが、 ':'を削除してプロセスの名前をlowercasetで始めるとグローバルになるはずですが、展開すると、不正なマニフェストエラーが発生します。サービスが ''タグ内に宣言されなければならないのか、それらの外側に宣言されなければならないのですか?私が見ることができるグローバルなサービスを作る例を知っていますか? – Ali

関連する問題