1

Android ウィジェットを動作させるために非常に単純なコードをいくつか試していますが、うまくいきません。私はあちこちを見回しましたが、良い答えが見つかりませんでした。

私が(今のところ)欲しいのは、ウィジェットがタッチされたときにカウンターをインクリメントし、現在の値を表示することだけです。

これは私の AppWidgetProvider です:

public class WordWidget extends AppWidgetProvider
{
    Integer touchCounter = 0;

    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds)
    {
        //This is run when a new widget is added or when the update period expires.
        Log.v("wotd",  "Updating " + appWidgetIds.length + " widgets");

        for(int x = 0; x < appWidgetIds.length; x++)
        {
            Integer thisWidgetId = appWidgetIds[x];

            RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widgetlayout);
            remoteViews.setTextViewText(R.id.mainText, touchCounter.toString());

            Intent widgetIntent = new Intent(context, WordWidget.class);
            widgetIntent.setAction("UPDATE_NUMBER");

            PendingIntent widgetPendingIntent = PendingIntent.getBroadcast(context, 0, widgetIntent, 0);

            remoteViews.setOnClickPendingIntent(R.id.widgetLinearLayout, widgetPendingIntent);
            appWidgetManager.updateAppWidget(thisWidgetId, remoteViews);
        }
    }

    @Override
    public void onReceive(Context context, Intent intent)
    {
        Log.v("wotd", "In onReceive with intent=" + intent.toString());
        if (intent.getAction().equals("UPDATE_NUMBER"))
        {
            Log.v("wotd", "In UPDATE_NUMBER");
            touchCounter++;
            RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widgetlayout);
            remoteViews.setTextViewText(R.id.mainText, touchCounter.toString());
        } else
        {
            Log.v("wotd", "In ELSE... going on to super.onReceive()");
            super.onReceive(context, intent);
        }
    }
}

これは私のマニフェストの一部です:

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

    <receiver
        android:icon="@drawable/ic_launcher"
        android:name="com.example.mywidget.WordWidget"
        android:label="@string/app_name">
        <intent-filter>
            <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
            <action android:name="UPDATE_NUMBER" />
        </intent-filter>

        <meta-data
            android:name="android.appwidget.provider"
            android:resource="@xml/widgetinfo" />
    </receiver>

</application>

ログは、ホーム画面に配置された直後、およびタッチされた後に onReceive() が呼び出されることを示していますが、数は増加しません。ウィジェットがどのように機能するか完全には理解できませんが、onUpdate() の後でウィジェットは強制終了されますか? これを行うには、ある種の永続ストレージを使用する必要がありますか?

また、現在別のウィジェットを追加すると、どちらかをタッチしただけでも同じ値が表示され、増加します。ウィジェットごとに独自のカウンターを持つ方法はありますか?

ありがとう!

4

1 に答える 1

12

実際、あなたはあなたの質問に答えました。しかし、いくつかのことを明確にしましょう:

A. ホーム画面にある限り、AppWidget は強制終了されません。しかし、それらはあなたのものではありません。それらはホームアプリケーションのプロセスで実行されています。より具体的には、ビューがホーム アプリケーションのプロセスで実行されているため、ウィジェットが表示されますが、期待どおりに動作しません。これが、ビューの代わりに RemoteViews を使用して更新する理由です。 .

B. 一方、AppWidgetProviders (あなたの場合は WordWidget クラス) は、onReceive メソッドが終了するとすぐに破棄されます。それらのすべての変数は、onReceive メソッドが呼び出されるたびに再初期化されます。これが、あなたの数が決して増えない理由です。AppWidgetProvider の目的は、ウィジェットの RemoteViews を更新し、登録されたブロードキャストが到着したことをアプリケーションに通知することです。

C. AppWidgetProvider の onUpdate メソッドは、更新する必要があるウィジェット ID を持つ配列を提供します。これは、ウィジェット インスタンスとその ID の数を取得するために使用できる唯一のコード ポイントです。RemoteViews のため、ウィジェットのビューから有用な値を取得する方法はありません (たとえば、TextView からカウンター値を読み取ることはできません)。そのため、提供された情報を使用し、ウィジェット ID ごとにカウンター値を永続化する必要があります。次の onUpdate が呼び出されると、ストレージから値を読み取り、値を増やし、新しい値でウィジェットを更新してから、新しい値を保存します。

D. 自分自身を更新するときに、ウィジェットが多くのことや遅いこと (ネットワーキングなど) を行う必要がある場合は、このためのサービスの使用を検討する必要があります。しかし、あなたの場合(数を増やすため)、永続ストレージまたは他の場所にカウンターを永続化する限り、アプローチは問題ありません。

最後に、「UPDATE_NUMBER」アクションを受信しない場合にのみ、onReceive オーバーライドで「super.onReceive」を呼び出していることに気付きました。良い理由 (それは別の話です) がない限り、オーバーライドの最初または最後のコマンドとして常に super.onReceive を呼び出します。

お役に立てれば...

于 2012-05-13T15:48:11.067 に答える