Android核心基础(手机卫士的一个知识点总结)(二)

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();

    }

转载于:https://my.oschina.net/fltsp/blog/607794

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值