2012-04-05 3 views
4

Ich habe einen Dienst geschrieben und ich habe vor, mehrere Anwendungen mit Messenger kommunizieren zu lassen. Ich bin dem Beispiel von Android Bound Services example for messenger gefolgt. Ich habe den Dienst in ein Android-Bibliotheksprojekt eingefügt und alle anderen Android-Projekte verwenden diese Bibliothek.Android - Warum sind mehrere Instanzen dieses Dienstes ausgeführt

Das Problem, das ich habe, ist, dass mehrere Instanzen des Dienstes ausgeführt werden, wenn ich an es binden. Jede Anwendung bindet an den Dienst in der folgenden Weise:

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

Der Service ist:

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

    } 

} 

Das Manifest für jede Anwendung mehr oder weniger wie folgt aussieht:

<?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> 

Jede Idee, was Ich mache falsch? Die Toast-Nachrichten zeigen recht überzeugend, dass mehrere Instanzen desselben Dienstes ausgeführt werden. Ist meine Projektstruktur falsch? Sollte ich den Dienst nicht in ein separates Bibliotheksprojekt stellen?

Antwort

2

Sie müssen <service /> Tag nur in einem AndroidManifest deklarieren, und in anderen Anwendungen müssen Sie über den vollständigen Komponentennamen binden. Wie zum Beispiel:

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

Auch, wenn Sie android:process=":remote" tun, sagen Sie Android dieser Prozess zu aktuellen Anwendung privat ist.

+0

Kann ich den Dienst nur in meinem Android-Bibliotheksprojekt deklarieren oder muss er in einer der Anwendungen enthalten sein? – Ali

+0

Ich denke es wird besser in einer der App sein. – pepyakin

+0

Laut der Android-Dokumentation, wenn ein Prozess mit ':' beginnt, dann ist es privat zu einer App, aber wenn ich das ':' entferne und mit einem kleineren Namen des Prozesses, sollte es global sein, aber wenn ich es tue, während Bereitstellung Ich erhalte einen ungültigen Manifest-Fehler. Wissen Sie, ob der Dienst innerhalb der ''-Tags oder außerhalb von ihnen deklariert werden muss? Kennen Sie ein Beispiel für die Erstellung eines globalen Service, den ich mir ansehen könnte? – Ali