web-dev-qa-db-ja.com

ウィジェットからアクティビティを起動する

本当に簡単なはずのことをしようとしていますが、それは私を夢中にさせます。ホーム画面ウィジェットが押されたときに、ウィジェットの構成アクティビティなどのアクティビティを起動しようとしています。 Android Developers Webサイトのチュートリアル、およびいくつかの非公式のチュートリアルでさえもWord for Wordに従っていましたが、機能しないため重要なものを見逃しているに違いありません。

コードは次のとおりです。

public class VolumeChangerWidget extends AppWidgetProvider {

public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds){
    final int N = appWidgetIds.length;

    for (int i=0; i < N; i++) {
        int appWidgetId = appWidgetIds[i];

        Log.d("Steve", "Running for appWidgetId " + appWidgetId);
        Toast.makeText(context, "Hello from onUpdate", Toast.LENGTH_SHORT);
        Log.d("Steve", "After the toast line");

        Intent intent = new Intent(context, WidgetTest.class);

        PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);

        RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget);
        views.setOnClickPendingIntent(R.id.button, pendingIntent);

        appWidgetManager.updateAppWidget(appWidgetId, views);
    }
}

}

ウィジェットをホーム画面に追加すると、Logcatは2つのデバッグ行を表示しますが、Toastは表示しません。 (なぜそうなのでしょうか?)ただし、PendingIntentが関連付けられたボタンをクリックしても、何も起こらないというのは面倒です。メインアクティビティ内からIntentをセットアップすると正常に起動するため、「WidgetTest」アクティビティを実行できることを知っています。

重要な場合、Androidマニフェストファイル:

<manifest xmlns:Android="http://schemas.Android.com/apk/res/Android"
package="com.steve"
Android:versionCode="1"
Android:versionName="1.0">
<application Android:icon="@drawable/icon" Android:label="@string/app_name">
    <activity Android:name=".Volume_Change_Program"
              Android:label="@string/app_name">
        <intent-filter>
            <action Android:name="Android.intent.action.MAIN" />
            <category Android:name="Android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

    <activity Android:name=".WidgetTest"
              Android:label="@string/hello">
        <intent_filter>
            <action Android:name="Android.intent.action.MAIN"/>
            <category Android:name="Android.intent.category.LAUNCHER"/>
        </intent_filter>
    </activity>

    <receiver Android:name=".VolumeChangerWidget" >
        <intent-filter>
            <action Android:name="Android.appwidget.action.APPWIDGET_UPDATE" />
        </intent-filter>
        <meta-data  Android:name="Android.appwidget.provider"
                    Android:resource="@xml/volume_changer_info" />
    </receiver>

</application>
<uses-sdk Android:minSdkVersion="3" />

障害の場所をテストする方法はありますか?つまりボタンがPendingIntentに適切にリンクされていない、またはPendingIntentまたはIntentがWidgetTest.classを見つけていないなどの障害ですか?

ご協力ありがとうございました!

スティーブ

36
Steve Haley

私は同じ問題を抱えていました。修正は、appwidgetマネージャーを介して更新を呼び出すことであることを発見しました。 onEnabledでこれを行う方法の例を次に示します。デバイスの電源を入れたときにクリックインテントも初期化されるように、onEnabledとonUpdatedの両方で実行する必要があるようです。

@Override 
    public void onEnabled(Context context) {  
          //Log.v("toggle_widget","Enabled is being called"); 

          AppWidgetManager mgr = AppWidgetManager.getInstance(context); 
          //retrieve a ref to the manager so we can pass a view update 

          Intent i = new Intent(); 
          i.setClassName("yourdoman.yourpackage", "yourdomain.yourpackage.yourclass"); 
          PendingIntent myPI = PendingIntent.getService(context, 0, i, 0); 
          //intent to start service 

        // Get the layout for the App Widget 
        RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.togglelayout); 

        //attach the click listener for the service start command intent 
        views.setOnClickPendingIntent(R.id.toggleButton, myPI); 

        //define the componenet for self 
        ComponentName comp = new ComponentName(context.getPackageName(), ToggleWidget.class.getName()); 

        //tell the manager to update all instances of the toggle widget with the click listener 
        mgr.updateAppWidget(comp, views); 
} 
9
mylock

これを持ってきてくださいway死者から戻ったのですが、私は同様の問題を抱えていたので、ついに解決したと思います...あなたのように、RemoteViewにアタッチしたPendingIntentがありました。時には機能し、時には失敗することもありました。私を夢中にさせていました。

PendingIntent.getActivty()のツールチップから私が見つけたのは:

アクティビティは既存のアクティビティのコンテキスト外で開始されるため、IntentでIntent.FLAG_ACTIVITY_NEW_TASK起動フラグを使用する必要があることに注意してください。

だから、私は追加しました:

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

これまでに見たサンプルコードはありませんが、問題は解決しました。これで、設定アクティビティが確実に起動されます。

うまく機能している完全なコード...

Intent intent = new Intent(context, Settings.class);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appId);  // Identifies the particular widget...
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// Make the pending intent unique...
intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
PendingIntent pendIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);

RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.wwwidget);
views.setOnClickPendingIntent(R.id.widget, pendIntent);
appWidgetManager.updateAppWidget(appId,views);
22
Brent Chartrand

こちらの情報、Wordウィジェットのサンプル、および チュートリアルはこちら

       Intent intent = new Intent(Intent.ACTION_MAIN, null);
      intent.addCategory(Intent.CATEGORY_LAUNCHER);
      // first param is app package name, second is package.class of the main activity
      ComponentName cn = new ComponentName("com....","com...MainActivity");
      intent.setComponent(cn);
      intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
      PendingIntent myPI = PendingIntent.getActivity(context, 0, intent, 0); 

    RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_Word); 


    views.setOnClickPendingIntent(R.id.widget, myPI); 

    AppWidgetManager mgr = AppWidgetManager.getInstance(context); 
    mgr.updateAppWidget(comp, views); 
7
kdahlhaus

Toastが表示されない問題は簡単です。show()を呼び出さないでください。

Toast.makeText(context, "Hello from onUpdate", Toast.LENGTH_SHORT).show();

の代わりに

Toast.makeText(context, "Hello from onUpdate", Toast.LENGTH_SHORT);
4
JohanS

スティーブ、

問題を発見しましたか?私はウィジェットを使用していますが、onEnabledトリックを使用しなくても正常に機能します。なぜあなたに向いていないのか興味があります。

私の推測:元のコードで試してください

PendingIntent pendingIntent = PendingIntent.getActivity(context, 1, intent, 0);

の代わりに

PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
1
Fedor

もう1つのポイント:ウィジェットから呼び出されるアクティビティは、マニフェストファイルで宣言する必要があります。例外はスローされず、何も起こらないように見えます...

0
Stephan

私はこのスレッドが古いことを知っていますが、...他の答えはあなたの焼けたトーストの問題を説明しています。ポップアップアクティビティがタッチで起動しない理由については、onUpdate()メソッドを起動して呼び出すために、「更新」アクションを有効にする必要があります。そのためには、次のような「APPWIDGET_UPDATE」アクションを追加する必要があると思います。

<activity Android:name=".WidgetTest" Android:label="@string/hello">
    <intent_filter>
        <action Android:name="Android.appwidget.action.APPWIDGET_UPDATE" />
        <action Android:name="Android.intent.action.MAIN"/>
        <category Android:name="Android.intent.category.LAUNCHER"/>
    </intent_filter>
</activity>

同様に、これらのメソッドもオーバーライドする場合は、APPWIDGET_ENABLEDアクションとAPPWIDGET_DISABLEDアクションを追加します。

これは、呼び出したいオーバーライドされたメソッドを宣言する必要がある非常に珍しいAPIのようです。親のカスタムバージョンを取得する通常の方法は、単純にオーバーライド/実装することです。この奇妙なパターンには十分な理由があるかもしれませんが、これは私が以前に見たJavaパターンではありません。したがって、多くのアプリウィジェット作成者をつまずかせるでしょう。このメカニズムがなければ、アプリウィジェットは十分に混乱しませんでした。

0
Melinda Green

res/xml/volume_changer_info.xmlで構成アクティビティを定義する必要があります。このタグを追加して、構成アクティビティへの完全修飾パスを指定します。

Android:configure = ""


例えば.

<appwidget-provider xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:minWidth="200dip"
    Android:minHeight="100dip"
    Android:updatePeriodMillis="60000"
    Android:initialLayout="@layout/widget_loading"
    Android:configure = "org.raza.ConfigureWidgetActivity"/>
0
Raza

ウィジェットをホーム画面に追加すると、Logcatは2つのデバッグ行を表示しますが、Toastは表示しません。 (なぜ考えないのですか?)

ToastsからBroadcastReceiverを起動しようとしないでください。

障害の場所をテストする方法はありますか?

LogCatを見るには、adb logcat、DDMS、またはEclipseのDDMSパースペクティブ。指定したIntentに一致するアクティビティが見つからないという警告が表示される場合があります。

明らかな問題は見当たりません。 私の本の例の1つ を覗いてみて、それがあなたに効果があるかどうか、そして何が起きているのか考えてくれるかどうかを確認したいかもしれません。

0
CommonsWare