【问题标题】:How to delete sent/delivered/undelivered SMS for specific address in android programmatically如何以编程方式删除android中特定地址的已发送/已发送/未发送的短信
【发布时间】:2016-10-07 11:00:28
【问题描述】:

我正在使用下面的代码来删除 SMS,它在 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 开始,除非您将应用程序创建为默认 SMS 应用程序,否则您无法正常使用 SMS,但我不想创建成熟的 SMS 默认 SMS 客户端,如我的应用没有任何用户交互。

我也有疑问,如果从 KITKAT 删除 SMS 对棒棒糖起作用,SMS API 发生了变化。

我只需要在 ANDROID-M 中从所有已发送/收件箱/未发送的地方删除特定收件人电话号码的短信 如果你们看不懂我的英语,请帮助我并原谅我 提前致谢

【问题讨论】:

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


    【解决方案1】:

    幸运的是,我通过使用 Java 反射解决了我的问题,因为我浏览了 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();
        }
    }
    

    根据上面在我的问题中的讨论,我正在创建系统应用程序,因此它对我来说非常有效,我测试此代码以用于正常应用程序,但它失败了。

    希望这段代码对开发者社区有所帮助,因为我花了很多天时间。 在此先感谢

    【讨论】:

    • "幸运的是我通过使用 Java Reflection 解决了我的问题,因为我已经浏览了 android 框架源代码......我使用 Java Reflection 并创建了一个类 SmsWriteOpUtil.java ...我花了很多天时间。” – 我不能确定你从哪里得到的,但你没有写一行 SmsWriteOpUtil: stackoverflow.com/revisions/27709655/4
    猜你喜欢
    • 1970-01-01
    • 2012-01-24
    • 1970-01-01
    • 1970-01-01
    • 2011-04-15
    • 1970-01-01
    • 2010-11-06
    • 1970-01-01
    • 2012-09-26
    相关资源
    最近更新 更多