web-dev-qa-db-ja.com

Android:「アプリケーションレベル」の一時停止と再開

アクティビティのonPauseとonResumeと同様に、アプリケーションレベルの一時停止と再開を取得しようとしています。この機能を備えたAPIはないことを私は知っています。

私はこの投稿をフォローしようとしています: http://curioustechizen.blogspot.com/2012/12/Android-application-level-pause-and.html

しかし、私は今のところ運がありませんでした。

誰かがこれを達成することができましたか?どのパラダイムを使用しましたか?

この質問にコードを貼り付ける必要がある場合はお知らせください。助けてくれてありがとう

14
TMacGyver

この問題のもう1つの解決策は、すべてのアクティビティからのonStart()およびonStop()呼び出しの数を追跡することです。例:

まず、カウントを保持するクラスを作成します。

public class ActiveActivitiesTracker {
    private static int sActiveActivities = 0;

    public static void activityStarted()
    {
        if( sActiveActivities == 0 )
        {
            // TODO: Here is presumably "application level" resume
        }
        sActiveActivities++;
    }

    public static void activityStopped()
    {
        sActiveActivities--;
        if( sActiveActivities == 0 )
        {
            // TODO: Here is presumably "application level" pause
        }
    }
}

次に、すべてのアクティビティで、activityStarted()メソッドとactivityStopped()メソッドを呼び出すだけです。

@Override
public void onStart() {
    super.onStart();
    ActiveActivitiesTracker.activityStarted();
}

@Override
public void onStop() {
    super.onStop();
    ActiveActivitiesTracker.activityStopped();
}
6
paulscode

私も同じ問題を抱えていました。私の目的は、ユーザーがアプリを放棄した場合にアプリをロックすることでした。簡単な目的で、実装は簡単だと思いました。しかし、私が見つけたすべての解決策は複雑になる方法でした。それで私は簡単な解決策にたどり着きました:時間ベースのロック。

基本的には次のように機能します。

  • カウントダウンを開始してアプリをonPauseにロックします
  • OnResumeでカウントダウンを停止します
  • OnResumeが時間内に呼び出されない場合は、lockedに変更します

そのため、私は小さな小さなクラスを作成しました。

public class ApplicationLock {

private static final String TAG = ApplicationLock.class.getSimpleName();
private static final int LOCK_TIME = 1000; //lock after a second
private static boolean lock = true; //default is locked
private static Handler handler = new Handler();
private static Runnable runnable = new Runnable() {
    @Override
    public void run() {
        lock = true;
        Log.i("ActivityTracker", "App locked");
    }
};

public static boolean activityStarted()
{
    handler.removeCallbacks(runnable);
    if(lock)
    {
        Log.i(TAG, "App resumed - LOCKED");
        return true;
    }else{
        Log.i(TAG, "App resumed - NOT LOCKED");
        return false;
    }
}

public static void activityStopped()
{
    handler.postDelayed(runnable, LOCK_TIME);
    Log.i(TAG, "App paused - Starting countdown");

}

アクティビティonPause()でactivityStopped()を呼び出し、onResume()でactivityStarted()を呼び出すだけです。 activityStarted()の結果を確認してください。 trueが返された場合は、アプリをロックします。アプリの向きが変更された場合、onResumeはonPauseの直後に呼び出されるため、アプリはロックされません。

このソリューションはすべてのシナリオに適合するとは限りませんが、私の場合は最良のソリューションでした。さらに、カウントダウンを変更して、ユーザーエクスペリエンスを向上させることができます(ユーザーが間違ったボタンを押して数秒でアプリに戻るため、アプリをロックする必要はありません)。これが他の誰かに役立つことを願っています。

4
AlbAtNf

いくつかのアクティビティでGPS機能を提供するサービスを利用したアプリでこれと非常によく似たことをしました。アイデアは、サービスを使用したアクティビティの1つが表示されている場合にのみサービスを提供し、何も表示されていない場合はサービスを提供しないことでした。あなたの場合、すべてのアクティビティがサービスにフックされ、サービスのonCreate()メソッドとonDestroy()メソッドにフックすることで、アプリケーション全体がいつ一時停止または再開されたかがわかります。

簡略化した例を次に示します。

必要なコンポーネント(これらは、再利用したい場合はユーティリティクラスに配置できます。または、アクティビティクラスごとに用意しました)。

private boolean mAppActiveServiceBound = false;
private AppActiveService mAppActiveService = null;
private ServiceConnection mAppActiveConnection = new ServiceConnection() {
    public void onServiceConnected( ComponentName className, IBinder service ) {
        mAppActiveService = ( (AppActiveService.AppActiveBinder) service ).getService();
    }
    public void onServiceDisconnected( ComponentName className ) {
        mAppActiveService = null;
    }
};

次に、各アクティビティのonStart()メソッドとonStop()メソッドで次のようにします。

@Override
public void onStart() {
    super.onStart();
    mAppActiveServiceBound = bindService( new Intent( this, AppActiveService.class ), mAppActiveConnection, Context.BIND_AUTO_CREATE );
}

@Override
public void onStop() {
    super.onStop();
    if( mAppActiveServiceBound ) {
        unbindService( mAppActiveConnection );
        mAppActiveServiceBound = false;
    }
}

そして最後に、サービス自体:

public class  AppActiveService extends Service {
    // Receives interactions from clients:
    private final IBinder mBinder = new AppActiveBinder();

    /**
     * Provides a handle to the bound service.
     */
    public class  AppActiveBinder extends Binder {
        AppActiveService getService() {
            return AppActiveService.this;
        }
    }

    @Override
    public void onCreate(){
        // TODO: Here is presumably "application level" resume
    }

    @Override
    public void onDestroy(){
        // TODO: Here is presumably "application level" pause
    }
}
1
paulscode