Android:将WebView输出加载到应用程序小部件
虽然我理解an不直接支持Android:将WebView输出加载到应用程序小部件,android,webview,imageview,android-appwidget,appwidgetprovider,Android,Webview,Imageview,Android Appwidget,Appwidgetprovider,虽然我理解an不直接支持网络视图,但是否可以使用图像视图(受支持)和所述技术为图像视图生成图像?WebView不能直接使用,只能在后台使用,以便为ImageView提供图像。显然,至少在我的设备上,这是可能的,尽管您的里程可能会有所不同 在清单中,我们正常注册小部件的,还注册处理WebView及其图像捕获的服务 <manifest ... > ... <uses-permission android:name="android.permission.INTER
网络视图
,但是否可以使用图像视图
(受支持)和所述技术为图像视图
生成图像?WebView
不能直接使用,只能在后台使用,以便为ImageView
提供图像。显然,至少在我的设备上,这是可能的,尽管您的里程可能会有所不同
在清单中,我们正常注册小部件的
,还注册处理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\u 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" />
在服务
中,我们实例化了一个WebView
,并将其添加到FrameLayout
,然后将其宽度和高度参数添加到WindowManager
。然后,我们在WebView
中加载一个测试URL,当页面完成时,我们强制WebView
以适当的大小进行布局,并通过画布
对象将其绘制到目标位图
。这是在稍微延迟后完成的,以允许WebView
完全渲染自身,以免最终得到一个空白的白色图像。然后在远程视图
对象上设置位图
,以更新小部件布局中的图像视图
。出于测试目的,我在代码中留下了一个Toast
,因为我们的示例小部件的更新频率可能比Stack Overflow的首页刷新频率更高
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;
}
}
公共类WebShotService扩展服务{
私有网络视图;
专用WindowManager winManager;
公共int onStartCommand(Intent Intent、int标志、int startId){
winManager=(WindowManager)getSystemService(Context.WINDOW\u服务);
webView=新的webView(此);
webView.setVerticalScrollBarEnabled(false);
setWebViewClient(客户端);
最终WindowManager.LayoutParams参数=
新建WindowManager.LayoutParams(WindowManager.LayoutParams.WRAP_内容,
WindowManager.LayoutParams.WRAP_内容,
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
WindowManager.LayoutParams.FLAG_不可触摸,
像素格式(半透明);
参数x=0;
参数y=0;
参数宽度=0;
参数高度=0;
最终框架布局框架=新框架布局(本);
frame.addView(webView);
winManager.addView(框架,参数);
webView.loadUrl(“http://stackoverflow.com");
返回开始时间;
}
私有最终WebViewClient客户端=新WebViewClient(){
公共void onPageFinished(WebView视图,字符串url){
最终点p=新点();
winManager.getDefaultDisplay().getSize(p);
webView.measure(MeasureSpec.makeMeasureSpec((p.x
这是Widgety Goods的截图
在上述答案的基础上
对于出现此错误的用户-无法添加窗口。此窗口类型的权限被拒绝至少在我的情况下,如果设备运行棉花糖,则需要更改类型
简单地替换
WindowManager.LayoutParams.键入系统覆盖
WindowManager.LayoutParams.TYPE_TOAST(或)
WindowManager.LayoutParams.TYPE_APPLICATION_面板
它会工作得非常好
注意:已通过运行最新版本marsmallow的Nexus6p进行检查和确认。
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY需要权限android.permission.INTERNAL_SYSTEM_窗口,只能为android系统相关应用添加该窗口
另外,对于希望使用Javascript解析数据的用户,在onPageFinished()加载完页面后,不要忘记更改web视图的高度和宽度
在上面的回答中,我完全忽略了这一点的重要性,结果浪费了很多时间
最初我的假设是因为我的要求不是在web视图中显示内容
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);
}
}
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;
}
}