首页 > 解决方案 > 是否可以从 Java/Kotlin 中的 android WorkManager 类启动广播接收器

问题描述

我被一个问题困扰了一个多月了。我想从 Android WorkManager 类启动广播接收器。我想接收/过滤所有传入的短信,然后发布到服务器。但是,我当前的解决方案在 android 系统终止应用程序并且接收器同步停止之前的几个小时内无法工作,或者当我从 PDU 对象(来自电话 Intent)中提取文本消息时,onReceive 方法已经返回。因此,为了解决这个问题,我希望让广播 onReceive 方法在 WorkManager 中运行,以确保进程不会这么快终止。我尝试过阅读,但没有得到适合我的解决方案,或者我可能对广播接收器或 android 后台进程的工作方式不清楚。这是我目前的实现。

    @TargetApi(Build.VERSION_CODES.M)
    @Override
    public void onReceive(final Context context, Intent intent) {
        this.context= context;
        if (Telephony.Sms.Intents.SMS_RECEIVED_ACTION.equals(intent.getAction())) {
           final Bundle data = intent.getExtras();

            if (data !=null ) {
                try {
                    final Object[] pdusObj = (Object[]) data.get("pdus");
                    if (pdusObj != null) {
                        for (int i = 0; i < pdusObj.length; i++) {
                            SmsMessage currentMessage =
                                    SmsMessage.createFromPdu((byte[]) pdusObj[i]);
                            Log.d(TAG, "run: currentMessage: " + currentMessage);

                            Log.d(TAG, "passReceivedMsg: handleMessage: message " + currentMessage);

                            int msgNo = counter++;
                            msgID = "SMS_ID_0" + msgNo;
                            sender = currentMessage.getDisplayOriginatingAddress();
                            text_message = currentMessage.getDisplayMessageBody();

                            long timestampMilliseconds = System.currentTimeMillis();
                            timestamp = formatter.format(timestampMilliseconds);

                            Data.Builder dataBuilder = new Data.Builder();
                            dataBuilder.putString("sender",sender);
                            dataBuilder.putString("message",text_message);
                            dataBuilder.putString("timestamp",timestamp);
                            dataBuilder.putString("sms_id",msgID);
//                            Log.d(TAG, "onReceive:  key:" +key+ " and keyValue "+data.get(key));

                            WorkManager mWorkManager = WorkManager.getInstance();
                            OneTimeWorkRequest mRequest = new OneTimeWorkRequest
                                    .Builder(MessageSyncWorker.class)
                                    .setInputData(dataBuilder.build())
                                    .build();
                            mWorkManager.enqueue(mRequest);
                        }
                    }
                }
                catch (Exception e){
                    Log.d(TAG, "onReceive: Exception occured "+e.getMessage());
                }
            }


       }

    }

下面是我的 MessageSyncWorker 类,它扩展了 Worker-doWork() 方法

@NonNull
@Override
public Result doWork() {

Data inputData1 = getInputData();

sender = inputData1.getString("sender");
text_message = inputData1.getString("message");
timestamp = inputData1.getString("timestamp");
msgID = inputData1.getString("sms_id");
Log.d(TAG, "doWork: Mesage "+text_message);

SharedPreferences sharedPreferences =
        PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
BASE_API_URL = sharedPreferences.getString("settings_server_url", "");

Log.d(TAG, "doWork: BASE URL "+BASE_API_URL);

try {
    //here I upload the data to the server
    uploadMessageData();
} catch (JSONException e) {
    e.printStackTrace();
    Log.d(TAG, "doWork: uploadMessage method Exception "+e.getMessage());
}


return Result.success();
}

标签: androidkotlinbroadcastreceiverandroid-broadcastandroid-workmanager

解决方案


最后,在评论区(针对这个问题)中可以看到详细讨论后,我已经破解了它。我现在有工作代码,我相信通过分享我可以帮助其他人遇到类似问题。下面是我是如何做到的。
这是 onReceive() 方法;

 @Override
    public void onReceive(Context context, Intent intent) {
        if (Telephony.Sms.Intents.SMS_RECEIVED_ACTION
                .equals(intent.getAction())){
            this.context = context;
            SmsMessage smsMessage = null;
            StringBuilder fullMessage = new StringBuilder();
            for (SmsMessage new_smsMessage : Telephony.Sms.Intents.getMessagesFromIntent(intent)){
                smsMessage = new_smsMessage;
                fullMessage.append(smsMessage.getDisplayMessageBody());
            }
            if (smsMessage ==null){
                return;
            }

            String sender = smsMessage.getOriginatingAddress();
            long timestampMilliseconds = System.currentTimeMillis();
            String timestamp = formatter.format(timestampMilliseconds);

            Log.d("NeTxt Receiver ", "onReceive: fullMessage: "+fullMessage);

            Data.Builder dataBuilder = new Data.Builder();
            dataBuilder.putString("fullMessage",fullMessage.toString());
            dataBuilder.putString("sender", sender);

            dataBuilder.putString("timestamp",timestamp);


            //defining constraints
            Constraints task_constraints = new Constraints.Builder()
                    .setRequiredNetworkType(NetworkType.CONNECTED)
                    .build();

            //scheduling the work
            WorkManager mWorkManager = WorkManager.getInstance();
            OneTimeWorkRequest mRequest = new OneTimeWorkRequest
                    .Builder(NewTxtWorker.class)
                    .setInputData(dataBuilder.build())
                    .setConstraints(task_constraints)
                    .build();
            mWorkManager.enqueue(mRequest);

            mWorkManager.getWorkInfoById(mRequest.getId());

        }

    }

下面是我的 doWork() 方法;

@NonNull
@Override
public Result doWork() {

    Data inputData = getInputData();
    String sender = inputData.getString("sender");
    String text_message = inputData.getString("fullMessage");
    String timestamp = inputData.getString("timestamp");

    Log.d("Txt WorkManager", "doWork: fullmessage: "+text_message);


    assert sender != null;
    assert text_message != null;
    if (!timestamp.isEmpty()||
            !sender.isEmpty()||
            !text_message.isEmpty()){

        FirebaseFirestore fireDb = FirebaseFirestore.getInstance();
        Map<String, Object> message = new HashMap<>();
        message.put("text_message", text_message);
        message.put("sender", sender);
        message.put("timestamp", timestamp);
        //sync the received message with the firebase firestore db
        fireDb.collection("text_messages")
                .add(message)
                .addOnSuccessListener(new OnSuccessListener<DocumentReference>() {
                    @Override
                    public void onSuccess(DocumentReference documentReference) {
                        Log.d("Txt WorkManager", "onSuccess: doc Id"
                                +documentReference.getId());
                    }
                })
               .addOnFailureListener(new OnFailureListener() {
                   @Override
                   public void onFailure(@NonNull Exception e) {
                       Log.d("Txt WorkManager", "onFailure: "+e.getMessage());
                   }
               }) ;

    }

    return Result.failure();
}

推荐阅读