サーチ…


前書き

サービスは、長時間実行される操作を実行したり、リモートプロセスの作業を実行するためにバックグラウンドで実行されます。サービスは、ユーザーの入力でバックグラウンドでのみ実行されるユーザーインターフェイスを提供しません。たとえば、ユーザーが別のAppにいる間にバックグラウンドで音楽を再生したり、Androidデバイスとのユーザーのやりとりを妨げることなくインターネットからデータをダウンロードしたりすることができます。

備考

AndroidManifest.xmlでサービスを定義していない場合、サービスを開始しようとするとServiceNotFoundExceptionが返されます。

注意:

IntentServiceに関する情報は、 IntentServiceしてください: IntentServiceの例

サービスの開始

サービスを開始することは非常に簡単です。アクティビティ内から目的を持ってstartServiceを呼び出すだけです:

Intent intent = new Intent(this, MyService.class);  //substitute MyService with the name of your service
intent.putExtra(Intent.EXTRA_TEXT, "Some text"); //add any extra data to pass to the service

startService(intent); //Call startService to start the service.

サービスのライフサイクル

サービスライフサイクルには以下のコールバックがあります

  • onCreate()

サービスが最初に作成されたときに実行され、必要な初期設定を設定します。このメソッドは、サービスがまだ実行されていない場合にのみ実行されます。

  • onStartCommand()

startService()がアクティビティやBroadcastReceiverのような別のコンポーネントによって呼び出されるたびに実行されstartService() 。このメソッドを使用すると、 stopSelf()またはstopService()を呼び出すまでサービスが実行されます。それに関係なく、あなたが呼び出し回数の注意onStartCommand()メソッドstopSelf()stopService()サービスを停止するために、一度だけ起動する必要があります。

  • onBind()

コンポーネントがbindService()を呼び出してbindService()のインスタンスを返し、通信チャネルをサービスに提供するときに実行されます。 bindService()を呼び出すと、バインドされたクライアントがある限り、サービスは実行されたままになります。

  • onDestroy()

サービスがもはや使用されなくなったときに実行され、割り当てられたリソースの廃棄が可能になります。

サービスのライフサイクル中に、 onConfigurationChanged()onLowMemory()などの他のコールバックが呼び出される可能性があることに注意することは重要です。

https://developer.android.com/guide/components/services.html

ここに画像の説明を入力

サービスのプロセスの定義

android:processフィールドは、サービスが実行されるプロセスの名前を定義します。通常、アプリケーションのすべてのコンポーネントは、アプリケーション用に作成されたデフォルトのプロセスで実行されます。ただし、コンポーネントは独自のプロセス属性を使用してデフォルトをオーバーライドすることができ、アプリケーションを複数のプロセスに分散することができます。

この属性に割り当てられた名前がコロン( ':')で始まる場合、サービスはそれ自身の別のプロセスで実行されます。

<service
  android:name="com.example.appName"
  android:process=":externalProcess" />

プロセス名が小文字で始まる場合、サービスはその名前のグローバルプロセスで実行されます。これにより、異なるアプリケーションのコンポーネントがプロセスを共有し、リソースの使用を削減できます。

バインダーの助けを借りてバインドされたサービスを作成する

Serviceクラスを拡張するクラスを作成し、オーバーライドされたメソッドonBindて、ローカルのバインダーインスタンスを返します。

public class LocalService extends Service {
    // Binder given to clients
    private final IBinder mBinder = new LocalBinder();

    /**
     * Class used for the client Binder.  Because we know this service always
     * runs in the same process as its clients, we don't need to deal with IPC.
     */
    public class LocalBinder extends Binder {
        LocalService getService() {
            // Return this instance of LocalService so clients can call public methods
            return LocalService.this;
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }
}

次に、あなたのアクティビティでonStartコールバックでサービスにバインドし、 ServiceConnectionインスタンスを使用してonStopバインドを解除します。

public class BindingActivity extends Activity {
    LocalService mService;
    boolean mBound = false;

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

    @Override
    protected void onStart() {
        super.onStart();
        // Bind to LocalService
        Intent intent = new Intent(this, LocalService.class);
        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
    }

    @Override
    protected void onStop() {
        super.onStop();
        // Unbind from the service
        if (mBound) {
            unbindService(mConnection);
            mBound = false;
        }
    }

    /** Defines callbacks for service binding, passed to bindService() */
    private ServiceConnection mConnection = new ServiceConnection() {

        @Override
        public void onServiceConnected(ComponentName className,
                IBinder service) {
            // We've bound to LocalService, cast the IBinder and get LocalService instance
            LocalBinder binder = (LocalBinder) service;
            mService = binder.getService();
            mBound = true;
        }

        @Override
        public void onServiceDisconnected(ComponentName arg0) {
            mBound = false;
        }
    };
}

リモートサービスの作成(AIDL経由)

.aidlファイルを使用してサービスアクセスインターフェースを.aidl

// IRemoteService.aidl
package com.example.android;

// Declare any non-default types here with import statements

/** Example service interface */
interface IRemoteService {
    /** Request the process ID of this service, to do evil things with it. */
    int getPid();
}

今すぐアプリケーションをビルドしたら、sdkツールは適切な.javaファイルを生成します。このファイルには、aidlインタフェースを実装し、拡張する必要があるStubクラスが含まれます:

public class RemoteService extends Service {

    private final IRemoteService.Stub binder = new IRemoteService.Stub() {
        @Override
        public int getPid() throws RemoteException {
            return Process.myPid();
        }
    };

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return binder;
    }
}

その後、活動中:

public class MainActivity extends AppCompatActivity {
    private final ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            IRemoteService service = IRemoteService.Stub.asInterface(iBinder);
            Toast.makeText(this, "Activity process: " + Process.myPid + ", Service process: " + getRemotePid(service), LENGTH_SHORT).show();
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {}
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    @Override
    protected void onStart() {
        super.onStart();
        Intent intent = new Intent(this, RemoteService.class);
        bindService(intent, connection, Context.BIND_AUTO_CREATE);
    }

    @Override
    protected void onStop() {
        super.onStop();
        unbindService(connection);
    }

    private int getRemotePid(IRemoteService service) {
        int result = -1;

        try {
            result = service.getPid();
        } catch (RemoteException e) {
            e.printStackTrace();
        }

        return result;
    }
}

アンバウンドサービスの作成

まず、 <application>タグ内のAndroidManifest.xmlにサービスを追加します。

<application ...>

    ...        

    <service
        android:name=".RecordingService"
        <!--"enabled" tag specifies Whether or not the service can be instantiated by the system — "true" -->
        <!--if it can be, and "false" if not. The default value is "true".-->
        android:enabled="true"
        <!--exported tag specifies Whether or not components of other applications can invoke the -->
        <!--service or interact with it — "true" if they can, and "false" if not. When the value-->
        <!--is "false", only components of the same application or applications with the same user -->
        <!--ID can start the service or bind to it.-->
        android:exported="false" />

</application>

別のパッケージ(例:.AllServices.RecordingService)でサービスクラスを管理する場合は、サービスがどこにあるかを指定する必要があります。したがって、上記の場合、次のように変更します。

android:name=".RecordingService"

android:name=".AllServices.RecordingService"

そうする最も簡単な方法は、完全なパッケージ名を指定することです。

次に、実際のサービスクラスを作成します。

public class RecordingService extends Service {
    private int NOTIFICATION = 1; // Unique identifier for our notification

    public static boolean isRunning = false;
    public static RecordingService instance = null;


    private NotificationManager notificationManager = null;


    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate(){
        instance = this;
        isRunning = true;

        notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId){
        // The PendingIntent to launch our activity if the user selects this notification
        PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, MainActivity.class), 0);

        // Set the info for the views that show in the notification panel.
        Notification notification = new NotificationCompat.Builder(this)
                .setSmallIcon(R.mipmap.ic_launcher)        // the status icon
                .setTicker("Service running...")           // the status text
                .setWhen(System.currentTimeMillis())       // the time stamp
                .setContentTitle("My App")                 // the label of the entry
                .setContentText("Service running...")      // the content of the entry
                .setContentIntent(contentIntent)           // the intent to send when the entry is clicked
                .setOngoing(true)                          // make persistent (disable swipe-away)
                .build();

        // Start service in foreground mode
        startForeground(NOTIFICATION, notification);

        return START_STICKY;
    }


    @Override
    public void onDestroy(){
        isRunning = false;
        instance = null;

        notificationManager.cancel(NOTIFICATION); // Remove notification

        super.onDestroy();
    }


    public void doSomething(){
        Toast.makeText(getApplicationContext(), "Doing stuff from service...", Toast.LENGTH_SHORT).show();
    }

}

このサービスは、実行時に通知を表示し、 doSomething()メソッドが呼び出されたときにトーストを表示することができます。

あなたが気づくように、それはシングルトンとして実装され、独自のインスタンスを追跡しますが、通常の静的シングルトンファクトリメソッドはありません。なぜなら、サービスは自然にシングルトンであり、意図によって作成されるからです。このインスタンスは、実行時にサービスへの「ハンドル」を得るために外部に役立ちます。

最後に、アクティビティからサービスを開始および停止する必要があります。

public void startOrStopService(){
    if( RecordingService.isRunning ){
        // Stop service
        Intent intent = new Intent(this, RecordingService.class);
        stopService(intent);
    }
    else {
        // Start service
        Intent intent = new Intent(this, RecordingService.class);
        startService(intent);
    }
}

この例では、サービスは現在の状態に応じて同じ方法で開始および停止します。

doSomething()メソッドをアクティビティから呼び出すこともできます:

public void makeServiceDoSomething(){
    if( RecordingService.isRunning )
        RecordingService.instance.doSomething();
}


Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow