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;
    }

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 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 Contacts = new ArrayList();
        //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" >
                data
                android:name="android.app.device_admin"
                android:resource="@xml/device_admin_sample" />
                
                
                
            
        (4)android:resource="@xml/device_admin_sample"依赖一个文件
            
            
                
                
                    
                重置密码 
                锁屏
                清理数据(恢复出厂设置)
                
            

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 getInstallApp(Context context){
        List list=new ArrayList();
        PackageManager manager = context.getPackageManager();
        List 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 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 getRunningTask(Context context) {
        List tasks = new ArrayList();
        ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        // 获取所有运行的进程
        List 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 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 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.注册广播
    
            
                
            
            data
                android:name="android.appwidget.provider"
                android:resource="@xml/example_appwidget_info" />
        

    //4.设置example_appwidget_info文件
        
        
            android:minWidth="294dp"
            android:minHeight="72dp"
            android:initialLayout="@layout/example_appwidget">
        
    

32.流量统计(TrafficStats)
    public static List getTraffics(Context context){
        List traffics=new ArrayList();
        PackageManager pm = context.getPackageManager();
        List 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文件
    
    
        
        
        
        
        
        
        
        
        
    
    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 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 getAllMessage(Context context){
            List infos=new ArrayList();
            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 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知识点总结)