Androidのアクティビティにサービスをバインドする


90

RTSPを使用してストリーミングオーディオを再生するシンプルなメディアプレーヤーを作成しようとしています。GUIアクティビティと再生を実行するサービスがあります。私の質問は、アクティビティとサービスの間で最良の通信を行う方法です(たとえば、プレーヤーの状態に基づいてGUIを更新する)。

onBind()を使用してサービスをアクティビティにバインドできることはわかっていますが、正しく理解していれば、アクティビティが終了した場合にサービスを停止します。ユーザーがアクティビティを終了しても、再生を継続したい。この問題に対処するための標準または推奨される方法はありますか?

回答:


154

「そのサービスでAndroidサービスを開始するとstartService(..)、明示的に呼び出すまでstopService(..)実行されたままになります。サービスがシステムによって実行される理由は2つあります。誰かが呼び出すとContext.startService()、システムがサービスを取得します(作成してそのonCreate()メソッドを呼び出す場合はonStartCommand(Intent, int, int)クライアントから提供された引数を使用してそのメソッドを呼び出します。この時点で、サービスは、Context.stopService()またはstopSelf()が呼び出されるまで実行を続けます。Context.startService()入れ子にしない複数の呼び出しはネストしないことに注意してください(ただし、対応する複数の呼び出しが発生するためonStartCommand())、サービスが開始される回数に関係Context.stopService()stopSelf()呼び出されますが、サービスはstopSelf(int) 開始されたインテントが処理されるまでサービスが停止しないようにする方法。

クライアントは、を使用Context.bindService()してサービスへの永続的な接続を取得することもできます。同様に、まだ実行されていない場合はサービスを作成します(実行onCreate()中に呼び出しonStartCommand()ます)が、呼び出しません。クライアントはIBinder、サービスがそのonBind(Intent)メソッドから返すオブジェクトを受け取り、クライアントがサービスにコールバックできるようにします。接続が確立されている限り、サービスは実行されたままになります(クライアントがサービスの参照を保持しているかどうかは関係ありませんIBinder)。通常、IBinder返されるのはAIDLで記述された複雑なインターフェースです。

サービスは開始することも、接続をバインドすることもできます。そのような場合、システムは、サービスが開始されているか、Context.BIND_AUTO_CREATEフラグを使用してサービスに1つ以上の接続がある限り、サービスを実行し続けます。これらの状況のどちらも成立しないと、サービスのonDestroy()メソッドが呼び出され、サービスは効果的に終了します。から戻ると、すべてのクリーンアップ(スレッドの停止、レシーバーの登録解除)が完了する必要がありますonDestroy()


1
少し混乱:アクティビティが破棄されると、サービスも破棄されるというのは本当ですか?または、自分のAIDLを実装した場合にのみ、そのサービスが破棄されないのですか?startService(esp on IntentService)を使用すると、アクティビティが停止するのではなく、作業が完了するとサービスが停止するので、質問します。では、アクティビティが停止すると、バインドされているサービスも(排他的に)停止するというのは本当ですか?
カテドラルピロン

1
startServiceを呼び出して単純なサーバーを使用している場合は、stopSelf()またはstopService()を呼び出すまでサービスは停止しません。次に、bindServiceを使用する場合、すべての接続済み/バインド済みコンポーネントが破棄されると、yesサービスが停止します。
Asif Mushtaq 2017

1
@UnKnown startService()を使用してサービスを開始した場合、サービスをバインドまたはアンバインドしても、サービスは引き続き実行され、stopService()またはstopSelf()を呼び出すことによってのみ破棄できます。したがって、サービスにバインドされていたアクティビティが破棄されても、サービスは破棄されません。
CopsOnRoad 2018

この質問で私を助けていただけませんか。stackoverflow.com
Rajesh K

25

まず最初に、私たちが理解する必要がある2つのこと

クライアント

  • 特定のサーバーにリクエストを出す

    bindService(new 
        Intent("com.android.vending.billing.InAppBillingService.BIND"),
            mServiceConn, Context.BIND_AUTO_CREATE);`

ここmServiceConnのインスタンスであるServiceConnectionクラス(作り付け)実際に我々は2つ(接続されたネットワークと接続されていない第二のネットワークのための第一)のネットワーク接続状態を監視するための方法で実装する必要があるとのインターフェイスですが。

サーバ

  • クライアントのリクエストを処理し、リクエストを送信するクライアントにのみプライベートな独自のレプリカを作成します。サーバーのこのレプリカは異なるスレッドで実行されます。

クライアント側で、サーバーのすべてのメソッドにアクセスするにはどうすればよいですか?

  • サーバーはIBind Object.soを使用して応答を送信します。IBindオブジェクトは、(。)演算子を使用してすべてのサービスメソッドにアクセスするハンドラーです。

    MyService myService;
    public ServiceConnection myConnection = new ServiceConnection() {
        public void onServiceConnected(ComponentName className, IBinder binder) {
            Log.d("ServiceConnection","connected");
            myService = binder;
        }
        //binder comes from server to communicate with method's of 
    
        public void onServiceDisconnected(ComponentName className) {
            Log.d("ServiceConnection","disconnected");
            myService = null;
        }
    }

サービスにあるメソッドを呼び出す方法

myservice.serviceMethod();

これmyServiceがオブジェクトでありserviceMethode、サービス中のメソッドです。このようにして、クライアントとサーバー間で通信が確立されます。



5

bindServiceの呼び出し時に作成したServiceConnectionを取得するunbindServiceというメソッドがあります。これにより、サービスを実行したまま、サービスから切断できます。

アクティビティを再度開始したときに実行中かどうかわからないため、再度接続すると問題が発生する可能性があるため、アクティビティコードでそれを考慮する必要があります。

幸運を!


-1

これは偏った答えですが、アプリと同じプロセスでローカルに実行する場合、Androidサービスの使用を簡素化できるライブラリを作成しました:https : //github.com/germnix/acacia

基本的に、@ Serviceとその実装クラスで注釈が付けられたインターフェースを定義し、ライブラリがサービスを作成してバインドし、接続とバックグラウンドワーカースレッドを処理します。

@Service(ServiceImpl.class)
public interface MyService {
    void doProcessing(Foo aComplexParam);
}

public class ServiceImpl implements MyService {
    // your implementation
}

MyService service = Acacia.createService(context, MyService.class);
service.doProcessing(foo);

<application
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme">
    ...
    <service android:name="com.gmr.acacia.AcaciaService"/>
    ...
</application>

関連するandroid.app.Serviceのインスタンスを取得して永続的な通知を非表示/表示し、独自のandroid.app.Serviceを使用して、必要に応じてスレッドを手動で処理できます。


-5

ユーザーがバックアウトすると、onDestroy()メソッドが呼び出されます。このメソッドは、アプリケーションで使用されているすべてのサービスを停止するためのものです。そのため、ユーザーがアプリケーションをバックアウトした場合でもサービスを継続したい場合は、単にを削除してくださいonDestroy()。この助けを願っています。


IDEが自動的に作成する場合は、関数をオーバーライドして、スーパークラスのonDestroy()へのデフォルトの呼び出しを削除する必要があります。しかし、なぜこれをしたいのですか?
Riptyde4 2015年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.