在使用KitKat之前,使用
SmsManager发送的SMS 要求发送消息的应用程序将其插入到Provider中,因此可以忽略该问题。
从KitKat开始,不是默认SMS应用程序且用于
SmsManager发送消息的任何应用程序都将系统自动将消息写入提供商。无法阻止这种情况,此外,该应用程序也将无法删除这些消息,因为它无法访问提供程序。*
作为默认SMS应用程序的应用程序负责编写其传出消息,因此可以省略该步骤。系统不会自动为默认SMS应用程序写入。
- 仅 在4.4中存在一个安全漏洞,非默认应用可以通过该漏洞获得对提供者的写访问权限。我在这里的答案中对此进行了详细说明,但在KitKat之后的版本中将无法使用。
本SmsWriteOpUtils类使用反射来的接入方式的AppOpsManager服务,以启用/禁用非默认的短信应用对SMS提供写访问的API等级19(奇巧)。设置后,将保留应用程序的访问模式,直到将其重置或将其卸载。
启用应用程序的写访问权限将允许该应用程序与SMS Provider进行交互的所有标准方法,包括insert()和delete()。
请注意,此类不进行API级别检查,并且WRITE_SMS仍然需要权限。
import android.app.AppOpsManager;import android.content.Context;import android.content.pm.PackageManager;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;public final class SmsWriteOpUtils { private static final int WRITE_OP_CODE = 15; public static boolean isWriteEnabled(Context context) { int result = checkOp(context); return result == AppOpsManager.MODE_ALLOWED; } public static boolean setWriteEnabled(Context context, boolean enabled) { int mode = enabled ? AppOpsManager.MODE_ALLOWED : AppOpsManager.MODE_IGNORED; return setMode(context, mode); } private static int checkOp(Context context) { try { Method checkOpMethod = AppOpsManager.class.getMethod("checkOp", Integer.TYPE, Integer.TYPE, String.class); AppOpsManager appOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); int uid = context.getApplicationInfo().uid; String packageName = context.getPackageName(); return checkOpMethod.invoke(appOpsManager, WRITE_OP_CODE, uid, packageName); } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) { e.printStackTrace(); } return -1; } private static boolean setMode(Context context, int mode) { try { Method setModeMethod = AppOpsManager.class.getMethod("setMode", Integer.TYPE, Integer.TYPE, String.class, Integer.TYPE); AppOpsManager appOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); int uid = context.getApplicationInfo().uid; String packageName = context.getPackageName(); setModeMethod.invoke(appOpsManager, WRITE_OP_CODE, uid, packageName, mode); return true; } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) { e.printStackTrace(); } return false; }}用法示例:
````
boolean canWriteSms;
if(!SmsWriteOpUtils.isWriteEnabled(getApplicationContext())) {
canWriteSms = SmsWriteOpUtils.setWriteEnabled(getApplicationContext(), true);
}
…
```
注意:对于普通用户应用程序,这仅适用于API级别19(KitKat)。该漏洞在更高版本中得到了修补。



