2016-10-07 11 views
0

だから、私が書いたappwidgetのいくつかの奇妙な行動を見ている。アプリウィジェットはGoogleサウンド検索でハイジャックされていますか?

ウィジェット自体は非常に単純です。永続ストレージからいくつかの値を読み込んだ後、テキストとして表示します。レイアウトに空想がありません - Linear LayoutTextViewの子を持つFrameLayoutルート要素です。

ウィジェットには、簡単な設定アクティビティが関連付けられています。

奇妙な振る舞いは、ユーザーが設定作業を終了した後、ウィジェットが最初に「問題の読み込みウィジェット」を表示してから数秒後に「Googleサウンド検索」ボタンが表示されますGoogleサウンド検索を起動します)。次に、数秒後に、最終的に予想される表示が表示されます。

私は今すぐ自分のコードから離れているので、今夜までコードスニペットを投稿するまで待つ必要があります。しかし、その間に誰かがそのようなことが起こる可能性についていくつかの洞察を提供することができますか?誰もこれを経験したことがありますか?どのように別のウィジェット "ハイジャック"私の鉱山できますか?

おかげで、 -Ron

はここにいくつかのスクリーンショットです: Step 1 - Problem Loading Widget Step 2 - Google Sound Search hijacks widget Step 3 - Success! Widget displays properly

答えて

0

[OK]を、ので、私はそれを考え出しました。他の誰かがこれにぶつかる場合に備えてここに投稿してください。 Androidデベロッパーのドキュメントはここで少し誤解を招くと思います。 documentation provided by googleによって推奨され

Intent intent = new Intent(); 
    intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE); 
    intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, new int[] {mAppWidgetId}); 
    intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId); 
    setResult(RESULT_OK, intent); 
    sendBroadcast(intent); 
    finish(); 

余分EXTRA_APPWIDGET_IDとの意図を提供する:

問題は、私の設定の活動に、私が最後にこのコードを持っていたということでした。

RemoteViews views = new RemoteViews(context.getPackageName(), 
R.layout.example_appwidget); 
appWidgetManager.updateAppWidget(mAppWidgetId, views); 

私は両方でプレゼンテーションロジックを置くのアイデアを好きではありませんでした:同じ文書は、あなたがRemoteViewを作成し、そのようなAppWidgetManager.updateAppWidget()を呼び出すことで、ウィジェットのビューを更新する必要があると言うことが

、設定アクティビティとウィジェットクラスのため、代わりに設定アクティビティの最後にインテントをブロードキャストして、ウィジェットに自身を再描画するよう指示しました。だからこそ私はsetResult()sendBroadcast()の最後にいる。ドキュメントでは、構成アクティビティを使用しているときにonUpdate()コールバックが呼び出されないことを示しています。だから、これは必要と思われた。私は、メソッドをトリガーするように、ACTION_APPWIDGET_UPDATEEXTRA_APPWIDGET_IDSをインテントに追加しました。この練習は、このSO answerによって推奨されました(ただし、活動結果の意図に含まれていませんが、2つを分けてみましたが効果はありませんでした)。

「Googleサウンド検索」ウィジェットがどのようにそこに入ったのか正確にはわかりません。また、インテントがどのように相互作用して観測結果を生成するかの仕組みを完全に理解していません。しかし、上記のコードをドキュメントに記載されているコードに置き換えるとすぐに、ウィジェットが正しく更新されました。

Intent resultIntent = new Intent(); 
    resultIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId); 
    setResult(RESULT_OK, resultIntent); 
    finish(); 

これは、構成アクティビティがウィジェットのビューを更新する必要があるというドキュメンテーションのステートメントと矛盾するようです。以下のような構成アクティビティー結果を提供するだけで、ウィジェットのonUpdate()メソッドがトリガーされ、ウィジェット自体を再描画できます。私は、API 23を実行しているエミュレータとSamsungのAndroidの味を実行しているSamsungのデバイスで動作を確認しました。

+0

ドキュメントが存在し、何の矛盾音ではありません。もしあなたがそれに正確に従えば、すべてが良いでしょう。私自身の答えを見てください。 –

1

ウィジェットの問題のカップルがありますし、それらのすべてへの回答(そのように任意のコードを投稿しませんでしたが、私の文のいくつかは仮定に基づいている)があります。

「問題ローディングウィジェット」これは、ウィジェットが初期化され、レイアウトが更新される前にAndroidが使用するデフォルトのビューです。ウィジェットは、あなたはおそらく、ウィジェットのonReceive方法で問題を持っている間違ったレイアウトを示している場合

android:initialLayout="@layout/my_cool_widget_loading_message" 

:単にあなたのウィジェットXML設定に次の行を追加します(ロードメッセージの代わりに、問題のメッセージを表示します)。 onReceiveは、ブロードキャストがその特定のウィジェット用であるかどうかにかかわらず、すべてのウィジェットに対して呼び出されます。 AndroidのAppWidgetProviderはappwidget Idによってブロードキャストをフィルタリングし、他のメソッド(onUpdateなど)にディスパッチします。

参照:https://developer.android.com/reference/android/appwidget/AppWidgetProvider.html#onReceive(android.content.Context、android.content.Intent)。

onReceiveをオーバーライドする場合は、super.onReceive(Context、Intent)をコールして、ほかのメソッドが他のウィジェット用のコールを受け取らないようにする必要があります。

ウィジェットの設定が完了しました。あなたがGoogleのドキュメントに従うならば、それはすべてうまく動作します。私が行う唯一の改善は、あなたが参照している私の他の答えが示唆していることです(https://stackoverflow.com/a/14991479/534471)。これは2つの放送を送信しません。 setResult()/ finish()部分はconfigアクティビティを終了するだけで、結果がRESULT_CANCELEDかRESULT_OKかによってAndroidに実際にウィジェットを追加するかどうかを知らせます。あなたのコードは動作しませんコードは次のとおりです。すべての

Intent intent = new Intent(); 
    intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE); 
    intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, new int[] {mAppWidgetId}); 
    intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId); 
    setResult(RESULT_OK, intent); 
    sendBroadcast(intent); 
    finish(); 

まずAppWidgetManager.EXTRA_APPWIDGET_IDSバージョンを使用して、あなたが良いなら、二回appWidgetIdを追加する必要はありません第二に、あなたが同じテントを使用していますあなたがそのインテントでアクションを設定したときに何が起こるのかは文書化されていませんが、Androidウィジェットでの私の経験は、あなたがドキュメントに正確に固執する必要があるか、 (あなたが遭遇するもののような)奇妙な問題を持つことになります。だから2つの異なるインテントを使用してください。 活動の結果:

Intent resultValue = new Intent(); 
resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId); 
setResult(RESULT_OK, resultValue); 
finish(); 

放送:

Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE, null, this, MyWidget.class); 
     intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, new int[] {mAppWidgetId}); 
     sendBroadcast(intent); 
+0

あなたのポストをありがとう、私はそれからいくつかを学んだ。私はsetResult()がブロードキャストを送信して(私の答えを編集する)と間違っていたことに気付きました。そして今、 "Problem Loading Widget"がどこから来たのか分かります。しかし、私はまだ動作がドキュメントから少し離れていることを維持しています。私は、setResult()(別の要件としてdocs状態)を使うだけで、OSが設定完了後にウィジェットを描画するのに十分であると考えています。あなたが提案した放送を追加しても効果はありません。これはAPIバージョンの違いでしょうか? 23を使う。 – rothloup

+1

これは、ウィジェットが新しく作成された場合にのみ当てはまりますが、ウィジェットがすでにホーム画面に追加された後にそのウィジェットを設定するためにアクティビティが使用されている場合は無効です(私のウィジェットの一部には同じ設定アクティビティを開く設定ボタンがあります)。これはAPIバージョンとは関係がありません。私は2.2から7.0までのAndroidバージョンの範囲で、約30種類の実デバイスで自分のウィジェットをテストしています。 –

+0

ああ、そうです。私のウィジェットは配置時にのみ構成されます。既存のウィジェットを再設定するときは、念頭に置いておきます。ありがとうございました! – rothloup

関連する問題