[安卓]手机管家(十八)一键 锁屏清理线程以及widget

有些broadcastReceiver不能在manifest里静态注册(不用运行起来就能收到)

锁屏是不能静态注册的,非常频繁的锁屏,动态注册,绑到service里最好,这样生命周期长


receiver

public class LockScreenReceiver extends BroadcastReceiver {

	@Override
	public void onReceive(Context context, Intent intent) {
		// TODO Auto-generated method stub
		 System.out.println("LockScreenReceiver.onReceive()");
		 
	}

在service里注册

public class ListenLockScreenService extends Service {
	private LockScreenReceiver lockScreenReceiver;
	@Override
	public IBinder onBind(Intent intent) {
		// TODO Auto-generated method stub
		return null;
	}
	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		// TODO Auto-generated method stub
		lockScreenReceiver = new LockScreenReceiver();		
		IntentFilter filter = new IntentFilter("android.intent.action.SCREEN_OFF");
		registerReceiver(lockScreenReceiver, filter);
		return super.onStartCommand(intent, flags, startId);
	}
	@Override
	public void onDestroy() {
		// TODO Auto-generated method stub
		if (lockScreenReceiver!=null) {
			unregisterReceiver(lockScreenReceiver);
            lockScreenReceiver=null;
		}
		super.onDestroy();
	}
}

可以再setting里写一个控制按钮,这里让他在splash里启动,不能忘了service的声明

Intent service = new Intent(this,ListenLockScreenService.class);
		startService(service);
	}
	
	Handler myHandler = new Handler(){


在日常使用中,可以再锁屏的时候把进程清一遍,其实很实用

ublic class LockScreenReceiver extends BroadcastReceiver {

	@Override
	public void onReceive(Context context, Intent intent) {
		// TODO Auto-generated method stub
		 System.out.println("LockScreenReceiver.onReceive()");
		//kill所有的后台进程
      	ActivityManager ams = (ActivityManager) context.getSystemService(context.ACTIVITY_SERVICE);
      	List<RunningAppProcessInfo> list =      ams.getRunningAppProcesses();
         for (RunningAppProcessInfo runningAppProcessInfo : list) {
				ams.killBackgroundProcesses(runningAppProcessInfo.processName);
         }
	}
}


widgets相当于桌面的功能快捷方式

桌面其实也是一个程序,相当于在一个程序上实现另一个程序的功能

需要一个类继承AppWidgetProvider,但是要声明称一个receiver,实际上他是一个receiver

和之前获得管理员权限类似,这个类里面什么也不做

public class MyAppWidgetProvider extends AppWidgetProvider {

	
}


声明一下,需要在values下新建一个xml文件夹,其中需有一个xml文件

 <receiver android:name="com.example.myappwidget.MyAppWidgetProvider" >
           <intent-filter>
                  <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
           </intent-filter>
           <meta-data 
                   android:name="android.appwidget.provider"
                   android:resource="@xml/example_appwidget_info" />
        </receiver>

这个xml文件里面,制定了我们要做出来的widget的相关属相参数,他还要一个layout来显示widget的外观

<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:minWidth="300dp"
    android:minHeight="40dp"
    android:updatePeriodMillis="0" 
    android:previewImage="@drawable/ic_launcher"
    android:initialLayout="@layout/example_appwidget"
    android:resizeMode="horizontal|vertical"
    android:widgetCategory="home_screen|keyguard">
</appwidget-provider>

layout   这里面不支持复杂控件,比如edittext,若加上,在拖到桌面时提示有问题

<?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="vertical" >
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="hello widget"/>
     <Button 
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="widget"/>
</LinearLayout>


widget生命周期,是一个receiver

第一次新建时,call到几个函数

onEnAble 

onUpdate 


第二次拖到别的桌面

onupdate  onReceive


第三次  还是和第二次一样


可以想到   onEnabled只在第一次建立的时候调用


删除第三个 ondelete onreceive

删除第二个 ondelete onreceive

删除第一个 ondelete ondisable


最后一次会调用disable

启用widget会有广播,onreceive里面会看广播里附带了什么信息,如果是update,他会先调用update,可以看源码


来实现手机管家的widget项目

新建widget类

public class ProcessManagerWidget extends AppWidgetProvider {

}

然后去manifest注册

<receiver android:name="com.rjl.mobilephonemanager.widget.ProcessManagerWidget" >
               <intent-filter>
        <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
    </intent-filter>
          <meta-data 
                android:name="android.appwidget.provider"
                android:resource="@xml/example_appwidget_info" />
    </receiver>

xml写法

<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:minWidth="300dp"
    android:minHeight="40dp"
    android:updatePeriodMillis="0" 
    android:previewImage="@drawable/ic_launcher"
    android:initialLayout="@layout/processmanager_appwidget"
    android:resizeMode="horizontal|vertical"
    android:widgetCategory="home_screen|keyguard">
</appwidget-provider>

新建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="wrap_content"
    android:background="@drawable/widget_bg_portrait"
    android:orientation="horizontal" >
      <LinearLayout
        android:layout_width="0.0dip"
        android:layout_height="fill_parent"
        android:layout_marginLeft="5.0dip"
        android:layout_weight="1.0"
        android:background="@drawable/widget_bg_portrait_child"
        android:gravity="center_vertical"
        android:orientation="vertical"
        android:paddingBottom="3.0dip"
        android:paddingTop="3.0dip" >
        <TextView
            android:id="@+id/tv_processwidget_count"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10.0dip"
            android:textSize="16sp"
            android:text="正在运行的软件:6个"/>
        <ImageView
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="1.0dip"
            android:layout_marginTop="1.0dip"
            android:background="@drawable/widget_bg_portrait_child_divider" />
        <TextView
            android:text="可用内存:433.37M"
            android:id="@+id/tv_processwidget_memory"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10.0dip"
            android:textSize="16sp"/>
    </LinearLayout>
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal"
        android:orientation="vertical" >
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center_vertical" >
            <ImageView
                android:layout_width="20.0dip"
                android:layout_height="20.0dip"
                android:src="@drawable/ic_launcher" />
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="手机管家"
                android:textColor="#FF0000" />
        </LinearLayout>
        <Button
            android:id="@+id/btn_clear"
            android:layout_width="90.0dip"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_marginTop="5.0dip"
            android:background="@drawable/call_locate_green"
            android:text="一键清理"
            android:textColor="#000000" />
    </LinearLayout>
</LinearLayout>

完成交互,类里的方法

首先是onenable,拖到到桌面会调到他,只有第一次创建时会用到


onupdate,我们要让widget的图标上的内容内很快更新,默认是至少半小时,可以去弄一个service

@Override
	public void onUpdate(Context context, AppWidgetManager appWidgetManager,
			int[] appWidgetIds) {
		//1.不是service而是provider
		AppWidgetManager widgetManager = AppWidgetManager.getInstance(context);
		//3.updateAppWidget的第一个参数应该是component的name
		ComponentName provider = new ComponentName(context, ProcessManagerWidget.class);
		//4.updateAppWidget的第二个参数
		RemoteViews views = new RemoteViews("com.rjl.mobilephonemanager",R.layout.processmanager_appwidget);
		//5.通过view找到控件
		views.setTextViewText(R.id.tv_processwidget_count, "10个进程");
		views.setTextViewText(R.id.tv_processwidget_memory, "400MB RAM");
		//2.更新桌面控件
		widgetManager.updateAppWidget(provider, views);
		super.onUpdate(context, appWidgetManager, appWidgetIds);
	}
service  manifest里声明
ublic class WidgetUpdateService extends Service {

	@Override
	public IBinder onBind(Intent intent) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void onCreate() {
		// TODO Auto-generated method stub
		super.onCreate();
	}

	@Override
	public void onDestroy() {
		// TODO Auto-generated method stub
		super.onDestroy();
	}

}

  <service  android:name="com.rjl.mobilephonemanager.service.WidgetUpdateService"></service>


让widget启动时启动这个service,放到onenable里

@Override
	public void onEnabled(Context context) {
		Intent service = new Intent(context, WidgetUpdateService.class);
		context.startService(service);
		super.onEnabled(context);
	}

然后在service的onstart里更新widget,这样相当于是在第一次创建桌面的widget时更新了widget,并且要让他更新快点,用到timer,更新的代码应该在timer里

@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		
		timer = new Timer();
		timer.schedule(new TimerTask() {
			@Override
			public void run() {
				//1.不是service而是provider
				widgetManager = AppWidgetManager.getInstance(WidgetUpdateService.this);
				//6.动态获取进程数,ram也可以获取
				int count =GetProcessInfoUtils.getAllProcess(WidgetUpdateService.this);
				long ram = GetProcessInfoUtils.getAvailRam(WidgetUpdateService.this);
				//3.updateAppWidget的第一个参数应该是component的name
				ComponentName provider = new ComponentName(WidgetUpdateService.this, ProcessManagerWidget.class);
				//4.updateAppWidget的第二个参数
				views = new RemoteViews("com.rjl.mobilephonemanager",R.layout.processmanager_appwidget);
				//5.通过view找到控件
				views.setTextViewText(R.id.tv_processwidget_count, count+"个进程");
				views.setTextViewText(R.id.tv_processwidget_memory, ram/1024+"MB RAM");
				//2.更新桌面控件
				widgetManager.updateAppWidget(provider, views); 
			}
		}, 1000, 3000);	//3s更新一次
		return super.onStartCommand(intent, flags, startId);
	}


当最后一个widget没有了的时候销毁这个service,在ProcessManagerWidget里的ondisable里

@Override
	public void onDisabled(Context context) {
		// 销毁service
		Intent service = new Intent(context, WidgetUpdateService.class);
		context.stopService(service);
		super.onDisabled(context);
	}

处理点击事件

pending,在点击时页面不跳转,只发出一个自定义的广播,然后有一个接收者

@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		//注册下面的广播接收者,自定义的action
		IntentFilter fileFilter = new IntentFilter("com.rjl.widget.update");
		registerReceiver(new MyWidgetBroadcastReceiver(), fileFilter);
			
		//1.不是service而是provider
		widgetManager = AppWidgetManager.getInstance(WidgetUpdateService.this);
		//3.updateAppWidget的第一个参数应该是component的name
		provider = new ComponentName(WidgetUpdateService.this, ProcessManagerWidget.class);
		//4.updateAppWidget的第二个参数
		views = new RemoteViews("com.rjl.mobilephonemanager",R.layout.processmanager_appwidget);
		
		timer = new Timer();
		timer.schedule(new TimerTask() {
			@Override
			public void run() {		
				//6.动态获取进程数,ram也可以获取
				int count =GetProcessInfoUtils.getAllProcess(WidgetUpdateService.this);
				long ram = GetProcessInfoUtils.getAvailRam(WidgetUpdateService.this);				
				//5.通过view找到控件
				views.setTextViewText(R.id.tv_processwidget_count, count+"个进程");
				views.setTextViewText(R.id.tv_processwidget_memory, ram/1024+"MB RAM");
				//2.更新桌面控件
				widgetManager.updateAppWidget(provider, views); 
			}
		}, 1000, 3000);	//3s更新一次
		
		Intent myintent = new Intent("com.rjl.widget.update");
		//widget的广播机制,经常需要pending,也就是说不是立即执行,需要去点击后助兴
		//点击后还在当前页面,只发出一个广播,所以是getBroadcast,然后需要一个广播接收者
		PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 100, myintent, PendingIntent.FLAG_UPDATE_CURRENT); 
		views.setOnClickPendingIntent(R.id.btn_clear, pendingIntent);
		
		return super.onStartCommand(intent, flags, startId);
	}
	class MyWidgetBroadcastReceiver extends BroadcastReceiver{
		@Override
		public void onReceive(Context context, Intent intent) {			
			//此处应该去将后台应用杀掉,然后在更新count显示的数字		
			views.setTextViewText(R.id.tv_processwidget_count, "当前时间"+ System.currentTimeMillis());
			widgetManager.updateAppWidget(provider, views);
		}		
	}	


这样子就可以随时清理线程了,而不用等半小时更新一次


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值