2

ここのチュートリアル/ガイドに従って、サービスを使用する最初のアプリをコーディングしていますhttp://www.vogella.com/articles/AndroidServices/article.html サービスが機能しており、ブロードキャストレシーバーの作成について説明していますBOOT_COMPLETED は機能し、数分ごとにサービスを実行できます。

私が抱えている問題は、ユーザーが電話を再起動するまで機能しないことです。サービスはアクティビティで開始されますが、デバイスが再起動されていない限り、アクティビティで終了するようです。

再起動せずに最初に実行したときにアクティビティからスケジューラを開始する方法はありますか?

スケジューラの私のコードは次のとおりです。

public class ScheduleReceiver extends BroadcastReceiver {

    // Restart service every 30 seconds
    private static final long REPEAT_TIME = 1000 * 60; // check every minute.  

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d("schedulereceiver", "starting schedule");
        AlarmManager service = (AlarmManager) context
                .getSystemService(Context.ALARM_SERVICE);
        Intent i = new Intent(context, StartServiceReceiver.class);
        PendingIntent pending = PendingIntent.getBroadcast(context, 0, i,
                PendingIntent.FLAG_CANCEL_CURRENT);
        Calendar cal = Calendar.getInstance();
        // Start 30 seconds after boot completed
        cal.add(Calendar.SECOND, 30);
        //
        // Fetch every 30 seconds
        // InexactRepeating allows Android to optimize the energy consumption
        service.setInexactRepeating(AlarmManager.RTC_WAKEUP,
                cal.getTimeInMillis(), REPEAT_TIME, pending);

        // service.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(),
        // REPEAT_TIME, pending);

    }
}

私のマニフェストファイルは次のようになります。

    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

    <uses-sdk android:minSdkVersion="8" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >

        <activity
            android:name=".ProximityActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <service
            android:name=".ProximityService"
            android:enabled="true"
            android:icon="@drawable/ic_launcher"
            android:label="@string/service_name" >
        </service>

        <receiver android:name="ScheduleReceiver" >
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
            </intent-filter>
        </receiver>
        <receiver android:name="StartServiceReceiver" >
        </receiver>
    </application>

</manifest>
4

2 に答える 2

2

ここでの基本的な問題は、2 つの異なるシナリオでタイマーを設定したいということです。

ブート時にセットアップしたいと考えています。また、ユーザーが最初にアプリケーションを起動したときにセットアップしたいと考えています。(インストール時にそれを行うことはできません、私は恐れています)。

これを行うために私が見つけた最良の方法は、最初にタイマーを設定したときに、タイマーを設定したことをファイルシステムに記録することです。

ScheduleReceiver で、2 つの public static メソッドを作成します。

public static void startupActions(Context ctx) {
    setupTimer();
    try {
        ctx.openFileOutput(".inited", Context.MODE_PRIVATE).close();
    } catch (IOException e) {
        throw new Error(e);
    }
}

onReceive() メソッドから上記のメソッドを呼び出します。すぐに再利用します。

public static boolean hasStartupRun(Context ctx) {
    try {
        ctx.openFileInput(".inited").close();
        return true;
    } catch (IOException e) {
        return false;
    }
}

これらをメイン アクティビティの onCreate() メソッドで使用して、タイマーを開始する必要があるかどうかを示します。

    if (! ScheduleReceiver.hasStartupRun(this)) {
        ScheduleReceiver.startupActions(this);
    }

再インストールしてもタイマーはクリアされないようです。そのため、他に心配する必要がある唯一の不具合は、タイマー (またはその他の一連の起動アクション) を何らかの方法で変更する必要がある場合です。これを処理するには、インテントを変更して古いものが処理されないようにし、ファイルの名前を変更して、新しいものがスケジュールされるようにすることができます。

データベースの作成、設定ファイルなど、他の永続的なフラグを使用することもできますが、この方法でファイルを作成することは、BroadcastReceiver から行うと考えることができる最も簡単な方法です。

あなたの質問で少し困惑したことの1つは、あなたのサービスがアクティビティで「開始」および「終了」することです。

この質問は数か月前のものだと思いますが、同様の立場にある可能性のある他の読者のために...少し混乱しているように聞こえます。サービスの onCreate() メソッドはアクティビティの開始時に呼び出され、onDestroy() メソッドはアクティビティの「終了」時に呼び出されるということですか? または、アクティビティがそれを開始またはバインドしますが、プロセスが強制終了されたときに消えて二度と戻ってこないということですか?

これを取り上げる理由は、サービスの内容によっては、サービスを開始している他のコードを削除して、タイマーだけに頼る必要がある場合があるためです。

サービスとアクティビティのライフサイクルはまったく異なり、無関係であり、プロセスのライフサイクルはどちらともまったく異なります。アクティビティからサービスと対話したい場合は、タイマーから開始するだけでなく、それにバインドすることもできます。両方やっても全然OK!(ただし、多くの場合、バックグラウンドまたはタイマーベースのサービスと、バックグラウンド サービスとアクティビティの両方がバインドされるコントロール/構成サービスの 2 つのサービスを使用する方が適切です)。

すべてのバインドをアンバインドと一致させ、すべての開始を Service.stopSelfResult(int) (サービスが開始されるたびに作業単位を実行する場合) または Context.stopService(Intent) (サービスが開始される場合) と一致させるようにしてください。発信者の必要に応じて継続的に行われます)、そのため、システムはいつサービスが終了したかを認識します。

また、startService を使用している場合は、onStartCommand(...) から返されるフラグを慎重に選択してください。

于 2012-12-29T09:44:25.750 に答える
0

Service問題は、単一のインスタンスとして実行されることです。同じサービスを開始するたびに、 onStartCommand() メソッドのみが呼び出されます。したがって、alarmManager で使用しても、Service再実行が期待できない場合があります。

詳細については、次を確認してください: http://developer.android.com/guide/components/services.html#StartingAService

于 2012-06-25T19:34:45.890 に答える