4

私はサービスを作成しました。Messenger を使用して複数のアプリケーションがサービスと通信することを計画しています。メッセンジャーの Android Bound Servicesの例の例に従いました。サービスを 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 メッセージは、同じサービスの複数のインスタンスが実行されていることを明確に示しています。私のプロジェクト構造は間違っていますか? このサービスを別の Library プロジェクトに入れるべきではありませんか?

4

1 に答える 1

2

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

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"そのプロセスが現在のアプリケーションにプライベートであることをアンドロイドに伝えます。

于 2012-04-05T07:34:22.860 に答える