卸载系统应用&动画气泡特效&创建守护服务&进程管理(ActivtyManager&提供批量操作)&桌面小控件AppWidget

功能

思路

软件管理

对已安装的apk的管理

data/app 

system/app

apk->>功能清单

 

1.获取apk信息的集合

2.PackageManager包管理者  查询与删除

3.PackageInfo 一个功能清单的解析内容的javaBean

4.ApplicationInfo  一个appliation标签 的解析信息  图标 应用名 路径.

5.flags变量  二进制   |分配  包含

6.复杂列表显示  ListView+BaseAdapter

7.两个方法getViewTypeCount视图种类

8.getItemViewType指定下标的类型-->getView

9.优化: 普通 列表 的n

10.Eviroment环境变量  

11.PopupWindow 弹出视图 指定坐标显示

12.ScaleAnimation 缩放 AnimationSet动画集合

13.隐式意图:使用请求参数action动作category类型 data数据 

14.adb命令+RootUtils.jar命令开发包

进程管理

对正在运行的程序的管理,查看 终止

相当于window任务管理器

1.进程 程序 线程

2.ActivityManager进程管理者 系统级的服务

3.获取正在运行的进程信息集合 uid pid  porcessName

4.给PackageManager来获取图标应用名

5.配置进程名

6.使用flags分类

7.使用复杂ListView getViewTypeCount种类

8.getItemViewType 显示指定下标的视图

9.进程个数据 用户+系统

10.总内存:兼容 /proc/meminfo 读取第一行

11.killBackGorundProcess +权限 

12.守护服务

13.服务级别 startForeGround

14.定时清理  Timer 1 2 3 4  CountDownTiemr倒计时

15.锁屏清理  接收SCREEN_OFF+清理所有进程 注意:代码注册广播

16.BaseAdaptergetCount 决定行数

AppWidget 显示在桌面的小程序

当用Activity来开发

参考文档完成

1.继承  AppWidgetProvider BoradcastReceiver的子类

2.布局    

3.配置 

4.xml描述

5.用户从widgets页面拖到桌面

6.刷新 Timer+Service

7.RemoteViews 对视图的操作的工具 a.初始化 b.写事件

8.BroadcastReceiver 来响应点击

1.1. 卸载系统应用

用户应用程序的卸载:调用系统应用卸载界面.刷新

系统应用程序的卸载:以root账号登录 删除system/app/...apk

C:\Users\itheima>adb root  登录

adbd is already running as root

C:\Users\itheima>adb remount system/app  授权

remount succeeded

C:\Users\itheima>adb shell            shell命令

root@vbox86p:/ # rm -r system/app/Calculator.apk  强制删除

rm -r system/app/Calculator.apk

root@vbox86p:/ #

RootTools.jar

将命令发送给手机的一个开发库

 

 

 

mount   -o  remount  ,  rw  system/app

rm -r system/app/Calculator.apk

 

try {
						if (!RootTools.isRootAvailable()) {
							Toast.makeText(getBaseContext(), "请root手机", 0).show();
							return;
						}
						if (!RootTools.isAccessGiven()) {
							Toast.makeText(getBaseContext(), "授权后可卸载系统应用程序", 0).show();

							return;
						}
						// 系统
						// mount -o remount , rw system/app
						RootTools.sendShell("mount -o remount , rw system/app", 2000);
						// rm -r system/app/Calculator.apk
						RootTools.sendShell("rm -r "+apkInfo.path, 2000);
						Log.i("wzx", apkInfo.path+"");
					} catch (Exception e) {
						e.printStackTrace();
}

1.2. 气泡特效

动画 Animation

|--TranslateAnimation

|--RoateAnimation 

|--ScaleAnimation

|--AlphaAnimation

 

// ScaleAnimation:缩放动画
				// AlphaAnimation:透明度
				// AnimationSet:动画集合
				ScaleAnimation anim = new ScaleAnimation//
				(0.5f, 1.0f, 0.5f, 1.0f, //
	ScaleAnimation.RELATIVE_TO_SELF, 0.0f, ScaleAnimation.RELATIVE_TO_SELF, 0.5f);
				anim.setDuration(500);
				// 1.宽高 0.5,0.5 -->1.0 1.0
				// 2.动画 时长 500
				// 3.点是 定点
				AlphaAnimation anim2 = new AlphaAnimation(0.5f, 1.0f);
				anim2.setDuration(500);
				AnimationSet animset = new AnimationSet(false);
				animset.addAnimation(anim);
				animset.addAnimation(anim2);
	viewPop.startAnimation(animset);

2. 进程管理

需求:帮助用户 管理进程(查看  释放内存),类似 window任务管理器

进程

程序(apk)

线程

程序被打开,系统分配cpu与内存(资源)

安装在手机上 成为一个程序

java 处理耗时代码 线程

Thread

编程

 

程序---》运行--》进程  

进程--》终止-->程序

 

知识要点:

① 创建 Activity a.继承 b.重写 c.配置 d.启动  布局

② 获取进程数(正在运行的程序个数)

 

 

ActivityManager

activity运行中

进程管理者

1.系统服务getSystemService

2.获取 个数

3.获取进程信息的集合

4.杀死后台进程

android 底层linux

linux proc目录  存放 的系统的信息。

1.cpu

2.men

3.流量

/**

 * 获取系统中的进程个数

 * @param context

 * @return

 */

public static int getProcessCount(Context context)

{

//获取进程管理者

ActivityManager am=(ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);

//获取个数process=RunningApp

List  list=am.getRunningAppProcesses();

return list.size();

}

③ 内存信息

/**
	 * 获取可用内存
	 * 
	 * @param context
	 * @return
	 */
	public static long getFreeMem(Context context) {
		// 获取进程管理者
		ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
		MemoryInfo mi = new MemoryInfo();
		// 获取进程信息
		am.getMemoryInfo(mi);
		return mi.availMem;
	}

	/**
	 * 获取总内存
	 * 
	 * @param context
	 * @return
	 */
	@SuppressLint("NewApi")
	public static long getTotalMem(Context context) {
		// 获取进程管理者
		ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
		MemoryInfo mi = new MemoryInfo();
		// 获取进程信息
		am.getMemoryInfo(mi);
		return mi.totalMem;// api 级别为16才有 sdk
	}


public static long getTotalMem(Context context) {
		long total = 0;
		try {
			// 创建 文件流
			// 读取第一行
			// 解析出数量
			// 返回*1024
			File file = new File("proc/meminfo");
			// BufferedReader字符读取器
			BufferedReader reader = new BufferedReader(new FileReader(file));
			String firstLine = reader.readLine();
			// root@vbox86p:/proc # cat meminfo
			char[] chars = firstLine.toCharArray();
			StringBuffer sb = new StringBuffer();
			for (char c : chars) {
				if (c >= '0' && c <= '9') {
					sb.append(c);
				}
			}
			// cat meminfo
			// MemTotal: 511128 kB
			// 511128 kb
			total = Long.parseLong(sb.toString()) * 1024;// -->byte
			reader.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return total;
	}

④ 获取进程信息的集合

/**
	 * 获取进程信息
	 * @param context
	 * @return
	 */
	public static List findAll(Context context) {
		// 创建集合
		List list = new ArrayList();
		// 获取进程管理者
		ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
		// apk 功能清单的application
		PackageManager pm = context.getPackageManager();
		// 获取进程列表
		List processList = am.getRunningAppProcesses();
		for (RunningAppProcessInfo item : processList) {
			try {
				ProcessInfo bean = new ProcessInfo();
				bean.uid = item.uid;
				bean.pid = item.pid;
				// 【默认情况】 进程名 会等于 包名
				bean.packagename = item.processName;
//				

⑤ 分类

⑥ 使用复杂ListView

listview.setOnItemClickListener(new ListView.OnItemClickListener() {

 

@Override

public void onItemClick(AdapterView parent, View view, int position, long id) {

 

ProcessInfo info = (ProcessInfo) adapter.getItem(position);

if (info != null) {

info.isCheck = !info.isCheck;

}

 

// adapter =new ProcessAdapter();

// listview.setAdapter(adapter);

// // 比较

// if (adapter != null) {

// adapter.notifyDataSetChanged();//重新可见的所有行刷新

// }

ProcessViewHolder holder = (ProcessViewHolder) view.getTag();

holder.check.setChecked(info.isCheck);

}

});

⑦ 提供批量操作(项目十分流行)

@OnClick(R.id.select_all)
	public void select_all(View view)
	{
		
		//用户
		for(ProcessInfo bean:userProcess)
		{
			bean.isCheck=true;
		}
		//系统
		for(ProcessInfo bean:systemPorcess)
		{
			bean.isCheck=true;
		}
		
		//界面刷新
		if(adapter!=null)
		{
			adapter.notifyDataSetChanged();
		}
	}
	
	
	@OnClick(R.id.select_reverse)
	public void select_reverse(View view)
	{
		//用户
		for(ProcessInfo bean:userProcess)
		{
			bean.isCheck=!bean.isCheck;
		}
		//系统
		for(ProcessInfo bean:systemPorcess)
		{
			bean.isCheck=!bean.isCheck;
		}
		//界面刷新
		if(adapter!=null)
		{
			adapter.notifyDataSetChanged();
		}
	}


⑧ 清理

// 获取进程管理者
		ActivityManager tm = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
		// tm.killBackgroundProcesses(包名);
		tm.killBackgroundProcesses("com.itheima.mobilesafe");
    

     



@OnClick(R.id.clean)
	public void clean(View view)
	{
		List selected=new ArrayList();
		//只针对选中
		//用户
		for(ProcessInfo bean:userProcess) //不可以 不能在加强for删除集合元素
		{
			if(bean.isCheck)
			{
				selected.add(bean);
			}
		}
		//系统
		for(ProcessInfo bean:systemPorcess)
		{
			if(bean.isCheck)
			{
				selected.add(bean);
			}
		}
		
		if(selected.size()<1)
		{
			Toast.makeText(getBaseContext(), "未选中进程", 0).show();
			return ;
		}
		//
		int freeCount=0;
		long  freeMemKill=0;
		//kill
		for(ProcessInfo bean:selected)
		{
			ProcessUtils.killBackGroundProcess(this, bean.packagename);
			if(bean.isSystem)
			{
				systemPorcess.remove(bean);
			}else
			{
				userProcess.remove(bean);
			}
			freeMemKill+=bean.memorySize;
			++freeCount;
		}
		
		if(adapter!=null)
		{
			adapter.notifyDataSetChanged();//同步刷新列表 
		}
		//从集合中删除  列表同步
		//统计  释放 进程   内存  同步界面
Toast.makeText(this, "杀死"+freeCount+"个进程,释放了"+formate(freeMemKill)+"内存", 0).show();
		//同步界面
		process_count.setText("进程:" + (userProcess.size() + systemPorcess.size()) + "个");
		//剩余内存
		freemem+=freeMemKill;
		String result = "剩余/总内存:" + formate(freemem) + "/" + formate(totalmem);
		memory.setText(result);
	}

⑨ 进程管理的设置

l 创建Activity 布局

l 事件  使用sp保存boolean

l 回到进程页面使用boolean

 

set_show_system_process.setOnCheckedChangeListener(new OnCheckedChangeListener() {
			@Override
			public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
				// 创建Activity 布局
				// 事件 使用sp保存boolean
				SharedPreferencesUtils.saveBoolean(getBaseContext(), "set_show_system_process", isChecked);
				// 回到进程页面使用boolean
			}

		});
	}
	@Override
	protected void onStart() {
		// TODO Auto-generated method stub
		super.onStart();
boolean set_show_system_processValue=SharedPreferencesUtils.getBoolean(getBaseContext(), "set_show_system_process", false);
		set_show_system_process.setChecked(set_show_system_processValue);
	}

显示时列表的行数

@Override
	protected void onStart() {
		// TODO Auto-generated method stub
		super.onStart();
		if (adapter != null) {
			adapter.notifyDataSetChanged();
		}
		showProcessCount();
	}

	private class ProcessAdapter extends BaseAdapter {

		// 返回行数
		@Override
		public int getCount() {
boolean set_show_system_processValue = SharedPreferencesUtils.getBoolean(getBaseContext(), "set_show_system_process", false);
			if (set_show_system_processValue) {
				return 2 + userProcess.size() + systemPorcess.size();
			} else {
				return 1 + userProcess.size();
			}
		}

⑩ 防止被清理

 

方式一 创建守护服务 防止被人kill

a. 创建一个服务  MoSecurityService 1.继承 2.重写 3.配置 4.启动

b. onDestory 被别人kill并不会调用onDestory

public class MoSecurityService extends Service {
	@Override
	public void onCreate() {
		super.onCreate();
		Log.i("wzx", "创建复活服务...");
		startService(new Intent(this,AddressShowService.class));
		startService(new Intent(this,CallSmsService.class));
	}
	// 服务 被强行关闭 隔5秒打开自已
	@Override
	public void onDestroy() {
		super.onDestroy();
		Log.i("wzx", "销毁复活服务...onDestroy");
	}
	@Override
	public IBinder onBind(Intent intent) {
		// TODO Auto-generated method stub
		return null;
	}
}

方式二:

 

服务也存在优先级的问题

系统>前台>后台>

startForgound

// 提成前台

// Notification:显示状态通知里的对象

// 状态栏隐藏 小图标

// 显示:大图标 标题 描述 运行时间

// 通常绑定一个意图

// PenddingIntent:对象 Intent包装 只有点击时才打开 Pendding将来

// startForeground(编号 , 状态栏通知);

 

// Notification notification=new Notification(大图标, 小字, 时间);

Notification notification = new Notification(R.drawable.shenmabg"黑马73 15K", System.currentTimeMillis());

// notification.setLatestEventInfo(上下文, 标题, 描述, 通常绑定一个意图 );

Intent intent = new Intent();

// 

// 

// 

// 

intent.setAction("itheima.intent.action.HOME");

intent.addCategory("android.intent.category.DEFAULT");

PendingIntent pendingIntent = PendingIntent.getActivity(getBaseContext(), 0, intent, 0);

notification.setLatestEventInfo(getBaseContext(), "金山手机卫士正在运行""范德萨放松", pendingIntent);

startForeground(1, notification);

11 定时清理

Thread+while

 

Timer

j2se提供的定时器 ,设定时间 与时间间隔

执行一段代码 TimerTask

1 2 3 4 5 ...

CountDownTimer

是一个倒计时定时器

30  29  28  27

方法一:

 

// 创建定时器
		timer = new Timer();
		// schedule :计划 plan
		// timer.schedule(task, 延时时间, 时间间隔);
		timer.schedule(task, 0, 10000);//2个小时  60*2*60*1000
	}
	private TimerTask task = new TimerTask() {
		@Override
		public void run() {
			Log.i("wzx", "当前是定时清理...");
			// kill
			List list = ProcessUtils.findAll(getBaseContext());
			for (ProcessInfo item : list) {
				ProcessUtils.killBackGroundProcess(getBaseContext(), item.packagename);
			}
		}
	};
	private Timer timer;

	// 服务 被强行关闭 隔5秒打开自已
	@Override
	public void onDestroy() {
		super.onDestroy();
		if (task != null) {
			task.cancel();
			task = null;
		}
		Log.i("wzx", "销毁复活服务...onDestroy");
	}

方法二

//		timer=new CountDownTimer(任务长度,时间间隔) {  30000  1000  30 29.。
		timer=new CountDownTimer(30000,1000) {
			//tick 滴答
			int count=30;
			//读秒
			@Override
			public void onTick(long millisUntilFinished) {
				count--;
				Log.i("wzx", count+" count");
				ProcessUtils.killAll(getBaseContext());
			}
			//最后一次
			@Override
			public void onFinish() {
				count--;
				ProcessUtils.killAll(getBaseContext());
				Log.i("wzx", count+" count");
				
			}
		};
		timer.start();
	}
	private CountDownTimer timer;

	// 服务 被强行关闭 隔5秒打开自已
	@Override
	public void onDestroy() {
		super.onDestroy();
		if(timer!=null)
		{
			timer.cancel();
			timer=null;
		}
		Log.i("wzx", "销毁复活服务...onDestroy");
	}

12 判断服务是否在运行

/**
	 * 判断 服务是否在运行
	 * @param context
	 * @param serviceName
	 * @return
	 */
	public static boolean isSerivceRunning(Context context, String serviceName) {
		// 获取进程管理者
		ActivityManager tm = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
		List infos = tm.getRunningServices(100);
		boolean isRunning = false;
		for (RunningServiceInfo item : infos) {
			if (serviceName.equals(item.service.getClassName())) {
				isRunning = true;
				break;
			}
		}
		return isRunning;
	}

13 锁屏清理:锁屏广播接收

1.继承  2.重写 3.配置  

该广播必须使用 代码注册才能生效

	IntentFilter filter = new IntentFilter();
		filter.addAction(Intent.ACTION_SCREEN_OFF);// 锁屏
		filter.addAction(Intent.ACTION_SCREEN_ON);// 解锁屏
		registerReceiver(receiver, filter);
	}
	private BroadcastReceiver receiver = new BroadcastReceiver() {

		public void onReceive(android.content.Context context, Intent intent) {
			Log.i("wzx", "onReceive接收到广播" + intent.getAction());
			if (Intent.ACTION_SCREEN_ON.equals(intent.getAction())||
					Intent.ACTION_SCREEN_OFF.equals(intent.getAction())) {
      //清理
			}

		};
	};
	// 服务 被强行关闭 隔5秒打开自已
	@Override
	public void onDestroy() {
		super.onDestroy();
		unregisterReceiver(receiver);
		Log.i("wzx", "销毁复活服务...onDestroy");
	}

14 桌面小控件AppWidget (只要求 开发者能够按照文档照抄)

AppWidget:微型小程序(“一个小Activity”)

1.只显示桌面

2.如果一个程序有appWidget 用户可从”小部件” 创建

3.包含视图

4.支持事件

5.自动更新

 

Activity

AppWidget

继承activity

继承 

|--BroadcastReicever

    |--AppWidgetProvider

布局view

布局view

配置

配置

启动

安装 以后由用户拖动桌面

刷新  Thread+handler

通过Service+Timer

findViewById  setOnClickListner

通过RemoteViews+BoradCastReceiver

 

http://www.apiminer.org/doc/guide/topics/appwidgets/index.html

//BroadcastReceiver

//|--AppWidgetProvider

public class MyWidgetProvider extends AppWidgetProvider {

 

}

 

  <receiver android:name="com.itheima.widget.receiver.MyWidgetProvider" >

            <intent-filter>

                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />

            intent-filter>

            <meta-data

                android:name="android.appwidget.provider"

                android:resource="@xml/my_widget_provider" />

        receiver>

 

描述文件

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"

    android:initialLayout="@layout/my_widget_layout"

    android:minHeight="100dp"

    android:minWidth="200dp"

    android:previewImage="@drawable/pre"

    android:resizeMode="horizontal|vertical"

    android:updatePeriodMillis="86400000" >

appwidget-provider>

 

 

 

2.1. Widget更新

public class WidgetUpdateService extends Service {

	private Timer timer = null;
	private TimerTask task = new TimerTask() {

		@Override
		public void run() {
			// 9:58:32
			SimpleDateFormat foramte = new SimpleDateFormat("HH:mm:ss");
			Date date = new Date();
			String time = foramte.format(date);
			// Actvitiy findViewById set..
			// 初始控件
			// RemoteViews: 只是一个操作控件的工具:findViewById setText setOnClickListern
			// 设置值
			RemoteViews remoteviews = new RemoteViews(getPackageName(), R.layout.my_widget_layout);
			remoteviews.setTextViewText(R.id.time_btn, time);// findViewById
																// setText
			// 更新到桌
			// AppWidgetManager 桌面小程序的管理 更新widget视图
			AppWidgetManager am = AppWidgetManager.getInstance(getBaseContext());
			// am.updateAppWidget(provider, views);//提交到桌面进行更新
			// ComponentName:组件name
			ComponentName name = new ComponentName(getBaseContext(), MyWidgetProvider.class);
			am.updateAppWidget(name, remoteviews);// 提交到桌面进行更新

		}
	};

	@Override
	public void onCreate() {
		// TODO Auto-generated method stub
		super.onCreate();
		timer = new Timer();
		timer.schedule(task, 0, 1000);
		Log.i("wzx", "widget更新服务 ....");

	}

	@Override
	public void onDestroy() {
		// TODO Auto-generated method stub
		super.onDestroy();
		if (timer != null) {
			timer.cancel();
			timer = null;
		}
	}

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

}

2.2. 事件添加

//PendingIntent点击响应的Intent
			Intent intent=new Intent();
			intent.setAction("itheima.appwidget.action.ON_CLICK");
			PendingIntent  pI=PendingIntent.getBroadcast(getBaseContext(), 0, intent, 0);
			remoteviews.setOnClickPendingIntent(R.id.time_btn, pI);

public class OnClickReciever extends BroadcastReceiver{

	@Override
	public void onReceive(Context context, Intent intent) {
		// TODO Auto-generated method stub
		Toast.makeText(context, "清理进程", 0).show();
	}
}

 
            
                
            
        

1. 桌面小程序

用户如果不看widget 暂停服务 stopService

用户看 启动 startService

appwidget生命周期

生命周期:一堆有序方法的集合,有开始 有销毁  x1 中间有可能多次

回调函数:(CallBack)都以on开头  由开发者实现(重写由系统调用。

Service: startService   onCreate-->onStartCommand --->running -->onDestory

@Override

protected void onDestroy() {

super.onDestroy();

}

@Override

protected void onStart() {

super.onStart();

}

@Override

protected void onResume() {

super.onResume();

}@Override

protected void onPause() {

super.onPause();

}

@Override

protected void onStop() {

super.onStop();

}

添加

09-21 01:08:27.840: I/wzx(2442): --onEnabled--- 第一个实例创建    Service+timer更新 

09-21 01:08:27.840: I/wzx(2442): --onUpdate---  更新桌面

09-21 01:09:08.320: I/wzx(2442): --onUpdate---N个实例创建 

删除 

09-21 01:09:50.168: I/wzx(2442): --onDeleted--删除第N个实例创建 

09-21 01:10:12.044: I/wzx(2442): --onDeleted---

09-21 01:10:12.044: I/wzx(2442): --onDisabled---最后一个widget实例从桌面删除   Service+Timer更新

 

1.1. Appwidget的尺寸问题

 

 

1.2. 山寨其它应用appwidget

 

a. 布局

b. 创建AppWidgetProider

c. 配置

d. 描述 创建xml

e. 更新    Service+Timer+Remoteviews+优化onEnable

f. 写事件  RemoteViews+BroadcastReceiver

你可能感兴趣的:(android项目片段分析)