Я занимаюсь разработкой приложения, которое синхронизирует все входящие текстовые сообщения с сервером. Я использую Broadcast Receiver, но в какой-то момент синхронизация не происходит, что означает, что процесс вещательного приемника вроде как убит. Большинство предложений, которые я получаю в Интернете, еще больше сбивают меня с толку, учитывая, что я все еще изучаю Android. Мне нужна помощь, чтобы решить эту проблему, обеспечивая синхронизацию без необходимости запуска приложения пользователем вручную и даже после перезапуска системы Android. Это мой широковещательный приемник.
Некоторые предложения, которые я получил, включали реализацию JobService, который я пробовал, но не смог правильно узнать, как запустить приемник из класса JobService. Я думаю, что концепция смутила меня. Вот код, который я попробовал
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public class TextBroadcastService extends JobService {
MessageReceiver messageReceiver;
static String TAG = "TextBroadcastService";
@Override
public boolean onStartJob(JobParameters params) {
//Code to be executed by the service
BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
}
};
// registerReceiver(broadcastReceiver,Telephony.Sms.Intents);
Log.d(TAG, "onStartJob: serviceRunning: " );
ServiceUtil.scheduleJob(getApplicationContext());
return false;
}
@Override
public boolean onStopJob(JobParameters params) {
Log.d(TAG, "onStopJob: Service destroyed: ");
return false;
}
}
Тогда вот как я пытался запланировать задание, затем я понял, что не соединяюсь, как организовать вещание, и класс JobService запускает другой.
public class ServiceUtil {
/** This class is responsible for scheduling jobs using the JobScheduler **/
public static void scheduleJob(Context context){
ComponentName serviceComponent = new ComponentName(context, TextBroadcastService.class);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
JobInfo.Builder jobBuilder = new JobInfo.Builder(0,serviceComponent);
jobBuilder.setMinimumLatency(30 *1000); // Wait at least 30s
jobBuilder.setOverrideDeadline(60 * 1000); //Setting Maximum delay at 60s
JobScheduler jobScheduler = (JobScheduler)context
.getSystemService(context.JOB_SCHEDULER_SERVICE);
jobScheduler.schedule(jobBuilder.build());
}
}
}
public class MessageReceiver extends BroadcastReceiver {
Handler mHandler;
Context context;
String sender, timestamp, msgID, text_message;
MessageDbHelper dbHelper;
private static String BASE_API_URL= "";
public static final String PREFS_NAME = "server_url";
private static final String TAG = "MessageReceiver";
String DATE_FORMAT = "dd/MM/yyyy HH:mm:ss";
SimpleDateFormat formatter =
new SimpleDateFormat(DATE_FORMAT, Locale.getDefault());
private static int counter = 0;
static int successMessageCounter = 0;
static int failedMessageCounter = 0;
public MessageReceiver() {
}
@TargetApi(Build.VERSION_CODES.M)
@Override
public void onReceive(final Context context, Intent intent) {
this.context= context;
dbHelper = new MessageDbHelper(context);
SharedPreferences settings = context.getSharedPreferences(PREFS_NAME, 0);
BASE_API_URL = settings.getString("server_url_str", "");
Log.d(TAG, "onCreate: base url"+BASE_API_URL);
if (Telephony.Sms.Intents.SMS_RECEIVED_ACTION.equals(intent.getAction())) {
final Bundle data = intent.getExtras();
HandlerThread bgHandlerThread=new HandlerThread("MyCoolBackgroundThread");
bgHandlerThread.start();
mHandler=new Handler(bgHandlerThread.getLooper());
Runnable backgroundRunnable = new Runnable() {
@Override
public void run() {
passReceivedMsg(data);
}
};
mHandler.post(backgroundRunnable);
}
}
private void passReceivedMsg(final Bundle bundleData) {
if (bundleData !=null ){
try {
final Object[] pdusObj = (Object[]) bundleData.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);
// msgID = UUID.randomUUID().toString();
String received_message = "You Received message from: " +sender
+ " message: " + text_message
+ " at: " + timestamp;
Log.d(TAG, "passReceivedMsg: received msg "+received_message);
Toast.makeText(context, received_message, Toast.LENGTH_SHORT).show();
try {
uploadMessageData();
} catch (JSONException e) {
e.printStackTrace();
Log.d(TAG, "passReceivedMsg: exception "+e.getMessage());
Log.d(TAG, "passReceivedMsg: exception: errorCause "+e.getCause());
}
}
}
}
catch (Exception e){
Log.d(TAG, "onReceive: Error occurred "+e);
}
}
}
Я ожидаю, что приемник вещания перехватит все входящие SMS без необходимости запуска приложения вручную. Я также ожидаю, что приемник будет запущен после включения устройства в случае, если устройство было выключено, что в данный момент не происходит.
Ниже описано, как я регистрирую приемник в манифесте
<receiver
android:name=".utils.MessageReceiver"
android:enabled="true"
android:exported="true"
android:permission="android.permission.BROADCAST_SMS">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>