Android(安卓)桌面Widget (小组件)开发详解
16lz
2021-01-25
Widget就是个桌面小组件,有了Widget,我们可以直接在桌面上进行各种操作。
Widget使用
AndroidManifest中声明AppWidgetxml中定义AppWidget配置文件layout中定义Widget布局文件创建类继承AppWidgetProvider类
1.AndroidManifest.xml配置
<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.xinrui.fristwidget"> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <!-- 声明widget对应的AppWidgetProvider --> <!--<receiver android:name=".ExampleAppWidgetProvider" >--> <!--<intent-filter>--> <!--<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />--> <!--<action android:name="com.xinrui.fristwidget.UPDATE_ALL"/>--> <!--</intent-filter>--> <!--<meta-data android:name="android.appwidget.provider"--> <!--android:resource="@xml/example_appwidget_info" />--> <!--</receiver>--> <!--<service android:name=".ExampleAppWidgetService" >--> <!--<intent-filter>--> <!--<action android:name="android.appwidget.action.EXAMPLE_APP_WIDGET_SERVICE" />--> <!--</intent-filter>--> <!--</service>--> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <receiver android:name=".MyWidget"> <intent-filter> <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> </intent-filter> <meta-data android:name="android.appwidget.provider" android:resource="@xml/appwidget_info" /> </receiver> <service android:name=".WidgetService"> </service> </application></manifest>
2.res 的xml下创建appwidget_info.xml
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" android:initialLayout="@layout/main_activity" android:minHeight="180dp" android:minWidth="350dp" android:previewImage="@drawable/preview" android:updatePeriodMillis="8640000" android:widgetCategory="home_screen|keyguard"></appwidget-provider> <!-- initialLayout : widget 的布局文件 minHeight: widget 的 最低高度 minWidth : widget 的最低高度 previewImage : widget 的预览图 android:updatePeriodMillis : 更新的频率 google 规定最小时间30 min 在这里设置 0 我们自定义 widgetCategory : widget 可以被添加主屏幕或者锁屏 -->
3.layout下创建布局文件
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal"> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center_vertical" android:orientation="horizontal" android:paddingLeft="30dp" android:paddingRight="30dp"> <LinearLayout android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:orientation="vertical"> <TextView android:id="@+id/tv_date" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="#000" android:text="日期:" android:textSize="16sp" /> <TextView android:id="@+id/tv_money" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="#000" android:text="毫秒值:" android:textSize="16sp" /> </LinearLayout> <Button android:id="@+id/btn_refound" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="点击" android:textColor="#000" android:textSize="16sp" /> </LinearLayout></LinearLayout>
4.provider的创建
package com.xinrui.fristwidget;import android.appwidget.AppWidgetManager;import android.appwidget.AppWidgetProvider;import android.content.Context;import android.content.Intent;import android.util.Log;public class MyWidget extends AppWidgetProvider { String TAG = "MyWidget:" ; @Override public void onReceive(Context context, Intent intent) { super.onReceive(context, intent); Log.i(TAG ,"接受广播"); } /** * 第一个widget被添加调用 * @param context */ @Override public void onEnabled(Context context) { super.onEnabled(context); Log.i(TAG ,"widget onEnabled 状态"); context.startService(new Intent(context, WidgetService.class)); } /** * widget被添加 || 更新时调用 * @param context */ @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { super.onUpdate(context, appWidgetManager, appWidgetIds); Log.i(TAG ,"widget onUpdate 状态"); context.startService(new Intent(context, WidgetService.class)); } /** * 最后一个widget被删除时调用 * @param context */ @Override public void onDisabled(Context context) { super.onDisabled(context); Log.i(TAG ,"widget onDisabled 状态"); context.stopService(new Intent(context, WidgetService.class)); } /** * widget被删除时调用 * @param context * @param appWidgetIds */ @Override public void onDeleted(Context context, int[] appWidgetIds) { super.onDeleted(context, appWidgetIds); Log.i(TAG ,"widget onDeleted 状态"); }}
5.service的创建
package com.xinrui.fristwidget;import android.app.PendingIntent;import android.app.Service;import android.appwidget.AppWidgetManager;import android.content.ComponentName;import android.content.Context;import android.content.Intent;import android.os.IBinder;import android.support.annotation.Nullable;import android.util.Log;import android.widget.RemoteViews;import java.text.SimpleDateFormat;import java.util.Date;import java.util.Timer;import java.util.TimerTask;public class WidgetService extends Service { String TAG = "WidgetService "; private Timer mTimer; private SimpleDateFormat mFormat; @Nullable @Override public IBinder onBind(Intent intent) { Log.i(TAG,"onBind"); return null; } @Override public void onCreate() { super.onCreate(); mFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); mTimer = new Timer(); mTimer.schedule(new TimerTask() { @Override public void run() { Log.i(TAG,"更新 widget"); updateWidget(WidgetService.this); //更新 widget } }, 0, 1000); } private void updateWidget(Context context) { //通过 RemoteViews 加载布局文件 //通过 setTextView 等方法实现对控件的控制 RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.main_activity); long millis = System.currentTimeMillis(); String format = mFormat.format(new Date(millis)); Log.i(TAG,"millis :" + millis + "\n" + "format: " + format); remoteViews.setTextViewText(R.id.tv_date, "日 期:" + format); remoteViews.setTextViewText(R.id.tv_money, "毫秒值:" + millis); PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, new Intent(this, MainActivity.class), PendingIntent.FLAG_UPDATE_CURRENT); remoteViews.setOnClickPendingIntent(R.id.btn_refound, pendingIntent); //点击跳转 ComponentName componentName = new ComponentName(this, MyWidget.class); AppWidgetManager.getInstance(this).updateAppWidget(componentName, remoteViews); } @Override public void onDestroy() { super.onDestroy(); mTimer.cancel(); mTimer = null;Log.i(TAG,"onDestory"); } @Override public int onStartCommand(Intent intent, int flags, int startId) { return START_STICKY; }}
6.MainActivity
package com.xinrui.fristwidget;import android.app.Activity;import android.os.Bundle;import android.util.Log;public class MainActivity extends Activity { String TAG = "MainActivity "; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main_activity); }}
简单的一个widget小组件就这样实现了
更多相关文章
- 一个Android下拉刷新样式
- Android(安卓)Material Design-Maintaining Compatibility(保持
- Android输入法开发
- 【Android面试】Android面试题集锦 (陆续更新)
- 3种Android隐藏顶部状态栏及标题栏的方法
- [译]三分钟玩转Android(安卓)Bottom Sheet
- android杀掉进程顺序
- Android.ApplicationCrash
- android跳转到另一个类再返回当前类和值