Android作成サービスのstartedサービス

52525 ワード

startedサービスの作成
アプリケーションコンポーネント(Activityなど)はstartService()を呼び出してServiceを起動し、必要なパラメータをIntentを介してServiceに渡します.サービスはonStartCommand関数でIntentを取得します.
startedサービスを作成するには、拡張サービスクラスと拡張IntentServiceクラスの2つの方法があります.
拡張サービス
これはすべてのサービスのベースクラスです.このクラスを拡張する際に特に重要なのは、サービスタスクを行うために新しいスレッドを作成する必要があります.サービスはデフォルトでメインスレッド(UIスレッド)で実行されているため、メインスレッドの実行が遅くなります.
InentServiceの拡張
これはサービスのサブクラスで、1つのワークスレッドですべての起動要求を処理することができます.同じ時間にすべてのサービスリクエストを出す必要がない場合は、InentServiceを使用するのが良い選択です.あなたがしなければならないのはonHandlerIntent()メソッドを実装し、この関数を通じて受け入れられた各起動要求を処理することだけです.
次に、InentServiceクラスとServiceクラスの拡張方法について説明します.
InentServiceクラスの拡張
InentServiceは何をしましたか?
1.onStartCommand()を介して送信されたすべてのintentを実行するために、プライマリ・スレッドとは独立した作業スレッドを作成します.
2.ワークキューを作成し、受け入れられたすべてのintentをonHandlerIntent()に渡すので、同じ時間に1つのintentしか処理しないので、マルチスレッドの問題を心配する必要はありません.
3.すべての要求が処理された後、サービスを停止するので、stopSelf()を手動で呼び出す必要はありません.
4.onBind()関数のデフォルト実装を提供しnullを返す
5.onStartCommand()関数のデフォルト実装を提供します.intentをワークキューに送信し、onHandlerIntent()関数にワークキューを送信します.
上記の基礎があれば、onHandlerIntent()を実現するだけです.小さな構造関数を実現します
次の例を参照してください.
public class HelloIntentService extends IntentService {

 
/**
   * A constructor is required, and must call the super IntentService(String)
   * constructor with a name for the worker thread.
   */
 
public HelloIntentService() {
     
super("HelloIntentService");
 
}

 
/**
   * The IntentService calls this method from the default worker thread with
   * the intent that started the service. When this method returns, IntentService
   * stops the service, as appropriate.
   */
 
@Override
 
protected void onHandleIntent(Intent intent) {
     
// Normally we would do some work here, like download a file.
     
// For our sample, we just sleep for 5 seconds.
     
long endTime = System.currentTimeMillis() + 5*1000;
     
while (System.currentTimeMillis() < endTime) {
         
synchronized (this) {
             
try {
                  wait
(endTime - System.currentTimeMillis());
             
} catch (Exception e) {
             
}
         
}
     
}
 
}
}

onCreate、onStartCommandなどの他のコールバック関数を実装する場合は、onDestroyは親クラスの対応する関数を呼び出すことを覚えておく必要があります.これにより、InentServiceはワークスレッドを正しく処理することができます.
たとえば、onStartCommand関数でプロンプトをポップアップする必要がある場合は、次のように書くことができます.
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
   
Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
   
return super.onStartCommand(intent,flags,startId);
}

例外として、他のコンポーネントバインドサービスが必要な場合は、onBind関数が親のonBindを呼び出す必要はありません.
次のセクションでは、サービスクラスを拡張することで、コードがより多くなるのとは異なり、コードがより柔軟になることを意味します.特に、複数のリクエストを同時に処理する必要がある場合は、直接サービスを拡張するのに適しています.
拡張サービスクラス
前節で見たように、IntentServiceを使用してstartedサービスを実現するのは簡単です.複数のスレッドを実行するためにサービスが必要な場合は、サービスクラスを拡張して各intentを処理する必要があります.
対比として,次の例ではサービスクラスを用いて前節と同様の機能のサービスを実現している.
public class HelloService extends Service {
 
private Looper mServiceLooper;
 
private ServiceHandler mServiceHandler;

 
// Handler that receives messages from the thread
 
private final class ServiceHandler extends Handler {
     
public ServiceHandler(Looper looper) {
         
super(looper);
     
}
     
@Override
     
public void handleMessage(Message msg) {
         
// Normally we would do some work here, like download a file.
         
// For our sample, we just sleep for 5 seconds.
         
long endTime = System.currentTimeMillis() + 5*1000;
         
while (System.currentTimeMillis() < endTime) {
             
synchronized (this) {
                 
try {
                      wait
(endTime - System.currentTimeMillis());
                 
} catch (Exception e) {
                 
}
             
}
         
}
         
// Stop the service using the startId, so that we don't stop
         
// the service in the middle of handling another job
          stopSelf
(msg.arg1);
     
}
 
}

 
@Override
 
public void onCreate() {
   
// Start up the thread running the service.  Note that we create a
   
// separate thread because the service normally runs in the process's
   
// main thread, which we don't want to block.  We also make it
   
// background priority so CPU-intensive work will not disrupt our UI.
   
HandlerThread thread = new HandlerThread("ServiceStartArguments",
           
Process.THREAD_PRIORITY_BACKGROUND);
    thread
.start();

   
// Get the HandlerThread's Looper and use it for our Handler
    mServiceLooper
= thread.getLooper();
    mServiceHandler
= new ServiceHandler(mServiceLooper);
 
}

 
@Override
 
public int onStartCommand(Intent intent, int flags, int startId) {
     
Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();

     
// For each start request, send a message to start a job and deliver the
     
// start ID so we know which request we're stopping when we finish the job
     
Message msg = mServiceHandler.obtainMessage();
      msg
.arg1 = startId;
      mServiceHandler
.sendMessage(msg);

     
// If we get killed, after returning from here, restart
     
return START_STICKY;
 
}

 
@Override
 
public IBinder onBind(Intent intent) {
     
// We don't provide binding, so return null
     
return null;
 
}

 
@Override
 
public void onDestroy() {
   
Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show();
 
}
}

ご覧のように、InentServiceの例よりも多くのコードがあります.
毎回onStartcommand()を自分で処理するので、同じ時間に複数のリクエストを処理することができます.この例ではそうはしませんが、必要に応じて、前のリクエスト処理が完了してから実行するのではなく、新しいスレッドを作成してすぐに実行することができます.
ただし、onStartCommand()関数は整数を返さなければなりません.この整数は、システムがサービスを殺したときにサービスをどのように処理するかを説明する.戻り値は次の値でなければなりません.
START_NOT_STICKY
onStartCommand()が戻った後、システムがサービスを殺した場合、pending intents(pending Inentsとは何か分からない)が配達されない限り、サービスは再起動されません.これは、未完了のタスクを容易に再起動できる場合に適しています.
START_STICKY
システムがサービスを殺した後、サービスを再起動し、onStartCommand()()を呼び出しますが、前回のintentは再送信されません.システムはonStartCommand()関数nullに渡され、pending intentがサービスを開始しない限り、onStartCommand()に対応するintentに渡されます.この方法は、コマンドを実行する必要はありませんが、独立して実行され、タスクを待つサービスに適しています.
START_REDELIVER_INTENT
システムがサービスを殺した後、サービスを再起動し、onStartCommand()を呼び出し、パラメータは前回のintentに転送され、次いでpending intentがonStartCommand()に転送されます.これは、ダウンロードファイルなどのすぐにリカバリできない作業を実行するのに適しています.
サービスの起動
Activityまたは他のコンポーネントからstartService(intent)を呼び出してサービスを開始できます.Androidシステムは、サービスのonStartCommand()関数を呼び出し、intentに渡します.
前節のHelloServiceを例に挙げます.
Intent intent = new Intent(this, HelloService.class);
startService
(intent);

startService()はすぐに戻り、AndroidシステムはサービスのonStartCommand()関数を呼び出します.サービスが実行されていない場合は、onCreate()関数が最初に呼び出され、onStartCommand()関数がすぐに呼び出されます.
サービスがバインドを提供していない場合、startService()関数を介して入力されるintentは、アプリケーションコンポーネントとサービスがインタラクティブになる唯一の方法です.サービスが結果を顧客コンポーネントに送信したい場合は、顧客コンポーネントは、サービスを開始するときに、ブロードキャスト用のPendingIntentを作成し、intentを通じてサービスに配信する必要があります.これにより,サービスはブロードキャストを用いて結果をクライアントコンポーネントに送信することができる.
複数のリクエストにより、サービスのonStartCommand()が複数回呼び出されます.ただし、停止要求(stopSelf()またはstopService()を1つだけ必要とすると、サービスは停止します.
サービスの停止
起動したサービスは、自分のライフサイクルを管理する必要があります.システムがリソースを回収する必要がない限り、システムはサービスを停止したり破棄したりしないからです.したがって、サービスはstopSelf()を呼び出すことによって自分を停止するか、stopService()を呼び出す他のコンポーネントが必要です.
stopSelf()またはstopService()の停止要求を受け取ると、システムはすぐにサービスを破棄します.
サービスが複数のサービス要求を同時に処理する場合、ある要求が完了するとすぐにサービスを停止することはできません.新しい要求を受け入れた可能性があります(最初の要求が完了すると、サービスが終了すると、2番目の要求が終了します).この問題を解決するためにstopSelf(int)関数を呼び出して、停止要求が常に最近のサービス要求に基づいていることを保証することができます.なぜならstopSelf(int)関数が呼び出されるからです
onStartCommand()関数が入力したstartIdは停止要求に渡されます.startIdが最近受信したサービスリクエストと一致しない場合、サービスは終了しません.
注意:stopSelf(int)関数は、最近受信したstartIdと簡単に比較されます.サービス処理プロセスがマルチスレッドで、後で受信したサービス要求が先に完了する可能性がある場合は、stopSelf(int)のスキームは適切ではありません.onStartCommand()関数でstartIdをテーブルに記録するなど、受信したサービス要求と完了したサービスを手動で管理する必要があります.サービスタスクの完了時に完了ステータスをテーブルに記録し、テーブル内のタスクが完了していることを確認した場合にstopSelf()を直接呼び出してサービスを停止します.
フロントでサービスを実行
1つのフロントサービスは、利用可能なメモリが低い場合、システムがフロントサービスを殺すことはありません.フロントサービスは、実行中のエントリにステータスバー通知を提供する必要があります.これは、サービスが停止していないか、フロントサービスが継続している限り、この通知は消えないことを意味します.
例えば、音楽プレーヤーサービスは、ユーザが実行していることを明らかに知っているため、フロントに設定されるべきである.このステータスバー通知は、再生中の曲を表示し、ユーザがクリックして音楽再生インタフェースにアクセスできるようにすることができる.
サービスをフロントで実行するにはstartForeground()を呼び出します.この方法には2つのパラメータがある:1つの通知の整数IDと1つのステータスバー通知.コードクリップ:
Notification notification = new Notification(R.drawable.icon, getText(R.string.ticker_text),
       
System.currentTimeMillis());
Intent notificationIntent = new Intent(this, ExampleActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification
.setLatestEventInfo(this, getText(R.string.notification_title),
        getText
(R.string.notification_message), pendingIntent);
startForeground
(ONGOING_NOTIFICATION_ID, notification);

stopForeground()関数を使用すると、フロントからサービスを削除できます.この関数には、ステータスバーから通知を削除するかどうかを示すブール値パラメータがあります.この関数はサービスを停止させません.フロントサービスを停止すると、通知も同時に削除されます.
参照先:http://developer.android.com/guide/components/services.html#CreatingStartedService
転載は出典を明記してください:Android作成サービスのstartedサービス
http://blog.csdn.net/oracleot/article/details/18817087