小编典典
在使用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)。该漏洞在更高版本中得到了修补。
2020-09-23