我使用下面的代码删除短信,它在Android 5.0.2版上运行正常,但在6.0.1上无效。代码是为API-22(targetSdkVersion)构建的,因为我想在应用程序中避免运行时权限模型。
public static void deleteSTMessage()
{
String SMS_INBOX= "content://sms/";
Uri inboxURI = Uri.parse(SMS_INBOX);
Cursor c = STApplication.getContext().getContentResolver().query(inboxURI, new String[] { "_id", "thread_id", "address", "person",
"date", "body" }, null, null, null);
try {
while (c.moveToNext()) {
try {
if (c != null && c.moveToFirst()) {
do {
String address=c.getString(2);
String id= c.getString(0);
long threadId = c.getLong(1);
// String stringFromBase = c.getString(5);
try
{
if(address.equalsIgnoreCase(AppConfig.DESTINATION_ADDRESS))
{
int deltedrowcount = STApplication.getContext().getContentResolver().delete(Uri.parse("content://sms/" + id), null, null);
FileLog.v(TAG, "- ST Client SMS has Deleted successfully " );
}
}catch (Exception e){
FileLog.v(TAG,"- Exception in deleting SMS "+e.getLocalizedMessage());
}
} while (c.moveToNext());
}
} catch (Exception e) {
FileLog.v(TAG,"- Exception in deleting SMS "+e.getLocalizedMessage());
}
}
}catch (Exception e){
FileLog.v(TAG,"- Exception in deleting SMS "+e.getLocalizedMessage());
}finally {
c.close();
}
}
Manifest.xml如下所示
<?xml version="1.0" encoding="utf-8"?>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.WRITE_SMS"/>
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<application
android:name=".application.STApplication"
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:manageSpaceActivity=".ManageSpaceActivity"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".BaseActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".ManageSpaceActivity"/>
<service
android:name=".services.ServiceMain"
android:exported="false" />
<receiver android:name=".receivers.STPowerOffReceiver">
<intent-filter>
<action android:name="android.intent.action.ACTION_SHUTDOWN" />
<action android:name="android.intent.action.REBOOT"/>
</intent-filter>
</receiver>
<receiver android:name=".receivers.STBootReciever">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<receiver android:name=".receivers.STSimChangedReceiver">
<intent-filter>
<action android:name="android.intent.action.SIM_STATE_CHANGED" />
</intent-filter>
</receiver>
</application>
它允许我阅读短信,但当我尝试删除短信影响的行数返回0 时代码。经过一些谷歌搜索我发现从link来自API-19你不能正常播放短信,除非你创建你的应用程序作为默认短信应用程序,但我不想创建完整的短信默认短信客户端,因为我的应用程序没有任何用户交互。
此外,我还有一个问题,即如果从KITKAT,SMS API已经改变,为什么删除短信工作在棒棒糖上。
我唯一需要从ANDROID-M发送的/ inbox / undelivered..etc中的任何地方删除特定收件人电话号码的短信 如果你们不懂我的英语,请帮助我并原谅我 在此先感谢
答案 0 :(得分:-1)
幸运的是我通过使用Java Reflection解决了我的问题,因为我已经通过android框架源代码并意识到要删除SMS我们需要将AppOpsManager类的MODE_ALLOWED变量设置为true(AppOpsManager.MODE_ALLOWED = true)因为我使用了Java反思并创建一个类SmsWriteOpUtil.java,其代码为
public class SmsWriteOpUtil {
private static final int OP_WRITE_SMS = 15;
public static boolean isWriteEnabled(Context context) {
int uid = getUid(context);
Object opRes = checkOp(context, OP_WRITE_SMS, uid);
if (opRes instanceof Integer) {
return (Integer) opRes == AppOpsManager.MODE_ALLOWED;
}
return false;
}
public static boolean setWriteEnabled(Context context, boolean enabled) {
int uid = getUid(context);
int mode = enabled ?
AppOpsManager.MODE_ALLOWED : AppOpsManager.MODE_IGNORED;
return setMode(context, OP_WRITE_SMS, uid, mode);
}
private static Object checkOp(Context context, int code, int uid) {
AppOpsManager appOpsManager =
(AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
Class appOpsManagerClass = appOpsManager.getClass();
try {
Class[] types = new Class[3];
types[0] = Integer.TYPE;
types[1] = Integer.TYPE;
types[2] = String.class;
Method checkOpMethod =
appOpsManagerClass.getMethod("checkOp", types);
Object[] args = new Object[3];
args[0] = Integer.valueOf(code);
args[1] = Integer.valueOf(uid);
args[2] = context.getPackageName();
Object result = checkOpMethod.invoke(appOpsManager, args);
return result;
}
catch (NoSuchMethodException e) {
e.printStackTrace();
}
catch (InvocationTargetException e) {
e.printStackTrace();
}
catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
private static boolean setMode(Context context, int code,
int uid, int mode) {
AppOpsManager appOpsManager =
(AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
Class appOpsManagerClass = appOpsManager.getClass();
try {
Class[] types = new Class[4];
types[0] = Integer.TYPE;
types[1] = Integer.TYPE;
types[2] = String.class;
types[3] = Integer.TYPE;
Method setModeMethod =
appOpsManagerClass.getMethod("setMode", types);
Object[] args = new Object[4];
args[0] = Integer.valueOf(code);
args[1] = Integer.valueOf(uid);
args[2] = context.getPackageName();
args[3] = Integer.valueOf(mode);
setModeMethod.invoke(appOpsManager, args);
return true;
}
catch (NoSuchMethodException e) {
e.printStackTrace();
}
catch (InvocationTargetException e) {
e.printStackTrace();
}
catch (IllegalAccessException e) {
e.printStackTrace();
}
return false;
}
private static int getUid(Context context) {
try {
int uid = context.getPackageManager()
.getApplicationInfo(context.getPackageName(), PackageManager.GET_ACTIVITIES).uid;
return uid;
}
catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
return 0;
}
}
}
并在manifest.xml中添加了以下权限
<uses-permission android:name="android.permission.UPDATE_APP_OPS_STATS"/>
我的修改后的deleteSTMessage()方法代码是
public static void deleteSTMessage() {
Uri uri= Telephony.Sms.CONTENT_URI;
Cursor c = STApplication.getContext().getContentResolver().query(uri, new String[]{"_id", "thread_id", "address", "person",
"date", "body"}, null, null, null);
try {
while (c.moveToNext()) {
try {
if (c != null && c.moveToFirst()) {
do {
String address = c.getString(2);
String id = c.getString(0);
long threadId = c.getLong(1);
String body = c.getString(5);
//FileLog.v(LOG_TAG , " address: "+address + " body: "+body + " threadId: "+ threadId + " id: "+id );
try {
if(!SmsWriteOpUtil.isWriteEnabled(STApplication.getContext())) {
boolean canWriteSms = SmsWriteOpUtil.setWriteEnabled(STApplication.getContext(), true);
FileLog.v(LOG_TAG, " canWriteSms: "+canWriteSms);
}
if ( address.replaceAll("\\s","").contains(Constants.DESTINATION_ADDRESS)) {
int deltedrowcount = STApplication.getContext().getContentResolver().delete(uri, "thread_id = "+threadId, null);
//int deltedrowcount = STApplication.getContext().getContentResolver().delete(Uri.parse("content://sms/" + id), null, null);
if(deltedrowcount!=0){
FileLog.v(LOG_TAG, " !!! ST Client SMS has Deleted successfully " + deltedrowcount);
}
}
} catch (Exception e) {
FileLog.v(LOG_TAG, " !!! Exception in deleting SMS " + FileLog.getStackTraceString(e));
}
} while (c.moveToNext());
}
} catch (Exception e) {
FileLog.v(LOG_TAG, " !!! Exception in deleting SMS " + FileLog.getStackTraceString(e));
}
}
} catch (Exception e) {
FileLog.v(LOG_TAG, " !!!! Exception in deleting SMS " + FileLog.getStackTraceString(e));
} finally {
c.close();
}
}
根据我上面讨论的问题,我正在创建系统应用程序,所以它对我来说非常适合我测试这个代码用于正常的应用程序,但它失败了。
希望这段代码可以帮助开发者社区,因为我花了很多天时间。 提前致谢