Android - Java - 发送短信后不调用 BroadcastReceiver.onReceive()

问题描述 投票:0回答:1

我的小米根本不发送短信,但默认短信客户端的消息历史记录中显示该短信为未发送。

三星将真正发送短信,但不会调用 BroadcastReceiver.onReceive() 并且我的应用程序不知道它是否已发送。 sms.sent() 的结果是我的超时错误消息。

(我不是 Java 开发人员 - 我只是将我找到的所有解决方案放在一起。如果您发现任何错误,请随时向我指出。)

LogCat展示:

  • 我 SmsServiceModule:onReceiveSmsMessage:errorCode=-1

SMS.java:

public class SMS {
    public Context context = null;

    SMS(Context context) { this.context = context; }

    static class Result {
        public String status = null;
        public String body = null;
        public String error = null;

        Result(String body) { this.body = body; }
        Result(String body, String error) { this.error = error; }
        Result(String body, String error, String status) {
            if (body != null && !body.equals(""))
                 this.body = body;
            else this.error = error;
            this.status = status;
        }
    }

    public static String SENT = "SMS_SENT";
    public static String DELIVERED = "SMS_DELIVERED";

    public Result sendSMS(JSONObject input) {
        final Result[] res = {null};

        try {
            ArrayList<PendingIntent> sentPendingIntents      = new ArrayList<PendingIntent>();
            ArrayList<PendingIntent> deliveredPendingIntents = new ArrayList<PendingIntent>();

            SmsManager smsManager = SmsManager.getDefault();
            ArrayList<String> mSMSMessage = smsManager.divideMessage(input.getString("message"));

            for (int i = 0; i < mSMSMessage.size(); i++) {
                Intent iSent = new Intent(SENT)
                    .setPackage(context.getPackageName())
                    .setClass(context, SMSBroadcastReceiver.class)
                    .putExtra("result", res);
                Intent iDelivered = new Intent(DELIVERED)
                    .setPackage(context.getPackageName())
                    .setClass(context, SMSBroadcastReceiver.class)
                    .putExtra("result", res);

                PendingIntent sentPI      = PendingIntent.getBroadcast(context, i, iSent,      PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_IMMUTABLE);
                PendingIntent deliveredPI = PendingIntent.getBroadcast(context, i, iDelivered, PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_IMMUTABLE);

                sentPendingIntents.add(i, sentPI);
                deliveredPendingIntents.add(i, deliveredPI);
            }

            BroadcastReceiver sentReceiver = new SMSBroadcastReceiver();
            context.registerReceiver(sentReceiver, new IntentFilter(SENT), context.RECEIVER_NOT_EXPORTED);

            BroadcastReceiver deliveredReceiver = new SMSBroadcastReceiver();
            context.registerReceiver(deliveredReceiver, new IntentFilter(DELIVERED), context.RECEIVER_NOT_EXPORTED);

            smsManager.sendMultipartTextMessage(input.getString("number"), null, mSMSMessage, sentPendingIntents, deliveredPendingIntents);

            int miliSecSleep = 300;
            int miliSecMax = 1000 * 18;
            int miliSecDeliveredMin = 1000 * 5;
            while (miliSecMax > 0) {
                Thread.sleep(miliSecSleep);
                miliSecMax = miliSecMax - miliSecSleep;
                miliSecDeliveredMin = miliSecDeliveredMin - miliSecSleep;

                if (res[0] != null && (res[0].status.equals(DELIVERED) || miliSecDeliveredMin < 0)) {
                    if (res[0].error != null)
                         Log.e("~=", res[0].error);
                    else Log.d("~=", res[0].body);

                    break;
                }
            }
            if (res[0] == null) {
                res[0] = new Result("", "SMS status: 25s TimeOut for SMS sending has expired");
            }

            context.unregisterReceiver(sentReceiver);
            context.unregisterReceiver(deliveredReceiver);
        } catch (Exception e) {
            Log.e("~=", "SMS error: " + e.toString());
            res[0] = new Result("", "SMS error: " + e.toString());
        }

        return res[0];
    }

}

service.java:

public class SMSService extends Service {
    SMS sms = new SMS(this);

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        sms.sent('123456', 'test message');

SMSBroadcastReceiver.java:

public class SMSBroadcastReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d("~=", "this is never be called");

        Functions.Result[] result = intent.getExtras().getParcelableArray("result", Functions.Result.class);

        SmsMessage smsM = SmsMessage.createFromPdu(
            intent.getByteArrayExtra("pdu"),
            intent.getStringExtra("format")
        );

        if (getResultCode() == Activity.RESULT_OK || (smsM != null && smsM.getStatus() == Telephony.Sms.STATUS_COMPLETE))
            result[0] = new Functions.Result(intent.getAction() + " status: DONE", null, intent.getAction());
        else if (intent.getAction().equals(Functions.SENT))
            result[0] = new Functions.Result(null, intent.getAction() + " status: " + getConstantName(getResultCode(), SmsManager.class), intent.getAction());
        else if (smsM != null && smsM.getStatus() == Telephony.Sms.STATUS_FAILED)
            result[0] = new Functions.Result(null, intent.getAction() + " status: STATUS_FAILED (SMS not delivered)", intent.getAction());
    }

    private String getConstantName(int value, Class<?> cls) {
        for ( java.lang.reflect.Field f : cls.getDeclaredFields()) {
            int mod = f.getModifiers();
            if (Modifier.isStatic(mod) && Modifier.isPublic(mod) && Modifier.isFinal(mod)) {
                try {
                    // Log.d(LOG_TAG, String.format("%s = %d%n", f.getName(), (int) f.get(null)));
                    if ((int) f.get(null) == value) return f.getName();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

}

MainActivity.java -> 权限:READ_SMS、SEND_SMS、RECEIVE_SMS

AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
    <uses-permission android:name="android.permission.READ_SMS" />
    <uses-permission android:name="android.permission.SEND_SMS" />
    <uses-permission android:name="android.permission.READ_CONTACTS" />
    <uses-permission android:name="android.permission.RECEIVE_SMS" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher_foreground"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/Theme.Material3.DayNight"
        tools:targetApi="31">
        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <service
            android:name=".SMSService"
            android:enabled="true"
            android:exported="true">
        </service>

        <receiver
            android:name=".SMSBroadcastReceiver"
            android:exported="false">
            <intent-filter android:priority="2147483645">
                <action android:name="SMS_SENT" />
                <action android:name="SMS_DELIVERED" />
                <action android:name="android.provider.telephony.SMS_RECEIVED"></action>
            </intent-filter>
        </receiver>
    </application>

</manifest>
java android broadcastreceiver sms smsmanager
1个回答
0
投票

非常感谢@MikeM。我已经彻底郁闷了。我将你的代码(在我看来是非必要部分)与我的代码结合起来,莫名其妙地它开始在三星 \o/ 上为我工作。它要么在小米上不起作用,要么完全随机工作,并且根本无法识别传递的事件消息(SmsMessage.createFromPdu() 为空),但现在我可能没有勇气进行下一步编辑我的解决方案。经过这次短信体验后,我认为 Android 是一个非常糟糕的操作系统。我很高兴我没有正式开发移动应用程序:D .
只是为了好玩,我的代码的当前版本在这里https://github.com/ObscurusGrassator/jjplugin-sms/tree/main/android-apk-source/app/src/main/java/jjplugin/obsgrass/sms

Java @MikeM 解决方案:https://gist.github.com/gonodono/8802779b2119497b848b72803fbaeec1

Kotlin @MikeM 解决方案:https://github.com/gonodono/sms-sender

© www.soinside.com 2019 - 2024. All rights reserved.