关于android4.4及以上版本无法恢复还原短信的问题记录与解决

本文主要是介绍关于android4.4及以上版本无法恢复还原短信的问题记录与解决,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

      前段时间在公司项目有系统短信备份和恢复的功能,在4.4(也就是API 19)以下的版本一点问题没有,很简单,没啥好说的,但是在4.4以上以及5.1由于系统更新了 SMS 的部分API,加强了权限控制,因此现在只有default SMS app才能对短信数据库有写权限,但是用户可以把第三方应用设置为default SMS app。也就是说非default SMS app也能读写短信,只不过是不能写入短信数据库中,这也就直接导致在4.4以上短信无法恢复。没办法,功能肯定还得完成,于是在我在搜索研究后发现了如下解决办法,希望对同样遇到这个问题的人有所帮助。

     首先,在4.4以上和5.0以下可以利用权限管理功能(Application Operations)也就是来默认开启写短信的权限,但是坑爹的问题又来了,这个功能被谷歌给隐藏了,因此只能使用反射来搞定,具体做法如下:

     一、检查写入短信权限是否已开启,因为有的国产手机,比如魅族,由于它们定制过系统,所以很有可能已经默认开启这个权限了。反射调用AppOpsManager类里的函数 int checkOp(int op, int uid, String packageName),其中op为15就是代表短信写入权限,代码如下:

  @TargetApi(Build.VERSION_CODES.KITKAT)private int checkMode(){AppOpsManager appOps = (AppOpsManager)getSystemService(Context.APP_OPS_SERVICE);Class c = appOps.getClass();try {          Class[] cArg = new Class[3];cArg[0] = int.class;cArg[1] = int.class;cArg[2] = String.class;Method lMethod = c.getDeclaredMethod("checkOp", cArg);return (Integer) lMethod.invoke(appOps, 15, Binder.getCallingUid(), getPackageName());} catch(NoSuchMethodException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (IllegalArgumentException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();}        return -1;}

    二、上述checkMode()方法,返回 0 就代表有权限,1代表没有权限,-1代表函数出错了。此时如果返回0,表示没有开启,同样反射调用setMode函数,方法如下:

     private boolean setMode(){AppOpsManager appOps = (AppOpsManager)getSystemService(Context.APP_OPS_SERVICE);Class c = appOps.getClass();Class[] cArg = new Class[4];cArg[0] = int.class;cArg[1] = int.class;cArg[2] = String.class;cArg[3] = int.class;Method lMethod;try {lMethod = c.getDeclaredMethod("setMode", cArg);lMethod.invoke(appOps, 15, Binder.getCallingUid(), getPackageName(),AppOpsManager.MODE_ALLOWED);return true;} catch (NoSuchMethodException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (IllegalArgumentException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();}return false;}

        至此,在4.4以上以及5.0以下的就又可以愉快的恢复短信,写入短信到短信数据库了,细心的朋友可以注意到了,这个是5.0以下能用,没错,非常不幸,在5.0以上这种方法又行不通了(此刻内心早已经把谷歌祖宗八代都默默问候了下),没办法,继续折腾,最后发现在5.0以上只能通过弹框来让用户选择默认短信应用,临时的设置自己的应用为Default SMS app,临时获取一次写入短信数据库数据能力,等短信恢复完成再改回原来的应用为Default SMS app,就是类似这种:

                                    

   做法如下:

      1、获取默认App的包名并保存。

    String defaultSmsApp = Telephony.Sms.getDefaultSmsPackage(context);

    2、让用户修改你的app为Default SMS app。

   Intent intent = new Intent(context, Sms.Intents.ACTION_CHANGE_DEFAULT);  intent.putExtra(Sms.Intents.EXTRA_PACKAGE_NAME, context.getPackageName());  startActivity(intent);

  3、恢复完短信,再让用户修改回Default SMS app,使用第一步保存的包名。

   Intent intent = new Intent(context, Sms.Intents.ACTION_CHANGE_DEFAULT);  intent.putExtra(Sms.Intents.EXTRA_PACKAGE_NAME, defaultSmsApp);  startActivity(intent);

    接下来,要将自己的应用设置为默认短信应用必须按照下面的步骤来,一样都不能少,不然成功不了,操作如下:

    1、首先在清单文件里做如下配置(一个都不能少):

         <receiver android:name="com.boy.pro.defaultsms.SmsReceiver"  android:permission="android.permission.BROADCAST_SMS">  <intent-filter>  <action android:name="android.provider.Telephony.SMS_DELIVER" />  </intent-filter>  </receiver>  <receiver android:name="com.boy.pro.defaultsms.MmsReceiver"android:permission="android.permission.BROADCAST_WAP_PUSH"><intent-filter><action android:name="android.provider.Telephony.WAP_PUSH_DELIVER" /><data android:mimeType="application/vnd.wap.mms-message" /></intent-filter></receiver><activity android:name="com.boy.pro.defaultsms.SmsActivity" ><intent-filter><action android:name="android.intent.action.SEND" />                <action android:name="android.intent.action.SENDTO" /><category android:name="android.intent.category.DEFAULT" /><category android:name="android.intent.category.BROWSABLE" /><data android:scheme="sms" /><data android:scheme="smsto" /><data android:scheme="mms" /><data android:scheme="mmsto" /></intent-filter></activity>         <service android:name="com.boy.pro.defaultsms.SmsService"android:permission="android.permission.SEND_RESPOND_VIA_MESSAGE"android:exported="true" ><intent-filter><action android:name="android.intent.action.RESPOND_VIA_MESSAGE" /><category android:name="android.intent.category.DEFAULT" /><data android:scheme="sms" /><data android:scheme="smsto" /><data android:scheme="mms" /><data android:scheme="mmsto" /></intent-filter></service>

    2、然后按照清单文件里的新建对应的类,类里面可以什么都不用写,如下图:




 至此,写入短信到短信数据库,恢复短信的功能就完成了,有需要的人拿去吧!

这篇关于关于android4.4及以上版本无法恢复还原短信的问题记录与解决的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/304766

相关文章

解决IDEA报错:编码GBK的不可映射字符问题

《解决IDEA报错:编码GBK的不可映射字符问题》:本文主要介绍解决IDEA报错:编码GBK的不可映射字符问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录IDEA报错:编码GBK的不可映射字符终端软件问题描述原因分析解决方案方法1:将命令改为方法2:右下jav

MyBatis模糊查询报错:ParserException: not supported.pos 问题解决

《MyBatis模糊查询报错:ParserException:notsupported.pos问题解决》本文主要介绍了MyBatis模糊查询报错:ParserException:notsuppo... 目录问题描述问题根源错误SQL解析逻辑深层原因分析三种解决方案方案一:使用CONCAT函数(推荐)方案二:

Redis 热 key 和大 key 问题小结

《Redis热key和大key问题小结》:本文主要介绍Redis热key和大key问题小结,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录一、什么是 Redis 热 key?热 key(Hot Key)定义: 热 key 常见表现:热 key 的风险:二、

IntelliJ IDEA 中配置 Spring MVC 环境的详细步骤及问题解决

《IntelliJIDEA中配置SpringMVC环境的详细步骤及问题解决》:本文主要介绍IntelliJIDEA中配置SpringMVC环境的详细步骤及问题解决,本文分步骤结合实例给大... 目录步骤 1:创建 Maven Web 项目步骤 2:添加 Spring MVC 依赖1、保存后执行2、将新的依赖

Spring 中的循环引用问题解决方法

《Spring中的循环引用问题解决方法》:本文主要介绍Spring中的循环引用问题解决方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录什么是循环引用?循环依赖三级缓存解决循环依赖二级缓存三级缓存本章来聊聊Spring 中的循环引用问题该如何解决。这里聊

Spring Boot中JSON数值溢出问题从报错到优雅解决办法

《SpringBoot中JSON数值溢出问题从报错到优雅解决办法》:本文主要介绍SpringBoot中JSON数值溢出问题从报错到优雅的解决办法,通过修改字段类型为Long、添加全局异常处理和... 目录一、问题背景:为什么我的接口突然报错了?二、为什么会发生这个错误?1. Java 数据类型的“容量”限制

SpringBoot基于配置实现短信服务策略的动态切换

《SpringBoot基于配置实现短信服务策略的动态切换》这篇文章主要为大家详细介绍了SpringBoot在接入多个短信服务商(如阿里云、腾讯云、华为云)后,如何根据配置或环境切换使用不同的服务商,需... 目录目标功能示例配置(application.yml)配置类绑定短信发送策略接口示例:阿里云 & 腾

关于MongoDB图片URL存储异常问题以及解决

《关于MongoDB图片URL存储异常问题以及解决》:本文主要介绍关于MongoDB图片URL存储异常问题以及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录MongoDB图片URL存储异常问题项目场景问题描述原因分析解决方案预防措施js总结MongoDB图

SpringBoot项目中报错The field screenShot exceeds its maximum permitted size of 1048576 bytes.的问题及解决

《SpringBoot项目中报错ThefieldscreenShotexceedsitsmaximumpermittedsizeof1048576bytes.的问题及解决》这篇文章... 目录项目场景问题描述原因分析解决方案总结项目场景javascript提示:项目相关背景:项目场景:基于Spring

解决Maven项目idea找不到本地仓库jar包问题以及使用mvn install:install-file

《解决Maven项目idea找不到本地仓库jar包问题以及使用mvninstall:install-file》:本文主要介绍解决Maven项目idea找不到本地仓库jar包问题以及使用mvnin... 目录Maven项目idea找不到本地仓库jar包以及使用mvn install:install-file基