2012年11月16日金曜日

暗黙的Intentの対象のServiceが複数あった場合の挙動について

Androidの暗黙的IntentでActivityを起動する場合には,どのActivityを起動するか選択するダイアログが表示されます.
ではServiceの場合ではどういう挙動をするのか.社内で話題になったので確認してみました.
Activityのように選択のダイアログが出てくるんじゃないか,両方起動するんじゃないか,パッケージ名でソートした結果上に来たものなどの予想をしていましたが,結果は先にインストールされたものが優先される,でした.
検証方法です.
  1. 起動するとToastを表示するServiceを持ったアプリを二つ作ります. 
  2. そのサービスを呼ぶ共通の暗黙的IntentをAndroidManifestに書きます.
  3. 第三のアプリから暗黙的Intentを投げて表示されるToastを確認します.
そもそもServiceを暗黙的Intentで呼び出すことなんてあるのでしょうか.

以下は検証に使用したソースコードです.

Service.java
package com.example.service1;

import android.content.Intent;
import android.os.IBinder;
import android.widget.Toast;

public class Service extends android.app.Service {
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Toast.makeText(this, "Service1", Toast.LENGTH_LONG).show();
        return START_STICKY;
    }
}

Service.javaはパッケージ名とToastのメッセージ以外同じものを別プロジェクトでも作成します.

AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.service1"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="16" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <service android:name=".Service" >
            <intent-filter>
                <action android:name="com.example.service.test" />
            </intent-filter>
        </service>
    </application>

</manifest>

サービスに対して暗黙的Intentを投げる別アプリを作ります.
MainActivity.java
package com.example.servicelauncher;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Button button = new Button(this);
        button.setText("Launch");
        button.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent("com.example.service.test");
                startService(intent);
            }
        });
        setContentView(button);
    }
}


0 件のコメント:

コメントを投稿