App Widget はWebView
を直接サポートしていませんが、ImageView
(サポートされています)と次のような手法を使用することは可能ですか?説明 ここImageView
の画像を生成するには? WebView
は直接使用されませんが、ImageView
の画像を提供するためにバックグラウンドでのみ使用されます。
あなたのマイレージは変わるかもしれませんが、これは明らかに、少なくとも私のデバイスでは可能です。
マニフェストでは、ウィジェットの_<receiver>
_を通常どおりに登録し、Service
とその画像キャプチャを処理するWebView
も登録します。
_<manifest ... >
...
<uses-permission Android:name="Android.permission.INTERNET" />
<uses-permission Android:name="Android.permission.SYSTEM_ALERT_WINDOW" />
<application ... >
...
<receiver
Android:name=".WebWidgetProvider"
Android:label="@string/widget_name" >
<intent-filter>
<action Android:name="Android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
Android:name="Android.appwidget.provider"
Android:resource="@xml/widget_info" />
</receiver>
<service Android:name=".WebShotService" />
</application>
</manifest>
_
ウィジェットの情報ファイル_widget_info.xml
_で、最小サイズを4 x2に設定しました。
_<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:initialLayout="@layout/widget_layout"
Android:minWidth="292dip"
Android:minHeight="146dip" />
_
この例では、ウィジェットのレイアウト_widget_layout.xml
_は単に_ImageView.
_です。
_<ImageView xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:id="@+id/widget_image"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:scaleType="fitXY"
Android:src="@drawable/ic_launcher" />
_
この例のAppWidgetProvider
は、同じ_ACTION_APPWIDGET_UPDATE
_を使用してAlarmManager
で独自の更新をトリガーしているため、onUpdate()
メソッドのみをオーバーライドしています。アクティブなウィジェットがある限り、サンプルのアラームは30秒ごとに発生することに注意してください。ウィジェットの更新にはかなりのコストがかかる可能性があるため、テスト以外でこれを実行することはおそらく望ましくありません。
_public class WebWidgetProvider extends AppWidgetProvider {
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
// We can't trust the appWidgetIds param here, as we're using
// ACTION_APPWIDGET_UPDATE to trigger our own updates, and
// Widgets might've been removed/added since the alarm was last set.
final int[] currentIds = appWidgetManager.getAppWidgetIds(
new ComponentName(context, WebWidgetProvider.class));
if (currentIds.length < 1) {
return;
}
// We attach the current Widget IDs to the alarm Intent to ensure its
// broadcast is correctly routed to onUpdate() when our AppWidgetProvider
// next receives it.
Intent iWidget = new Intent(context, WebWidgetProvider.class)
.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE)
.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, currentIds);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, iWidget, 0);
((AlarmManager) context.getSystemService(Context.ALARM_SERVICE))
.setExact(AlarmManager.RTC, System.currentTimeMillis() + 30000, pi);
Intent iService = new Intent(context, WebShotService.class);
context.startService(iService);
}
}
_
Service
で、WebView
をインスタンス化し、それをFrameLayout
に追加します。これは、幅がゼロのWindowManager
に追加されます。高さパラメータ。次に、テストURLをWebView
にロードし、ページが終了したら、WebView
を強制的に適切なサイズにレイアウトし、それをターゲットのBitmap
に描画します。 Canvas
オブジェクト。これは、WebView
が完全にレンダリングされるように少し遅れて行われ、空白の白い画像になってしまうことはありません。次に、Bitmap
がRemoteViews
オブジェクトに設定され、ウィジェットのレイアウトのImageView
が更新されます。この例のウィジェットはStackOverflowのフロントページが更新されるよりも頻繁に更新される可能性があるため、テスト目的でコードにToast
を残しました。
_public class WebShotService extends Service {
private WebView webView;
private WindowManager winManager;
public int onStartCommand(Intent intent, int flags, int startId) {
winManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
webView = new WebView(this);
webView.setVerticalScrollBarEnabled(false);
webView.setWebViewClient(client);
final WindowManager.LayoutParams params =
new WindowManager.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
PixelFormat.TRANSLUCENT);
params.x = 0;
params.y = 0;
params.width = 0;
params.height = 0;
final FrameLayout frame = new FrameLayout(this);
frame.addView(webView);
winManager.addView(frame, params);
webView.loadUrl("http://stackoverflow.com");
return START_STICKY;
}
private final WebViewClient client = new WebViewClient() {
public void onPageFinished(WebView view, String url) {
final Point p = new Point();
winManager.getDefaultDisplay().getSize(p);
webView.measure(MeasureSpec.makeMeasureSpec((p.x < p.y ? p.y : p.x),
MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec((p.x < p.y ? p.x : p.y),
MeasureSpec.EXACTLY));
webView.layout(0, 0, webView.getMeasuredWidth(), webView.getMeasuredHeight());
webView.postDelayed(capture, 1000);
}
};
private final Runnable capture = new Runnable() {
@Override
public void run() {
try {
final Bitmap bmp = Bitmap.createBitmap(webView.getWidth(),
webView.getHeight(), Bitmap.Config.ARGB_8888);
final Canvas c = new Canvas(bmp);
webView.draw(c);
updateWidgets(bmp);
}
catch (IllegalArgumentException e) {
e.printStackTrace();
}
stopSelf();
}
};
private void updateWidgets(Bitmap bmp) {
final AppWidgetManager widgetManager = AppWidgetManager.getInstance(this);
final int[] ids = widgetManager.getAppWidgetIds(
new ComponentName(this, WebWidgetProvider.class));
if (ids.length < 1) {
return;
}
final RemoteViews views = new RemoteViews(getPackageName(), R.layout.widget_layout);
views.setImageViewBitmap(R.id.widget_image, bmp);
widgetManager.updateAppWidget(ids, views);
Toast.makeText(this, "WebWidget Update", 0).show();
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
_
これがウィジェットの良さのスクリーンショットです。
上記の答えに加えて、
このエラーが発生した場合-ウィンドウを追加できません。このウィンドウタイプのアクセスが拒否されました少なくとも、Marshmallowを実行しているデバイスでは、タイプを変更する必要があります。
単に交換する
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAYいずれかに
WindowManager.LayoutParams.TYPE_TOAST(または)
WindowManager.LayoutParams.TYPE_APPLICATION_PANEL
そしてそれは完全にうまくいくでしょう。
注:最新バージョンのmarsmallowを実行しているNexus6pで確認および確認されました。
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAYには権限が必要ですAndroid.permission.INTERNAL_SYSTEM_WINDOWこれは、Androidシステム関連のアプリにのみ追加できます。
また、Javascriptを使用してデータを解析しようとしている人のために、onPageFinished()でページの読み込みが完了したら、Webビューの高さと幅を変更することを忘れないでください。
上記の回答でこれの重要性を完全に見落とし、多くの時間を無駄にしてしまいました。
当初、私の想定は、Webビューのコンテンツを画像ビューを介してウィジェットに表示することではなかったため、これは必須ではありませんでした。
結局のところ、ビューの幅と高さがゼロでない限り、javascriptはWebビューからのデータを解析できません。
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY Android Mの後にのみ機能します。また、権限の設定が必要ですSettings.canDrawOverlays(context)