自定义通知栏格式
- 完成notification的初始化。
- 如果需要点击进入下一个界面则对pendingintent进行初始化。
- 设置RemoteViews
RomoteViews remoteviews = new RemoteViews(getPackagename(),R.layout.layout_notification);
//参数分别为包名和通知栏布局样式xml的文件名
remoteviews.setTextViewText(R.id.text,"文字内容");
//参数分别为textview的id和内容
remoteviews.setImageViewResouce(R.id.pic,R.drawable.icon1);
remoteviews.setOnClickPendingIntent(R.id.open_activity,pendingIntent);
//参数为布局(viewgroup)的id,第二为设置将要打开的活动的pendingIntent
//最后设置view即可
notification。contentView=remoteviews;
需要设置不同的样式在布局文件中自行设置即可。 如下
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/open_activity"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/pic"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<TextView
android:id="@+id/text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="默认值"/>
</LinearLayout>
需要注意的是在SDK版本>=26后,通知栏弹出需要加上信道的处理。
生成桌面小部件
小部件的实现通过使用android提供的AppWidgetProvider类来实现的,其本质是一个广播。要定义一个桌面小部件,首先定义它的界面。
- 在res/layout/下新建一个XML文件。命名为widget.xml(名字和内容可以自定义)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/touch"
android:layout_height="match_parent"
android:layout_width="match_parent">
<ImageView
android:id="@+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/label_1"/>
</LinearLayout>
- 定义小部件的配置信息。在res/xml/下新建appwidget_provider_info.xml(名字随意)
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:initialLayout="@layout/widget"
android:minHeight="84dp"
android:minWidth="84dp"
android:updatePeriodMillis="86400000">
</appwidget-provider>
initialLayout是指小工具使用的初始化布局。还有小部件的最小尺寸以及自动更新时间。
- 小部件的实现类,新建一个类MyAppWidgetProvider继承AppWidgetProvider。并重写onUpdate(小部件启动和自动更新时调用)和onRecieve(小部件启动和自动更新时调用)
package com.example.administrator.wifitest;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.os.SystemClock;
import android.util.Log;
import android.widget.RemoteViews;
import android.widget.Toast;
public class MyAppWidgetProvider extends AppWidgetProvider {
public static final String TAG = "MyAppWidgetProvider";
public static final String CLICK_ACTION = "com.example.administrator.MyAppWidgetProvider.action.CLICK";
public MyAppWidgetProvider(){
super();
}
@Override
public void onReceive(final Context context, Intent intent) {
super.onReceive(context, intent);
Log.d(TAG, "onReceive: action = "+intent.getAction());
//判断是不是自己的action,好进行下一步操作
if(intent.getAction().equals(CLICK_ACTION)){
Toast.makeText(context,"Clicked it",Toast.LENGTH_SHORT).show();
new Thread(new Runnable() {
@Override
public void run() {
Bitmap srcbBitmap = BitmapFactory.decodeResource(context.getResources(),R.drawable.label_1);
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
for(int i=0;i<37;i++){
float degree = (i*10)%360;
RemoteViews remoteViews = new RemoteViews(context.getPackageName(),R.layout.widget);
remoteViews.setImageViewBitmap(R.id.imageView1,
rotateBitmap(context,srcbBitmap,degree));
Intent intentClick = new Intent();
intentClick.setAction(CLICK_ACTION);
intentClick.setComponent(new ComponentName(context.getPackageName(),
"com.example.administrator.wifitest.MyAppWidgetProvider"));
//添加这个的原因是因为sdk>=26后要求给出准确的广播位置。
PendingIntent pendingIntent = PendingIntent.getBroadcast(context,0,
intentClick,0);
remoteViews.setOnClickPendingIntent(R.id.touch,pendingIntent);
appWidgetManager.updateAppWidget(new ComponentName(context,MyAppWidgetProvider.class),
remoteViews);
SystemClock.sleep(30);
}
Intent intent2= new Intent(context,Main2Activity.class);
context.startActivity(intent2);
}
}).start();
}
}
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
//添加时会调用
super.onUpdate(context, appWidgetManager, appWidgetIds);
Log.d(TAG, "onUpdate: ");
final int counter = appWidgetIds.length;
Log.d(TAG, "counter = "+counter);
for(int i=0;i<counter;i++){
int appWidgetId = appWidgetIds[i];
onWidgetUpdate(context,appWidgetManager,appWidgetId);
}
}
private void onWidgetUpdate(Context context,AppWidgetManager appWidgetManager,int appWidgetId){
Log.d(TAG, "onWidgetUpdate: ="+appWidgetId);
RemoteViews remoteViews = new RemoteViews(context.getPackageName(),R.layout.widget);
//将布局设置在RemoteViews中
Intent intentClick = new Intent(CLICK_ACTION);
intentClick.setComponent(new ComponentName(context.getPackageName(),
"com.example.administrator.wifitest.MyAppWidgetProvider"));
PendingIntent pendingIntent = PendingIntent.getBroadcast(context,0,
intentClick,0);
remoteViews.setOnClickPendingIntent(R.id.touch,pendingIntent);
//设置点击后发送广播,之后实现类的onReceieve就可以收到
appWidgetManager.updateAppWidget(appWidgetId,remoteViews);
}
private Bitmap rotateBitmap(Context context, Bitmap srcbBitmap, float degree){
Matrix matrix =new Matrix();
matrix.reset();
matrix.setRotate(degree);
Bitmap tmpBitmap = Bitmap.createBitmap(srcbBitmap,0,0,srcbBitmap.getWidth(),
srcbBitmap.getHeight(),matrix,true);
return tmpBitmap;
}
}
- 最后要在AndroidManifest中声明小部件(因为它本质是一个广播组件,所以要注册)
<receiver android:name=".MyAppWidgetProvider">
<meta-data android:name="android.appwidget.provider"
android:resource="@xml/appwidget_provider_info">
</meta-data>
<intent-filter>
<action android:name="com.example.administrator.MyAppWidgetProvider.action.CLICK"/>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
</intent-filter>
</receiver>
其中android.appwidget.action.APPWIDGET_UPDATE是不可缺少的。不加这个action就无法在小部件列表中找到小部件。com.example.administrator.MyAppWidgetProvider.action.CLICK是自己定义的action(内容可以更改,其实在这里的作用是声明这个action)。要和实现类对应上。