バックグラウンドサービスが実行されているかどうかを確認するにはどうすればよいですか?
サービスの状態を切り替えるAndroidアクティビティが必要です。これにより、サービスがオフの場合はオンになり、オンの場合はオフにできます。
getRunningTasks()
に神経衰弱していないなら、おそらくそうなるでしょう。
バックグラウンドサービスが実行されているかどうかを確認するにはどうすればよいですか?
サービスの状態を切り替えるAndroidアクティビティが必要です。これにより、サービスがオフの場合はオンになり、オンの場合はオフにできます。
getRunningTasks()
に神経衰弱していないなら、おそらくそうなるでしょう。
回答:
ずっと前に同じ問題がありました。私のサービスはローカルだったので、ここの hackbod で説明されているように、サービスクラスの静的フィールドを使用して状態を切り替えました
編集(記録用):
これがハックボッドによって提案されたソリューションです:
クライアントとサーバーのコードが同じ.apkの一部であり、具体的なインテント(正確なサービスクラスを指定するもの)を使用してサービスにバインドしている場合は、サービスでグローバル変数を設定するだけで実行できます。クライアントが確認できます。
ほぼ間違いなく、コードで競合状態が発生するようなことをしたいので、サービスが実行されているかどうかを確認するAPIは意図的にはありません。
onDestroy()
は呼び出されません。そのため、このようなシナリオでは静的変数を更新できず、動作に一貫性がなくなります。
私はアクティビティ内から以下を使用します:
private boolean isMyServiceRunning(Class<?> serviceClass) {
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (serviceClass.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}
そして私はそれを使ってそれを呼び出します:
isMyServiceRunning(MyService.class)
これは、ActivityManager#getRunningServicesを通じてAndroidオペレーティングシステムによって提供される実行中のサービスに関する情報に基づいているため、確実に機能します。
onDestroy、onSometingイベント、Binder、または静的変数を使用するすべてのアプローチは、Androidがプロセスを強制終了することを決定したとき、または言及されたコールバックのどれが呼び出されるかどうかがわからないため、確実に機能しません。Androidドキュメントのライフサイクルイベントテーブルの「killable」列に注意してください。
getRunningServices
推奨されていません。この回答には、新しいバージョンのアップデートが必要です。
とった!
あなたはstartService()
あなたのサービスが適切に登録されるように要求しなければなりません、そして、通過BIND_AUTO_CREATE
は十分ではありません。
Intent bindIntent = new Intent(this,ServiceTask.class);
startService(bindIntent);
bindService(bindIntent,mConnection,0);
そして今ServiceToolsクラス:
public class ServiceTools {
private static String LOG_TAG = ServiceTools.class.getName();
public static boolean isServiceRunning(String serviceClassName){
final ActivityManager activityManager = (ActivityManager)Application.getContext().getSystemService(Context.ACTIVITY_SERVICE);
final List<RunningServiceInfo> services = activityManager.getRunningServices(Integer.MAX_VALUE);
for (RunningServiceInfo runningServiceInfo : services) {
if (runningServiceInfo.service.getClassName().equals(serviceClassName)){
return true;
}
}
return false;
}
}
少し補足すると:
私の目標は、サービスが実行されていなくても、実際に実行せずにサービスが実行されているかどうかを知ることです。
bindServiceを呼び出すか、サービスがキャッチできるインテントを呼び出すことは、サービスが実行されていない場合にサービスを開始するため、適切ではありません。
したがって、miracle2kが示唆しているように、サービスが開始されているかどうかを確認するために、サービスクラスに静的フィールドを含めるのが最善です。
さらにクリーンにするために、サービスを非常に遅延したフェッチでシングルトンに変換することをお勧めします。つまり、静的メソッドによるすべてのシングルトンインスタンスでのインスタンス化はありません。サービス/シングルトンの静的getInstanceメソッドは、シングルトンが作成されている場合、そのインスタンスを返すだけです。しかし、それは実際にはシングルトン自体を開始したりインスタンス化したりするものではありません。サービスは、通常のサービス開始方法でのみ開始されます。
次に、シングルトン設計パターンを変更して、紛らわしいgetInstanceメソッドの名前をメソッドのような名前に変更すると、さらにクリーンになりますisInstanceCreated() : boolean
。
コードは次のようになります。
public class MyService extends Service
{
private static MyService instance = null;
public static boolean isInstanceCreated() {
return instance != null;
}//met
@Override
public void onCreate()
{
instance = this;
....
}//met
@Override
public void onDestroy()
{
instance = null;
...
}//met
}//class
このソリューションは洗練されていますが、サービスクラスへのアクセス権があり、サービスのアプリ/パッケージがクラスの場合にのみ関連します。クラスがサービスアプリ/パッケージの外にある場合、Pieter-Jan Van Robaysによって下線が引かれた制限付きでActivityManagerをクエリできます。
あなたはこれを使うことができます(私はまだこれを試していませんが、これがうまくいくことを願っています):
if(startService(someIntent) != null) {
Toast.makeText(getBaseContext(), "Service is already running", Toast.LENGTH_SHORT).show();
}
else {
Toast.makeText(getBaseContext(), "There is no service running, starting service..", Toast.LENGTH_SHORT).show();
}
すでに実行中のサービスがある場合、startServiceメソッドはComponentNameオブジェクトを返します。そうでない場合は、nullが返されます。
public abstract ComponentName startService(Intent service)を参照してください。
これは、サービスを開始しているのでstopService(someIntent);
、コードの下に追加できるので、私が考えるチェックとは異なります。
if(startService(someIntent) != null)
それをチェックするときにそれIsserviceRunning
が新しいサービスを再生するので、それは適切な方法ではありません。
/**
* Check if the service is Running
* @param serviceClass the class of the Service
*
* @return true if the service is running otherwise false
*/
public boolean checkServiceRunning(Class<?> serviceClass){
ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE))
{
if (serviceClass.getName().equals(service.service.getClassName()))
{
return true;
}
}
return false;
}
Androidドキュメントからの抜粋:
sendBroadcast(Intent)と似ていますが、Intentのレシーバーがある場合、この関数はブロックしてすぐにディスパッチしてから戻ります。
このハックは、「ping」と考えることができますService
。同期的にブロードキャストできるため、UIスレッドで同期的にブロードキャストして結果を取得できます。
Service
@Override
public void onCreate() {
LocalBroadcastManager
.getInstance(this)
.registerReceiver(new ServiceEchoReceiver(), new IntentFilter("ping"));
//do not forget to deregister the receiver when the service is destroyed to avoid
//any potential memory leaks
}
private class ServiceEchoReceiver extends BroadcastReceiver {
public void onReceive (Context context, Intent intent) {
LocalBroadcastManager
.getInstance(this)
.sendBroadcastSync(new Intent("pong"));
}
}
Activity
bool serviceRunning = false;
protected void onCreate (Bundle savedInstanceState){
LocalBroadcastManager.getInstance(this).registerReceiver(pong, new IntentFilter("pong"));
LocalBroadcastManager.getInstance(this).sendBroadcastSync(new Intent("ping"));
if(!serviceRunning){
//run the service
}
}
private BroadcastReceiver pong = new BroadcastReceiver(){
public void onReceive (Context context, Intent intent) {
serviceRunning = true;
}
}
もちろん、多くのアプリケーションでの勝者は、true
in Service.onCreate()
and to false
inに設定されているサービスの静的ブールフィールドService.onDestroy()
です。
上記の解決策の1つを少し変更しましたが、同じメソッドから出てくる文字列を確実に比較するために、一般的な文字列名の代わりにクラスを渡します。 class.getName()
public class ServiceTools {
private static String LOG_TAG = ServiceTools.class.getName();
public static boolean isServiceRunning(Context context,Class<?> serviceClass){
final ActivityManager activityManager = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);
final List<RunningServiceInfo> services = activityManager.getRunningServices(Integer.MAX_VALUE);
for (RunningServiceInfo runningServiceInfo : services) {
Log.d(Constants.TAG, String.format("Service:%s", runningServiceInfo.service.getClassName()));
if (runningServiceInfo.service.getClassName().equals(serviceClass.getName())){
return true;
}
}
return false;
}
}
その後
Boolean isServiceRunning = ServiceTools.isServiceRunning(
MainActivity.this.getApplicationContext(),
BackgroundIntentService.class);
Class<? extends Service>
サービスが実行されているかどうかを確認する適切な方法は、単にそれを尋ねることです。アクティビティからのpingに応答するBroadcastReceiverをサービスに実装します。サービスの開始時にBroadcastReceiverを登録し、サービスが破棄されたら登録を解除します。アクティビティ(または任意のコンポーネント)から、ローカルブロードキャストインテントをサービスに送信します。サービスが応答した場合、サービスは実行されています。以下のコードのACTION_PINGとACTION_PONGのわずかな違いに注意してください。
public class PingableService extends Service
{
public static final String ACTION_PING = PingableService.class.getName() + ".PING";
public static final String ACTION_PONG = PingableService.class.getName() + ".PONG";
public int onStartCommand (Intent intent, int flags, int startId)
{
LocalBroadcastManager.getInstance(this).registerReceiver(mReceiver, new IntentFilter(ACTION_PING));
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy ()
{
LocalBroadcastManager.getInstance(this).unregisterReceiver(mReceiver);
super.onDestroy();
}
private BroadcastReceiver mReceiver = new BroadcastReceiver()
{
@Override
public void onReceive (Context context, Intent intent)
{
if (intent.getAction().equals(ACTION_PING))
{
LocalBroadcastManager manager = LocalBroadcastManager.getInstance(getApplicationContext());
manager.sendBroadcast(new Intent(ACTION_PONG));
}
}
};
}
public class MyActivity extends Activity
{
private boolean isSvcRunning = false;
@Override
protected void onStart()
{
LocalBroadcastManager manager = LocalBroadcastManager.getInstance(getApplicationContext());
manager.registerReceiver(mReceiver, new IntentFilter(PingableService.ACTION_PONG));
// the service will respond to this broadcast only if it's running
manager.sendBroadcast(new Intent(PingableService.ACTION_PING));
super.onStart();
}
@Override
protected void onStop()
{
LocalBroadcastManager.getInstance(this).unregisterReceiver(mReceiver);
super.onStop();
}
protected BroadcastReceiver mReceiver = new BroadcastReceiver()
{
@Override
public void onReceive (Context context, Intent intent)
{
// here you receive the response from the service
if (intent.getAction().equals(PingableService.ACTION_PONG))
{
isSvcRunning = true;
}
}
};
}
@Snicolasの回答にメモを追加したいだけです。次の手順を使用して、を呼び出して、または呼び出さずにサービスの停止を確認できますonDestroy()
。
onDestroy()
呼び出し:設定->アプリケーション->実行中のサービス->選択してサービスを停止します。
onDestroy()
呼び出されない:設定->アプリケーション->アプリケーションの管理->サービスが実行されているアプリケーションを選択して「強制停止」します。ただし、ここでアプリケーションが停止すると、サービスインスタンスも確実に停止します。
最後に、シングルトンクラスで静的変数を使用する方法について説明します。
まず最初に、ActivityManagerを使用してサービスにアクセスしようとしないでください。(ここで議論)
サービスは単独で実行することも、アクティビティにバインドすることも、その両方を行うこともできます。サービスが実行されているかどうかをアクティビティにチェックインする方法は、アクティビティとサービスの両方が理解するメソッドを宣言するインターフェイス(バインダーを拡張する)を作成することです。これを行うには、たとえば「isServiceRunning()」などを宣言する独自のインターフェースを作成します。次に、アクティビティをサービスにバインドし、メソッドisServiceRunning()を実行します。サービスは、サービスが実行中かどうかをチェックし、ブール値をアクティビティに返します。
このメソッドを使用して、サービスを停止したり、別の方法でサービスと対話したりすることもできます。
このチュートリアルを使用して、このシナリオをアプリケーションに実装する方法を学びました。
繰り返しになりますが、保留中のインテントを使用する場合に人々がよりクリーンに感じるかもしれない別の代替(たとえばAlarmManager
:
public static boolean isRunning(Class<? extends Service> serviceClass) {
final Intent intent = new Intent(context, serviceClass);
return (PendingIntent.getService(context, CODE, intent, PendingIntent.FLAG_NO_CREATE) != null);
}
CODE
サービスに関連付けられている保留中のインテントを識別するためにクラスでプライベートに定義する定数はどこにありますか。
以下は、すべてをカバーするエレガントなハックですIfs
。これはローカルサービス専用です。
public final class AService extends Service {
private static AService mInstance = null;
public static boolean isServiceCreated() {
try {
// If instance was not cleared but the service was destroyed an Exception will be thrown
return mInstance != null && mInstance.ping();
} catch (NullPointerException e) {
// destroyed/not-started
return false;
}
}
/**
* Simply returns true. If the service is still active, this method will be accessible.
* @return
*/
private boolean ping() {
return true;
}
@Override
public void onCreate() {
mInstance = this;
}
@Override
public void onDestroy() {
mInstance = null;
}
}
そして後で:
if(AService.isServiceCreated()){
...
}else{
startService(...);
}
Xamarin C#バージョン:
private bool isMyServiceRunning(System.Type cls)
{
ActivityManager manager = (ActivityManager)GetSystemService(Context.ActivityService);
foreach (var service in manager.GetRunningServices(int.MaxValue)) {
if (service.Service.ClassName.Equals(Java.Lang.Class.FromType(cls).CanonicalName)) {
return true;
}
}
return false;
}
GetSystemService
。
ここで示すユースケースでは、stopService()
メソッドの戻り値を利用するだけです。true
指定されたサービスが存在し、強制終了された場合に戻ります。そうでなければ、それは戻りますfalse
。したがって、結果がfalse
それ以外の場合は、現在のサービスが停止していることが保証されているため、サービスを再起動できます。あなたが見ている場合:)それは良いだろうこれを。
kotlinを使用した別のアプローチ。他のユーザーの回答に触発された
fun isMyServiceRunning(serviceClass: Class<*>): Boolean {
val manager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
return manager.getRunningServices(Integer.MAX_VALUE)
.any { it.service.className == serviceClass.name }
}
コトリン拡張として
fun Context.isMyServiceRunning(serviceClass: Class<*>): Boolean {
val manager = this.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
return manager.getRunningServices(Integer.MAX_VALUE)
.any { it.service.className == serviceClass.name }
}
使用法
context.isMyServiceRunning(MyService::class.java)
以下に示すように、サービスサブクラスで静的ブールを使用してサービスの状態を取得します。
MyService.kt
class MyService : Service() {
override fun onCreate() {
super.onCreate()
isServiceStarted = true
}
override fun onDestroy() {
super.onDestroy()
isServiceStarted = false
}
companion object {
var isServiceStarted = false
}
}
MainActivity.kt
class MainActivity : AppCompatActivity(){
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val serviceStarted = FileObserverService.isServiceStarted
if (!serviceStarted) {
val startFileObserverService = Intent(this, FileObserverService::class.java)
ContextCompat.startForegroundService(this, startFileObserverService)
}
}
}
kotlinの場合、以下のコードを使用できます。
fun isMyServiceRunning(calssObj: Class<SERVICE_CALL_NAME>): Boolean {
val manager = requireActivity().getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
for (service in manager.getRunningServices(Integer.MAX_VALUE)) {
if (calssObj.getName().equals(service.service.getClassName())) {
return true
}
}
return false
}
geekQの応答ですが、Kotlinクラスです。ありがとうgeekQ
fun isMyServiceRunning(serviceClass : Class<*> ) : Boolean{
var manager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
for (service in manager.getRunningServices(Integer.MAX_VALUE)) {
if (serviceClass.name.equals(service.service.className)) {
return true
}
}
return false
}
呼び出し
isMyServiceRunning(NewService::class.java)
ActivityManager.getRunningServices
Android Oから廃止されました
同じクラス名を持つ複数のサービスが存在する可能性があります。
2つのアプリを作成しました。最初のアプリのパッケージ名はcom.example.mock
です。lorem
アプリで呼び出されるサブパッケージとというサービスを作成しましたMock2Service
。したがって、その完全修飾名はcom.example.mock.lorem.Mock2Service
です。
次に、2番目のアプリとというサービスを作成しましたMock2Service
。2番目のアプリのパッケージ名はcom.example.mock.lorem
です。サービスの完全修飾名com.example.mock.lorem.Mock2Service
もです。
これが私のlogcat出力です。
03-27 12:02:19.985: D/TAG(32155): Mock-01: com.example.mock.lorem.Mock2Service
03-27 12:02:33.755: D/TAG(32277): Mock-02: com.example.mock.lorem.Mock2Service
パッケージ名とクラス名の両方を比較するComponentName
ためequals()
、インスタンスを比較することをお勧めしComponentName
ます。また、同じパッケージ名の2つのアプリをデバイスにインストールすることはできません。
のequals()メソッドComponentName
。
@Override
public boolean equals(Object obj) {
try {
if (obj != null) {
ComponentName other = (ComponentName)obj;
// Note: no null checks, because mPackage and mClass can
// never be null.
return mPackage.equals(other.mPackage)
&& mClass.equals(other.mClass);
}
} catch (ClassCastException e) {
}
return false;
}
このコードを使用してください。
if (isMyServiceRunning(MainActivity.this, xyzService.class)) { // Service class name
// Service running
} else {
// Service Stop
}
public static boolean isMyServiceRunning(Activity activity, Class<?> serviceClass) {
ActivityManager manager = (ActivityManager) activity.getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (serviceClass.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}
サービスが別のプロセスまたはAPKに属している場合は、ActivityManagerに基づくソリューションを使用します。
ソースにアクセスできる場合は、静的フィールドに基づくソリューションを使用してください。しかし、ブール値を使用する代わりに、Dateオブジェクトを使用することをお勧めします。サービスの実行中に、その値を「今」に更新し、終了したらnullに設定します。アクティビティから、そのnullまたは日付が古すぎるかどうかを確認できます。これは、実行されていないことを意味します。
進行状況などの詳細情報に沿って実行されていることを示すブロードキャスト通知をサービスから送信することもできます。
TheServiceClassの内部では以下を定義します。
public static Boolean serviceRunning = false;
次に、onStartCommand(...)
public int onStartCommand(Intent intent, int flags, int startId) {
serviceRunning = true;
...
}
@Override
public void onDestroy()
{
serviceRunning = false;
}
次に、if(TheServiceClass.serviceRunning == true)
任意のクラスから呼び出します。
stopService
。少なくともIntentサービスの場合。onDestroy()
すぐに呼び出されますが、onHandleIntent()
まだ実行中です
bindを単純に使用して、autoを作成しない-psを参照。そして更新...
public abstract class Context {
...
/*
* @return {true} If you have successfully bound to the service,
* {false} is returned if the connection is not made
* so you will not receive the service object.
*/
public abstract boolean bindService(@RequiresPermission Intent service,
@NonNull ServiceConnection conn, @BindServiceFlags int flags);
例:
Intent bindIntent = new Intent(context, Class<Service>);
boolean bindResult = context.bindService(bindIntent, ServiceConnection, 0);
なぜ使用しないのですか?getRunningServices()
List<ActivityManager.RunningServiceInfo> getRunningServices (int maxNum)
Return a list of the services that are currently running.
注:このメソッドは、サービス管理タイプのユーザーインターフェイスのデバッグまたは実装のみを目的としています。
ps。Androidのドキュメントが誤解を招く疑いを解消するために、Googleトラッカーで問題を開いた:
https://issuetracker.google.com/issues/68908332
バインドサービスが実際にサービスキャッシュバインダーを介してActivityManagerバインダーを介してトランザクションを呼び出すことがわかるので、バインドを担当するサービスを追跡しますが、バインドの結果は次のとおりです。
int res = ActivityManagerNative.getDefault().bindService(...);
return res != 0;
トランザクションはバインダーを介して行われます:
ServiceManager.getService("activity");
次:
public static IBinder getService(String name) {
try {
IBinder service = sCache.get(name);
if (service != null) {
return service;
} else {
return getIServiceManager().getService(name);
これは、ActivityThreadで次のように設定されます。
public final void bindApplication(...) {
if (services != null) {
// Setup the service cache in the ServiceManager
ServiceManager.initServiceCache(services);
}
これは、メソッドのActivityManagerServiceで呼び出されます。
private final boolean attachApplicationLocked(IApplicationThread thread,
int pid) {
...
thread.bindApplication(... , getCommonServicesLocked(),...)
次に:
private HashMap<String, IBinder> getCommonServicesLocked() {
ただし、「アクティビティ」はなく、ウィンドウパッケージとアラームのみです。
だから私たちは電話に戻る必要があります:
return getIServiceManager().getService(name);
sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
これはコールスルーになります:
mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);
につながる:
BinderInternal.getContextObject()
これはネイティブメソッドです...
/**
* Return the global "context object" of the system. This is usually
* an implementation of IServiceManager, which you can use to find
* other services.
*/
public static final native IBinder getContextObject();
私は今cを掘る時間がないので、レストコールを分析するまで、回答を一時停止します。
ただし、サービスが実行されているかどうかを確認する最良の方法は、バインドを作成することです(バインドが作成されていない場合は、サービスが存在しません)。
私はそれらを面白いと思いました:
/**
* Provide a binder to an already-bound service. This method is synchronous
* and will not start the target service if it is not present, so it is safe
* to call from {@link #onReceive}.
*
* For peekService() to return a non null {@link android.os.IBinder} interface
* the service must have published it before. In other words some component
* must have called {@link android.content.Context#bindService(Intent, ServiceConnection, int)} on it.
*
* @param myContext The Context that had been passed to {@link #onReceive(Context, Intent)}
* @param service Identifies the already-bound service you wish to use. See
* {@link android.content.Context#bindService(Intent, ServiceConnection, int)}
* for more information.
*/
public IBinder peekService(Context myContext, Intent service) {
IActivityManager am = ActivityManager.getService();
IBinder binder = null;
try {
service.prepareToLeaveProcess(myContext);
binder = am.peekService(service, service.resolveTypeIfNeeded(
myContext.getContentResolver()), myContext.getOpPackageName());
} catch (RemoteException e) {
}
return binder;
}
要するに :)
「すでにバインドされているサービスにバインダーを提供します。このメソッドは同期的であり、存在しない場合はターゲットサービスを開始しません。」
public IBinder peekService(Intent service、String resolveType、String callingPackage)はRemoteExceptionをスローします。
*
public static IBinder peekService(IBinder remote, Intent service, String resolvedType)
throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken("android.app.IActivityManager");
service.writeToParcel(data, 0);
data.writeString(resolvedType);
remote.transact(android.os.IBinder.FIRST_CALL_TRANSACTION+84, data, reply, 0);
reply.readException();
IBinder binder = reply.readStrongBinder();
reply.recycle();
data.recycle();
return binder;
}
*
ActivityManager::getRunningServices
ベースの回答の私のkotlin変換。この関数をアクティビティに入れます
private fun isMyServiceRunning(serviceClass: Class<out Service>) =
(getSystemService(ACTIVITY_SERVICE) as ActivityManager)
.getRunningServices(Int.MAX_VALUE)
?.map { it.service.className }
?.contains(serviceClass.name) ?: false
簡単に言うと... :)
最も適切なソリューションはSharedPreferences
、サービスが実行されているかどうかに関係なく、キーと値のペアを保持することです。
論理は非常にまっすぐです。サービスクラスの任意の位置。サービスが実行されているかどうかについてのフラグとして機能するブール値を入力します。次に、この値をアプリケーションの任意の場所で読み取ります。
私のアプリで使用しているサンプルコードは以下のとおりです。
私のServiceクラス(Audio Streamのサービス)では、サービスが稼働しているときに次のコードを実行します。
private void updatePlayerStatus(boolean isRadioPlaying)
{
SharedPreferences sharedPref = this.getSharedPreferences(getString(R.string.str_shared_file_name), Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putBoolean(getString(R.string.str_shared_file_radio_status_key), isRadioPlaying);
editor.commit();
}
次に、アプリケーションのアクティビティで、次のコードを使用してサービスのステータスを確認しています。
private boolean isRadioRunning() {
SharedPreferences sharedPref = this.getSharedPreferences(getString(R.string.str_shared_file_name), Context.MODE_PRIVATE);
return sharedPref.getBoolean(getString(R.string.str_shared_file_radio_status_key), false);
}
特別な権限なし、ループなし...簡単な方法、クリーンなソリューション:)
お役に立てれば。
onDestroy
は、サービスが終了したときに常に呼び出されるわけではありません。たとえば、サービスonDestroy
が呼び出されずにメモリ不足の状況で終了するのを見てきました。