Android核心基础(手机卫士的一个知识点总结)
注意:有些功能是需要权限的,在这里并没有写出来,在程序运行中,根据程序报的错误,添加相应的权限即可,里面的具体里面可能有一些小细节,没有明确的写出来,具体的需要在程序中自己调试,解决。 这个总结涵盖了Android的一些核心的内容,如四大组建Service、ContentProvider、BroadCastReceiver、Activity,而且四大组建都必须在清单文件中注册。
还涉及了Android手机底层的一些功能,如读取联系人、短信等。还有一些看似牛别点技术,什么短息拦截,电话拦截,黑名单拦截,甚至电话窃听、短信窃取(这里只是技术的分享,切不可做违法乱纪之事,否则后果自负)都是可以实现的,只需要在功能中稍加改动就很容实现想要的功能。 1.获取版本号
思路:
1.获取包管理器PackageManager
2.通过包管理器获取包信息PackageInfo
3.通过包信息获取版本号 packageInfo.VersionName
PackeageManager p=getPackageMamager();
PackageInfo info=p.getPackageInfo(getPackageName(),0)
String version=info.versionName;//获取版本号
2.获取网络的连接状态(ConnectivityManager)
1.获取连接管理器(ConnectivityManager)
2.通过连接管理器获取网络状态信息的对象(NetworkInfo)
ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = manager.getActiveNetworkInfo();
if(networkInfo==null){//没有网络
return false;
}else if(networkInfo.getType()==ConnectivityManager.TYPE_MOBILE){//手机2g/3g网络
return true;
}else if(networkInfo.getType()==ConnectivityManager.TYPE_WIFI){//wifi网络
return true;
}else{
return false;
} .httpClient设置连接超时时间
client.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 5000); .textView设置跑马灯效果
第一种:
android:ellipsize="marquee"
android:singleLine="true"
android:marqueeRepeatLimit="marquee_forever"
setSelected(true);
第二种方法是自定义textView 标签名称是自定义类的全类名
android:ellipsize="marquee"
android:singleLine="true"
android:marqueeRepeatLimit="marquee_forever"
自定义一个类继承子TextView方法,重写isFocused()方法,把返回值置为true .获取sim卡的串号
TelephonyManager =getSystemService(Context.Telephony_service)
pm.getSimSerialerNumber(); 6.安装sdcard中的apk文件
// 跳转到安装程序的界面
Intent intent = new Intent();
intent.setAction("android.intent.action.VIEW");
intent.setDataAndType(Uri.fromFile(file),"application/vnd.android.package-archive");
startActivity(intent); .自定义对话框,去掉黑边
View view = getLayoutInflater().inflate(R.layout.safe_dialog_second,null);
AlertDialog.Builder builder = new AlertDialog.Builder(this);
AlertDialog dialog = builder.create();
dialog.show();
Window window = dialog.getWindow();
//通过 window对象弹出的对话框,输入法无法自动弹出,通过下面的设置解决该问题问题
window.clearFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
window.setContentView(view); 8.ListView分页加载
1.listview.addFootView(view);
2.sqlite支持分页查找的功能
db.query("blackNumber", null, null, null, null, null, null, startId+","+block)
3.先查找总共有多少条记录,定义开始查找的索引位置,每次加载多少条记录,以及定义一个标记是否加载数据
4.给listview设置滑动事件
// 每次滑动都会调用
public void onScroll(AbsListView view, int firstVisibleItem,int visibleItemCount, int totalItemCount) {
// 是否滑动到了最后
if (firstVisibleItem + visibleItemCount == totalItemCount) {
Log.i("onScroll", "滑动到了最后。。");
if (!isloading) {// 如果没有加载数据
//是否滑动到了最后一页
if (totalItemCount < total) {
// 加载数据
isloading = true;
// 添加Footer
lv_black.addFooterView(footView);
// 加载数据
loadData(totalItemCount);
}
}
}
} 9.ListView的优化
1.定义一个静态类,定义控件的变量
2.在适配器中的getView()方法通过listview自身的缓存功能
public View getView(final int position, View convertView,
ViewGroup parent) {
ViewHolder holder = null;
View view;
if (convertView != null) {
view = convertView;
holder = (ViewHolder) convertView.getTag();// 直接从缓存里面取数据
} else {
holder = new ViewHolder();
view = getLayoutInflater().inflate(R.layout.activity_commuicate_lv_item, null);
holder.tv_number = (TextView) view.findViewById(R.id.tv_number);
view.setTag(holder);// 把数据控件直接缓存起来,不用每次都来查找控件
}
BlackNumberInfo info = infos.get(position);
holder.tv_number.setText(info.getNumber());
return view;
}
//listview的优化
private static class ViewHolder {
TextView tv_number = null;
TextView tv_type = null;
ImageView img = null;
} 10.黑名单拦截
1.启动一个服务,通过TelephonyManager监听电话的到来状态;
TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
tm.listen(new PhoneStateListener() {
switch (state) {
case TelephonyManager.CALL_STATE_IDLE://电话闲置状态
break;
case TelephonyManager.CALL_STATE_RINGING://响铃状态
// 2.判断来电号码是否是电话黑名单
boolean black = dao.isPhoneBlack(incomingNumber);
if (black) {
//3. 挂断黑名单号码
endCall(incomingNumber);
// 挂断电话,但是还有通话记录,所以通过内容监听者,监听内容的改变,一旦发生改变就删除通话记录
Uri uri = Calls.CONTENT_URI;
ContentResolver resolver = getContentResolver();
// 4.注册内容监听者,监听通话记录,并删除通话记录
resolver.registerContentObserver(uri, true,new MyContentObserver(new Handler(),incomingNumber));
}
break;
case TelephonyManager.CALL_STATE_OFFHOOK://接听状态
break;
}
} 11.删除通话记录
// 通话记录的Uri
Uri uri = Calls.CONTENT_URI;
getContentResolver().delete(uri, Calls.NUMBER + "=?",new String[] { inComingNumber }); 12.挂断电话
private void endCall(String incomingNumber) {
//通过反射获取服务管理器,因为底层隐藏了该功能,所以只能通过反射获取挂断电话的方法
Class<?> clazz = Class.forName("android.os.ServiceManager");
Method method = clazz.getMethod("getService", String.class);
IBinder inBinder = (IBinder) method.invoke(null,Context.TELEPHONY_SERVICE);
ITelephony iTelephony = ITelephony.Stub.asInterface(inBinder);
iTelephony.endCall();
}
注意:
挂断电话他还依赖于两个aidl文件(ITelephony.aidl和NeighboringCellInfo.aidl)
ITelephony.aidl文件必须在com.android.internal.telephony该包下
NeighboringCellInfo.aidl文件必须在android.telephony包下
包名不能写错,因为这是系统规定好的关于进程间通信的文件,不能随便乱改 13.获取联系人
public static List<ContactInfo> getContacts(ContentResolver cr) {
//1.首先查询raw_contacts表中联系人的id号
Cursor cursor = cr.query(Uri.parse("content://com.android.contacts/raw_contacts"),new String[] { "_id" }, null, null, null);
List<ContactInfo> Contacts = new ArrayList<ContactInfo>();
//2.遍历所有所有联系人的id
while (cursor.moveToNext()) {
int _id = cursor.getInt(0);
//3.根据联系人的id,获取联系人的信息,data1代表联系人的信息,mimtype是代表信息的类型,如电话,邮件,姓名等
Cursor contacts_cursor = cr.query(Uri.parse("content://com.android.contacts/raw_contacts/"+ _id + "/data"),new String[]{"data1","mimetype"},null,null,null);
ContactInfo info = new ContactInfo();
while (contacts_cursor.moveToNext()) {
String data = contacts_cursor.getString(0);
String mimetype = contacts_cursor.getString(1);
if ("vnd.android.cursor.item/name".equals(mimetype)) {// 姓名
info.setName(data);
} else if ("vnd.android.cursor.item/phone_v2".equals(mimetype)) {// 电话
info.setNumber(data);
}
}
Contacts.add(info);
}
return Contacts;
} 14.订阅开机广播,判断sim卡是否变更
1.新建一个类继承自BroadcastReceiver
2.注册广播,并订阅开启广播 android.intent.action.BOOT_COMPLETED
3.在onReceiv()方法中取出手机sim的串口,在和首选项(sharedpreference)中的值进行配对
4.如果不对,就发送短信通知,手机有可能已经丢 15.拦截短信到来
1.新建一个类继承自BroadcastReceiver
2.注册广播,并订阅接收短信广播 android.provider.Telephony.SMS_RECEIVED
3.在onReceive()方法中获取短信内容
Object[] objects = (Object[]) intent.getExtras().get("pdus");
for (Object object : objects) {
byte[] sms = (byte[]) object;
SmsMessage message = SmsMessage.createFromPdu(sms);//创建一个短信对象
String msg_content = message.getDisplayMessageBody();// 获取信息的内容
String number = message.getDisplayOriginatingAddress();// 获取发送短信的号码
//4.中断广播
abortBroadcast();
}
}
} 16.GPS手机定位
//获取定位管理器
LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
//注册地理发生改变事件监听器
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER, 0, 0,
new LocationListener() {
public void onStatusChanged(String provider,int status, Bundle extras) {}
public void onProviderEnabled(String provider) {}
public void onProviderDisabled(String provider) {}
public void onLocationChanged(Location location) {
double longitude = location.getLongitude();// 获取经度值
double latitude = location.getLatitude();// 获取纬度
}
}); 17.远程锁屏
1.拦截短信,根据短信的指令判断是否锁屏
2.锁屏
//安全设备管理器
DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
dpm.resetPassword("871405", 0);//设置锁屏密码
dpm.lockNow();// 锁屏
3.远程锁屏需要管理员权限,所以要激活管理员权限
(1)首先要定义一个类继承DeviceAdminReceiver类
public class MyAdmin extends DeviceAdminReceiver {}
(2)激活管理员
//设备安全管理器
DevicePolicyManager dpm = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
// 指定要激活的组件
ComponentName mDevice = new ComponentName(getApplicationContext(),MyAdmin.class);
//判断该应用是否有管理员权限
if(!dpm.isAdminActive(mDeviceAdminSample)){
Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
// 意图里面携带的数据
intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN,mDevice);
intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION,"开启后可以锁定屏幕");
startActivityForResult(intent, 100);
}
(3)需要注册广播
<receiver
android:name="liu.li.meng.receiver.MyAdmin"
android:permission="android.permission.BIND_DEVICE_ADMIN" >
<meta-data
android:name="android.app.device_admin"
android:resource="@xml/device_admin_sample" />
<intent-filter>
<action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
</intent-filter>
</receiver>
(4)android:resource="@xml/device_admin_sample"依赖一个文件
<?xml version="1.0" encoding="utf-8"?>
<device-admin xmlns:android="http://schemas.android.com/apk/res/android">
<uses-policies>
<limit-password />
<watch-login />
<reset-password />重置密码
<force-lock />锁屏
<wipe-data />清理数据(恢复出厂设置)
</uses-policies>
</device-admin> 18.远程清除数据(恢复出厂设置)
1.拦截短信,根据短信的指令判断是否清理数据
2.恢复出厂设置(需要管理员权限)
//设备安全管理器
DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
dpm.wipeData(0);// 清除数据,恢复出厂设置
3.一样需管理员权限,上面的操作都需要进行设置 19.播放报警音乐
1.拦截短信,根据指令播放播放报警音乐
2.播放报请音乐
MediaPlayer mediaPlayer = MediaPlayer.create(context,R.raw.shuai);
mediaPlayer.setLooping(true);// 循环播放
mediaPlayer.setVolume(1.0f, 1.0f);// 设置声音最大,即使手机是静音也是最大音量播放
mediaPlayer.start(); 20获取SDCard的可用内存,以及手机内置的可用内存
String sdcardPath = Environment.getExternalStorageDirectory().getAbsolutePath();
getAvailableMemory(sdcardPath);//获取sdcard可用内存
String memoryPath = Environment.getDataDirectory().getAbsolutePath();
getAvailableMemory(memoryPath);//获取手机可用内存
public String getAvailableMemory(String path) {
StatFs statFs = new StatFs(path);
// 获取可用的内存块
int blocks = statFs.getAvailableBlocks();
int size = statFs.getBlockSize();
// 计算可用的内存空间
int avaiableMemory = blocks * size;
String dataSize = Formatter.formatFileSize(this, avaiableMemory);//格式化数据
return dataSize;
} .获取系统总共运行内存和可用运行内存
文件读取文件管理器下/proc/meminfo文件;其中第一行就是总共的运行内存,第二行就是可用的运行内存 22.获取安装的所有应用
public static List<AppInfo> getInstallApp(Context context){
List<AppInfo> list=new ArrayList<AppInfo>();
PackageManager manager = context.getPackageManager();
List<PackageInfo> infos = manager.getInstalledPackages(0);//获取所有安装的应用信息的集合
for (PackageInfo info : infos) {
String versionName = info.versionName;//获取程序的版本号
String packageName = info.packageName;//获取应用程序的包名
ApplicationInfo appInfo = info.applicationInfo;//获取应用程序的相关信息
Drawable iconDrawable = appInfo.loadIcon(manager);//获取应用程序的图标
int uid = appInfo.uid;//获取应用的user id
String name = appInfo.loadLabel(manager).toString();//获取应用程序的名字
int flags = appInfo.flags;//获取应用的flags标识
boolean isUserApp = isUserApp(flags);//判断是否是用户应用还是系统应用
boolean isInstallSDCard = isInstallSDCard(flags);//判断应用安装的位置
AppInfo appInfos=new AppInfo(versionName, iconDrawable, name, uid, isInstallSDCard, isUserApp, packageName);
list.add(appInfos);
}
return list;
}
//判断是否是系统应用,还是用户应用
public static boolean isUserApp(int flags) {
if ((flags & ApplicationInfo.FLAG_SYSTEM) == 0) {//用户安装的应用
return true;
}else{//系统应用
return false;
}
}
// 判断安装的位置
public static boolean isInstallSDCard(int flags){
//安装到了手机内存
if((flags& ApplicationInfo.FLAG_EXTERNAL_STORAGE)==0){
return false;
}else{//sd卡
return true;
}
} 23.ListView分栏显示系统应用和用户应用
1.首先应该是两个集合,分别存放用户的应用和系统的应用
2.在实现BaseAdapter类中的getCount()方法应该写成,return userApp.size()+systemApp.size()+2;
这里的加2是因为用来标识是系统应用栏目,还是用户应用栏目
3.在getItem()方法中修改代码如下:
public AppInfo getItem(int position) {
if(position==0){
return null;
}else if(position<=userApp.size()){
return userApp.get(position-1);//返回用于安装的应用
}else if(position==userApp.size()+1){
return null;
}else{
return systemApp.get(position-(userApp.size()+2));//返回系统安装的应用
}
}
4.getView()中的设置如下:
public View getView(int position, View convertView, ViewGroup parent) {
if (position == 0) {
TextView tv = null;
if(convertView != null && convertView instanceof TextView){
tv = (TextView) convertView;
}else{
tv = (TextView) getLayoutInflater().inflate(R.layout.list_separator, null);
}
tv.setText("用户进程("+userApp.size()+")");
//用户应用的栏目
return tv;
} else if (position == userApp.size() + 1) {
//系统应用的栏目
TextView tv = null;
if(convertView != null && convertView instanceof TextView){
tv = (TextView) convertView;
}else{
tv = (TextView) getLayoutInflater().inflate(R.layout.list_separator, null);
}
tv.setText("系统进程("+systemApp.size()+")");
return tv;
} else if(position<=userApp.size()){
ViewHolder holder = null;
View view = null;
if (convertView == null || convertView instanceof TextView) {
view = getLayoutInflater().inflate(R.layout.activity_app_manager_lv_item, null);
holder = new ViewHolder();
holder.app_icon = (ImageView) view.findViewById(R.id.app_icon);
......
view.setTag(holder);
} else {
view = convertView;
holder = (ViewHolder) view.getTag();
}
AppInfo appInfo = userApp.get(position-1);
holder.app_icon.setImageDrawable(appInfo.getIcon());
return view;
}
else{
ViewHolder holder = null;
View view = null;
if (convertView == null || convertView instanceof TextView) {
view = getLayoutInflater().inflate(R.layout.activity_app_manager_lv_item, null);
holder = new ViewHolder();
holder.app_icon = (ImageView) view.findViewById(R.id.app_icon);
holder.iv_app_lock = (ImageView) view.findViewById(R.id.iv_app_lock);
view.setTag(holder);
} else {
view = convertView;
holder = (ViewHolder) view.getTag();
}
AppInfo appInfo = systemApp.get(position-(userApp.size()+2));
holder.app_icon.setImageDrawable(appInfo.getIcon());
......
return view;
}
}
}
static class ViewHolder {
ImageView app_icon;
ImageView iv_app_lock;
TextView tv_app_name;
TextView tv_app_package_name;
TextView tv_app_version_name;
TextView tv_app_install_location;
TextView tv_app_uid;
} .卸载应用
Intent intent = new Intent();
intent.setAction("android.intent.action.DELETE");
intent.setData(Uri.parse("package:" + packageName));
startActivity(intent); .启动应用
PackageManager pm=context.getPackageManager();
Intent intent = pm.getLaunchIntentForPackage(packageName);
if (intent == null) {
Toast.makeText(this, "该应用无法启动", 0).show();
return;
}
startActivity(intent); .显示应用详情信息
Intent intent = new Intent();
intent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
intent.setData(Uri.parse("package:" + packageName));
startActivity(intent); .激活新建短信页面
Intent intent = new Intent();
intent.setAction(Intent.ACTION_SEND);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_TEXT, "我发现了一个好玩的软件,赶紧下载吧www.baidu.com");//短信内容
startActivity(intent); .PopupWindow
View v = getLayoutInflater().inflate(R.layout.app_manager_popup, null);
//新建popuwindow
PopupWindow pop = new PopupWindow(v, ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT);
// 设置pop获得焦点
pop.setFocusable(true);
// 必须要设置背景资源,点击别的区域,才会自动消失
pop.setBackgroundDrawable(new BitmapDrawable());
int[] location = new int[2];//定义一个数组存放view的位置
view.getLocationInWindow(location);//获取view在窗口的位置
pop.showAtLocation(view, Gravity.LEFT | Gravity.TOP,location[0] + 50, location[1]);
// 定义动画
AnimationSet set = new AnimationSet(false);// 动画集合
AlphaAnimation alpha = new AlphaAnimation(0.3f, 1f);// 透明度改变动画
alpha.setDuration(500);// 设置动画的周期时间
ScaleAnimation scale = new ScaleAnimation(0f, 1f,// x轴
1f, 1f,// y轴
Animation.RELATIVE_TO_SELF, 0,// x点
Animation.RELATIVE_TO_SELF, 0.5f);// y点
scale.setDuration(500);
set.addAnimation(alpha);
set.addAnimation(scale);
v.startAnimation(set); .给程序加锁或者解锁
程序锁的原理:就是在Android中有一个任务栈,获取到任务栈的顶部的任务,就是刚才你打开的应用,根据这个原理
判断一个应用是否在顶部,就可以判断程序是否加锁了
1.应该有一个开关开启一个程序锁的功能,并开启一个程序锁服务
2.在服务中实时的监测用户要打开的应用是否加锁,是一个非常耗时的操作,应该开启一个线程;
并定义一个标志位使用while(flag)循环,在服务结束的时候就应该置为false
3.在应用列表中长按一个应用,进行加锁或者解锁的操作(程序锁数据库的增删操作);
如果是解锁操作,需要发送一个广播,通知这个程序已经解锁
4.在服务中OnCreate()方法获取按住的应用,查询应用锁数据库,是否是枷锁状态,如果是则解锁(从数据库删除记录),
如果不是就加锁(往数据库添加记录)
5.当手机屏幕灭屏的时候,就让线程休眠等待,手机亮屏就唤醒线程,这里需要订阅手机亮屏和灭屏的广播接受者
核心代码:
new Thread(new Runnable() {
public void run() {
while (flag) {
synchronized (AppLockService.class) {
if(isScreenOn){
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
// 获取正在运行的任务栈(最近打开的任务是在最前面)
List<RunningTaskInfo> tasks = manager.getRunningTasks(10);
// 最新的那个任务栈
RunningTaskInfo taskInfo = tasks.get(0);
// 最顶端的activity
ComponentName topActivity = taskInfo.topActivity;
final String packageName = topActivity.getPackageName();
if (!packageName.equals(tempApp)) {
if (isLockApp(packageName)) {
Intent intent = new Intent(getApplicationContext(),
AppLockEnterPasswordActivity.class);
intent.putExtra("packageName", packageName);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
}
}else{
try {
AppLockService.class.wait(500);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
}).start(); 30.进程管理
1.获取activityManager管理器ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
2.通过管理器获取正在运行的进程集合manager.getRunningAppProcesses();
3.遍历进程集合
public static List<TaskInfo> getRunningTask(Context context) {
List<TaskInfo> tasks = new ArrayList<TaskInfo>();
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
// 获取所有运行的进程
List<RunningAppProcessInfo> runningAppProcesses = am.getRunningAppProcesses();
PackageManager pm = context.getPackageManager();
boolean flag=true;
for (RunningAppProcessInfo proInfo : runningAppProcesses) {
// 获取应用的包名
String packageName = proInfo.processName;
TaskInfo taskInfo = new TaskInfo();
taskInfo.setPackageName(packageName);
ApplicationInfo applicationInfo=null;
try {
flag=true;
//当一个进程没有应用信息时,就在下面的一句中,出现了异常所以捕捉异常
//所以这里用了一个标记,来处理这些特殊的进程
applicationInfo = pm.getApplicationInfo(packageName, 0);
} catch (Exception e) {
flag=false;
}
if (!flag) {
taskInfo.setAppName(packageName);
taskInfo.setIcon(context.getResources().getDrawable(R.drawable.ic_launcher));
} else {
Drawable icon = applicationInfo.loadIcon(pm);
taskInfo.setIcon(icon);
String name = applicationInfo.loadLabel(pm).toString();
taskInfo.setAppName(name);
boolean isUserTask = filterApp(applicationInfo);
taskInfo.setUserTask(isUserTask);
} // 获取应用的占用内存空间
int pid = proInfo.pid;
int[] pids = new int[] { pid };
MemoryInfo[] processMemoryInfo = am.getProcessMemoryInfo(pids);
int memory = processMemoryInfo[0].getTotalPrivateDirty() * 1024;
String size = Formatter.formatFileSize(context, memory);// 格式化应用的内存 // 判断是否是系统应用还是用户应用
taskInfo.setMemory(size);
tasks.add(taskInfo);
}
return tasks;
}
//杀死进程
am.killBackgroundProcesses(taskInfo.getPackageName()); 31.窗口小部件进行一键清理进程
//1.窗口小部件
AppWidgetManager widgetManager = AppWidgetManager.getInstance(getApplicationContext());
ComponentName provider = new ComponentName(getApplicationContext(),ProcessAppWidget.class);
RemoteViews views = new RemoteViews(getPackageName(),R.layout.example_appwidget);
widgetManager.updateAppWidget(provider, views);
ActivityManager activityManager=(ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
List<RunningAppProcessInfo> list = activityManager.getRunningAppProcesses();
views.setTextViewText(R.id.tv_running_task, "正在运行的软件:"+list.size()+"个");
try {
views.setTextViewText(R.id.tv_avail_memory, "可用内存:"+getAvailMemory());
} catch (Exception e) {
e.printStackTrace();
}
//杀死进程
kills(list,activityManager); //点击一键清理按钮,重新启动服务,杀死所有正在运行的进程
Intent intented=new Intent(this,AppWidgetService.class);
PendingIntent pendingIntent=PendingIntent.getService(getApplicationContext(), 200, intented, 0);
views.setOnClickPendingIntent(R.id.btn_clear, pendingIntent); //点击手机卫士,启动打开安全卫士的首页
Intent intentStart=new Intent(this,MainActivity.class);
PendingIntent startMobile=PendingIntent.getActivity(getApplicationContext(), 200, intentStart, 0);
views.setOnClickPendingIntent(R.id.tv_mobilesafe, startMobile);
//更新视图
widgetManager.updateAppWidget(provider, views); //杀死进程
private void kills(List<RunningAppProcessInfo> list, ActivityManager activityManager) {
for (RunningAppProcessInfo info : list) {
String packageName = info.processName;
if(!packageName.equals(getPackageName())){
activityManager.killBackgroundProcesses(packageName);
}
}
}
//2.常见一个广播继承AppWidgetProvider
public class ProcessAppWidget extends AppWidgetProvider {
public void onEnabled(Context context) {
super.onEnabled(context);
//开启窗口小部件服务
Intent service=new Intent(context, AppWidgetService.class);
context.startService(service);
}
public void onDisabled(Context context) {
super.onDisabled(context);
//关闭窗口小部件服务
Intent service=new Intent(context, AppWidgetService.class);
context.stopService(service);
}
}
//3.注册广播
<receiver android:name="liu.li.meng.receiver.ProcessAppWidget" >
<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> //4.设置example_appwidget_info文件
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="294dp"
android:minHeight="72dp"
android:initialLayout="@layout/example_appwidget">
</appwidget-provider> 32.流量统计(TrafficStats)
public static List<TrafficInfo> getTraffics(Context context){
List<TrafficInfo> traffics=new ArrayList<TrafficInfo>();
PackageManager pm = context.getPackageManager();
List<PackageInfo> installedPackages = pm.getInstalledPackages(0);
for (PackageInfo packageInfo : installedPackages) {
ApplicationInfo applicationInfo = packageInfo.applicationInfo;
String name = applicationInfo.loadLabel(pm).toString();//获取应用的名字
Drawable icon = applicationInfo.loadIcon(pm);//获取应用的图标
int uid = applicationInfo.uid;//获取应用的uid
long rx = TrafficStats.getUidRxBytes(uid);//获取接受的数据流量
long tx = TrafficStats.getUidTxBytes(uid);//获取发送的数据流量
long totalx=rx+tx;
TrafficInfo info=new TrafficInfo(rx, tx, name, totalx, icon);
traffics.add(info);
}
return traffics;
} .手机杀毒
使用金山的杀毒数据库,杀毒原理:包名相同和签名(经过MD5加密)也相同才认为是病毒 1.获取应用的签名信息
public String getSignatures(String packageName) throws Exception {
PackageInfo packageInfo = pm.getPackageInfo(packageName,PackageManager.GET_SIGNATURES);
Signature[] signatures = packageInfo.signatures;
String signature = signatures[0].toCharsString();
String result = Md5Utils.encode(signature);
return result;
}
2.查询所有的病毒数据,进行扫描匹配;金山病毒数据库,有两个字段,md5(软件签名信息),name(应用的包名) .旋转动画
让一个图片不停的旋转
animation = new RotateAnimation(0, 360,Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,0.5f);
// 动画执行的周期
animation.setDuration(2000);
// 重复旋转
animation.setRepeatCount(Integer.MAX_VALUE);
lv.startAnimation(animation); 35.自定义进度条
1.首先写一个自定义进度条progress_style文件
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:id="@android:id/background">
<bitmap android:src="@drawable/security_progress_bg" />
</item>
<item android:id="@android:id/secondaryProgress">
<bitmap android:src="@drawable/security_progress" />
</item>
<item android:id="@android:id/progress">
<bitmap android:src="@drawable/security_progress" />
</item>
</layer-list>
2.然后在progressbar的属性设置为android:progressDrawable="@drawable/progress_style" 36.移动改变控件的位置
1.找到控件
2.获取到屏幕的宽高
Display display = getWindowManager().getDefaultDisplay();
//获取屏幕的宽高
int screenwidth = display.getWidth();
int screenHeight = display.getHeight();
3.给控件设置触摸事件
btn_location.setOnTouchListener(new OnTouchListener() {
int startx=0;
int starty=0;
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
startx=(int) event.getRawX();
starty=(int) event.getRawY();
break;
case MotionEvent.ACTION_MOVE:
//getRawx获取的是相对于屏幕的坐标
int stopx=(int) event.getRawX();
int stopy=(int) event.getRawY();
//计算移动的距离
int distancex=stopx-startx;
int distancey=stopy-starty;
//计算控件相对于屏幕的位置变化
int left = btn_location.getLeft()+distancex;
int right = btn_location.getRight()+distancex;
int top = btn_location.getTop()+distancey;
int bottom = btn_location.getBottom()+distancey;
//在屏幕显示区域改变位置,方式控件移除屏幕
if(left>=0 && right<=screenwidth && top>=0 && bottom<=screenHeight){
btn_location.layout(left, top, right, bottom);//更改控件的位置
}
//把这次的终点作为下次的起点
startx=stopx;
starty=stopy;
break;
case MotionEvent.ACTION_UP: break;
}
return false;
}
}); .三击居中
btn_location.setOnClickListener(new OnClickListener() {
long[] mHits = new long[3];
public void onClick(View v) {System.arraycopy(mHits, 1, mHits, 0, mHits.length-1);
mHits[mHits.length-1] = SystemClock.uptimeMillis();
//三击居中
if (mHits[0] >= (SystemClock.uptimeMillis()-500)) {
//获取控件的宽高
int width = btn_location.getWidth();
int height = btn_location.getHeight();
int l = screenwidth/2 - width/2;
int t = screenHeight/2 - height/2;
int r = screenwidth/2 + width/2;
int b = screenHeight/2 + height/2;
//居中
btn_location.layout(l, t, r, b);
}
}
}); 38.缓存清理
1.获取所有具有缓存信息的应用
(1)public void getCacheApp(Context context) throws Exception {
PackageManager pm = context.getPackageManager();
List<PackageInfo> installedPackages = pm.getInstalledPackages(0);
size=installedPackages.size();
for (PackageInfo packageInfo : installedPackages) {
String packageName = packageInfo.packageName;
// 获取缓存信息PackageManager中getPackageSizeInfo()隐藏了该方法,所以只能通过反射的手段得到
Class<?> clazz = Class.forName("android.content.pm.PackageManager");
Method method = clazz.getMethod("getPackageSizeInfo", new Class[] {String.class, IPackageStatsObserver.class });
// 调用方法,他会自动回调IPackageStatsObserver中的onGetStatsCompleted方法
method.invoke(pm, new Object[] { packageName, observer });
}
}
(2)//这是一个异步的方法
IPackageStatsObserver.Stub observer = new Stub() {
@Override
public void onGetStatsCompleted(PackageStats pStats, boolean succeeded) throws RemoteException {
i++;
long cacheSize=pStats.cacheSize;//缓存的大小
if(cacheSize>0){
try {
String packageName=pStats.packageName;//获取应用的包名
ApplicationInfo applicationInfo = pm.getApplicationInfo(packageName, 0);
Drawable icon = applicationInfo.loadIcon(pm);//图标
String name = applicationInfo.loadLabel(pm).toString();//应用的名字
String cache = Formatter.formatFileSize(context, cacheSize);
CacheInfo info=new CacheInfo(icon, name, cache, packageName);
caches.add(info);
} catch (Exception e) {
e.printStackTrace();
}
}
if(i==size){
//因为这是一个异步的方法,所以要用一个变量统计当内容加载完之后回调activity通知已经加载完毕 ,之后进行list的显示
activity.cacheFinish(caches);
}
}
};
IPackageStatsObserver对象依赖于两个个aidl文件,在android.content.pm包下的IPackageStatsObserver.aidl文件和PackageStats.aidl文件
.一键清理缓存
在framwork中提供了该方法。但是在上层系统给隐藏了起来,所以只能通过反射才能获取到该方法
public abstract void freeStorageAndNotify(long freeStorageSize, IPackageDataObserver observer);
PackageManager pm=getPackageManager();
Class<?> clazz = Class.forName("android.content.pm.PackageManager");
Method method = clazz.getMethod("freeStorageAndNotify", new Class[]{Long.TYPE,IPackageDataObserver.class});
//计算释放的空间,这里的参数是手机内存的大小(getMemory()或者getMemory()-1L)
Long freeSize=Long.valueOf(getMemory()-1L);
//清理缓存
method.invoke(pm, new Object[]{freeSize,obsever});
//清空集合
if(!(list == null || list.size() == 0)){
list.clear();
adapter.notifyDataSetChanged();
}
}
注意:单独清理一个内存是实现不了的,因为系统不支持 .短信的备份
原理:就是通过内容提供者读取到所有的短信内容,之后通过把短信内容json格式的字符串写入到一个文件中
1.读取所有短信内容
public List<MessageInfo> getAllMessage(Context context){
List<MessageInfo> infos=new ArrayList<MessageInfo>();
ContentResolver re = context.getContentResolver();
Cursor cursor = re.query(Uri.parse("content://sms"), new String[]{"type","body","address","date"}, null, null, null);
while(cursor.moveToNext()){
int type = cursor.getInt(0);
String body = cursor.getString(1);
String address = cursor.getString(2);
long date = cursor.getLong(3);
MessageInfo info=new MessageInfo(address, date, body, type);
infos.add(info);
}
return infos;
}
2.通过Gson框架,把短信集合转换成json字符串
Gson gson=new Gson();
String json = gson.toJson(infos);
3.把字符串写入文件
FileOutputStream outputStream=new FileOutputStream(Environment.getExternalStorageDirectory()+"/msm.txt");
outputStream.write(json.getBytes());
outputStream.close(); 40.短信的恢复
1.读取备份短信文件
2.把json格式的数据封装成对象
3.删除所有短信内容,把数据添加到短信数据库中
private void smsRestore(File file) {
try {
//1.读取短息备份文件
FileInputStream inputStream=new FileInputStream(file);
int len=0;
byte[] buffer=new byte[1024];
ByteArrayOutputStream outputStream=new ByteArrayOutputStream();
while((len=inputStream.read(buffer))!=-1){
outputStream.write(buffer, 0, len);
}
String json = outputStream.toString();
//2.把字符串封装到MessageInfo对象中
List<MessageInfo> infos = dao.changeStringToList(this, json);
ContentResolver re = getContentResolver();
//3.删除所有短信内容
re.delete(Uri.parse("content://sms"), null, null);
//4.恢复短信内容
for (MessageInfo info : infos) {
ContentValues values=new ContentValues();
values.put("body", info.getBody());
values.put("date", info.getDate());
values.put("address", info.getAddress());
values.put("type", info.getType());
re.insert(Uri.parse("content://sms"), values);
}
Toast.makeText(this, "短信还原成功", 0).show();
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(this, "短信还原失败", 0).show();
}
}
41.来去电归属地的显示
1.应该通过一个开关,是否打开归属地显示功能
2.如果开启归属地显示功能,就应该启动一个服务,一直监听电话的状态
3.外拨电话归属地的显示,需要获取到外拨电话号码,那就必须自己定义一个外拨电话广播,获取到电话号码,之后查询归属地数据库显示即可
4.来电归属地,通过TelephonyManager.listen(PhoneStateListener listen, PhoneStateListener.LISTEN_CALL_STATE)的一个方法监听即可
5.归属地的显示,需要通过windowManager对象添加到窗口上显示,才可显示出来,我们这里通过Toast的方式添加到窗口中 //电话管理器
TelephonyManager telephonyManager = (TelephonyManager) getApplicationContext().getSystemService(Context.TELEPHONY_SERVICE);
//window管理器
WindowManagerw indowManager = (WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
//监听来电电话的状态
listener = new MyPhoneListener();
telephonyManager.listen(listener, PhoneStateListener.LISTEN_CALL_STATE); //注册外拨电话广播接受者
receiver = new MyCallOutGoingReceiver();
IntentFilter filter=new IntentFilter();
filter.addAction(Intent.ACTION_NEW_OUTGOING_CALL);
registerReceiver(receiver, filter); //外拨电话广播
private class MyCallOutGoingReceiver extends BroadcastReceiver{
public void onReceive(Context context, Intent intent) {
String number = getResultData();//外拨电话号码
showAddressWindow(number);
} } //来电状态的一个监听器
private class MyPhoneListener extends PhoneStateListener {
@Override
public void onCallStateChanged(int state, String incomingNumber) {
switch (state) {
case TelephonyManager.CALL_STATE_IDLE:// 闲置状态
if(view!=null){
windowManager.removeView(view);
}
break;
case TelephonyManager.CALL_STATE_RINGING:// 响铃状态
showAddressWindow(incomingNumber);
break;
case TelephonyManager.CALL_STATE_OFFHOOK:// 接听状态
break;
}
}
} //显示归属地显示视图
private void showAddressWindow(String incomingNumber) {
final WindowManager.LayoutParams params = new LayoutParams();
params.height = WindowManager.LayoutParams.WRAP_CONTENT;
params.width = WindowManager.LayoutParams.WRAP_CONTENT;
params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
// | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE 不可触摸
| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
params.format = PixelFormat.TRANSLUCENT;
params.type = WindowManager.LayoutParams.TYPE_PRIORITY_PHONE;// 设置优先级和电话一样
view = LayoutInflater.from(getApplicationContext()).inflate(R.layout.call_show_address, null);
TextView tv_address=(TextView) view.findViewById(R.id.btn_address);
//查询电话号码的归属地
String address = AddressDao.getAddress(getApplicationContext(), incomingNumber);
tv_address.setText(address);
view.setBackgroundResource(Id);
//添加window窗口
windowManager.addView(view, params); //可以拖动归属地显示的位置
view.setOnTouchListener(new OnTouchListener() {
int startx=0;
int starty=0;
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
startx=(int) event.getRawX();//getRawX()获取到相对于屏幕的距离
starty=(int) event.getRawY();
break;
case MotionEvent.ACTION_MOVE:
int stopx=(int) event.getRawX();
int stopy=(int) event.getRawY(); int distancex=stopx-startx;//计算移动的距离
int distancey=stopy-starty; params.x+=distancex;
params.y+=distancey;
windowManager.updateViewLayout(view, params);//更新视图的位置 //把停止的点设置为新的起点
startx=stopx;
starty=stopy;
break;
case MotionEvent.ACTION_UP: break;
}
return true;
}
});
}
@Override
public void onDestroy() {
// 取消电话的监听
telephonyManager.listen(listener, PhoneStateListener.LISTEN_NONE);
unregisterReceiver(receiver);//取消外拨电话的广播接受
super.onDestroy();
}
Android核心基础(手机卫士的一个知识点总结)的更多相关文章
- Android项目实战--手机卫士开发系列教程
<ignore_js_op> banner131010.jpg (71.4 KB, 下载次数: 0) 下载附件 保存到相册 2 分钟前 上传 Android项目实战--手机卫士01- ...
- Android 项目实战--手机卫士(实现splash)
从今天开始根据之前学习的android的基础知识,实战一下,实现一个简单功能的android手机卫士 本文地址:http://www.cnblogs.com/wuyudong/p/5899283.ht ...
- ANDROID——仿360手机卫士的旋转打分控件
转载请注明本文出自大苞米的博客(http://blog.csdn.net/a396901990),谢谢支持! 简介 灵感源自360手机卫,主要功能就是实现显示评分或等级的效果.并稍微改良了一下,有更好 ...
- Android项目实战--手机卫士18--读取用户的短信内容以及短信备份
我们今天要说的就是我们手机卫士里面的高级工具里面的短信备份功能啦,其实这个软件备份的功能也很简单,就是把用户的短信读出来,然后写到一个xml或者数据库里面, 但我们这里的是读取到xml里面的. 首先我 ...
- Android仿360手机卫士悬浮窗效果
请看下图: 首先是一个小的悬浮窗显示的是当前使用了百分之多少的内存,点击一下小悬浮窗,就会弹出一个大的悬浮窗,可以一键加速.好,我们现在就来模拟实现一下 ...
- Android核心基础(二)
1.对应用进行单元测试 在实际开发中,开发android软件的过程需要不断地进行测试.而使用Junit测试框架,侧是正规Android开发的必用技术,在Junit中可以得到组件,可以模拟发送事件和检测 ...
- Android项目实战--手机卫士24--程序锁的实现以及逻辑
昨天我们已经把程序全部读取出来,显示到界面上了,那今天,我们就来讲一下那个程序锁的实现啦.其实也很简单啦,我们主要就是把用户要锁定的程序放到一个表里面,然后就监听手机里面的任务栈,如果发现任务栈里面出 ...
- Android核心基础(四)
1.联系人表结构 添加一条联系人信息 package com.itheima.insertcontact; import android.app.Activity; import android.co ...
- Android项目实战--手机卫士20--拿到已经安装了的程序以及程序管理主界面
好了,之前我们就讲了高级工具里面的短信备份与还原,那么我们高级工具里面的功能就基本上完成的啦,还有一个叫程序锁的功能而已,但我们今天先不做它先,我们先把我们的程序管理这个功能完成先. 先让大家看一下我 ...
随机推荐
- 讲解最好的Python正则表达式
这篇文章转载自:http://www.cnblogs.com/huxi/archive/2010/07/04/1771073.html#!comments 这里非常感谢作者无私的贡献自己的成果. 请大 ...
- 在.NET 应用程序设计中如何选择Class, Abstract Class and Interface
关键字: Type– 类型 Class - 类 Abstract - 抽象的 Interface - 接口 Member - 成员 Method - 方法 Property - 属性 预备知识:在阅读 ...
- Spark-Cassandra-Connector 插入数据函数saveToCassandra
在spark-shell中将数据保存到cassandra: var data = normalfill.map(line => line.split("\u0005")) d ...
- Python之实现一个简易计算器
自己动手写计算器 一.功能分析 用户输入一个类似这样 3*( 4+ 50 )-(( 100 + 40 )*5/2- 3*2* 2/4+9)*((( 3 + 4)-4)-4) 这样的表达式,假设表达式里 ...
- #添加屏蔽IP LINUX
netfilter/iptables 的最大优点是它可以配置有状态的防火墙,这是 ipfwadm 和 ipchains 等以前的工具都无法提供的一种重要功能.有状态的防火墙能够指定并记住为发送或接收信 ...
- SQLServer数据库 导出表和导入sql脚本
1.选择需要导出表的数据库--任务---生成脚本 2.显示:生成和发布脚本窗口--简介(某些可能关闭该页面的,可以省略该步骤),点击下一步 3.显示:生成和发布脚本窗口--选择对象--按照图片操作即可 ...
- Delphi接口
program Demo1; { Create Date: 2014-06-29 Author: P.S.M 1.接口Demo1 } {$APPTYPE CONSOLE} uses SysUtils; ...
- C#中的委托用法
当一个函数有返回值的时候用,用Func委托方法. 例如: static int sum(int x) { return x+x; } Func<int> a = sum; 当一个函数没有返 ...
- qt 5 小练习 简易画板
如何在窗口上画线?用一根根线来拼凑图案呢? 想必大家都知道点的集合是线,而线的集合就是很多线啦,用线的集合我们能拼凑出许许多多的图案.于是我就要记录自己跟着老师的学习之路啦: 既然有集合的话,势必要用 ...
- iOS项目架构文档
设计的项目架构主要引用MVVM+MVC架构,并以功能模块分级.以下为目录结构. 初级目录: 我们只需要关注SGZH文件夹下的目录,其他为Xcode管理的目录.可以看到此目录为项目初级目录,我们开发过程 ...