注意:有些功能是需要权限的,在这里并没有写出来,在程序运行中,根据程序报的错误,添加相应的权限即可,里面的具体里面可能有一些小细节,没有明确的写出来,具体的需要在程序中自己调试,解决。
这个总结涵盖了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; } 3.httpClient设置连接超时时间 client.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 5000); 4.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 5.获取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); 7.自定义对话框,去掉黑边 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; } 21.获取系统总共运行内存和可用运行内存 文件读取文件管理器下/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; } 24.卸载应用 Intent intent = new Intent(); intent.setAction("android.intent.action.DELETE"); intent.setData(Uri.parse("package:" + packageName)); startActivity(intent); 25.启动应用 PackageManager pm=context.getPackageManager(); Intent intent = pm.getLaunchIntentForPackage(packageName); if (intent == null) { Toast.makeText(this, "该应用无法启动", 0).show(); return; } startActivity(intent); 26.显示应用详情信息 Intent intent = new Intent(); intent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS"); intent.setData(Uri.parse("package:" + packageName)); startActivity(intent); 27.激活新建短信页面 Intent intent = new Intent(); intent.setAction(Intent.ACTION_SEND); intent.setType("text/plain"); intent.putExtra(Intent.EXTRA_TEXT, "我发现了一个好玩的软件,赶紧下载吧www.baidu.com");//短信内容 startActivity(intent); 28.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); 29.给程序加锁或者解锁 程序锁的原理:就是在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; } 33.手机杀毒 使用金山的杀毒数据库,杀毒原理:包名相同和签名(经过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(应用的包名) 34.旋转动画 让一个图片不停的旋转 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; } }); 37.三击居中 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文件 2.一键清理缓存 在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(); } } 注意:单独清理一个内存是实现不了的,因为系统不支持 39.短信的备份 原理:就是通过内容提供者读取到所有的短信内容,之后通过把短信内容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(); }
发表评论 取消回复