如何以编程方式删除android中特定地址的已发送/已发送/未发送短信

时间:2016-10-07 11:00:28

标签: sms android-contentprovider android-6.0-marshmallow android-permissions smsmanager

我使用下面的代码删除短信,它在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中的任何地方删除特定收件人电话号码的短信 如果你们不懂我的英语,请帮助我并原谅我 在此先感谢

1 个答案:

答案 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();
    }
}

根据我上面讨论的问题,我正在创建系统应用程序,所以它对我来说非常适合我测试这个代码用于正常的应用程序,但它失败了。

希望这段代码可以帮助开发者社区,因为我花了很多天时间。 提前致谢