在Doze模式下使用Ably的问题



我使用Ably API作为两个Android设备(手机(之间的通信方式。第一个是">Master";其向第二个("从"(发送请求。">";是后台服务,正在等待的命令。一旦发出请求,就会获取其地理位置,并将其发送回主机。问题是,当处于休眠模式时,Ably不工作(">onMessage"方法不工作(,直到我唤醒手机。同时,如果我使用sms reciever(mainBroadcastReceiver的onRecieve方法(的服务";即使当手机处于"待机"状态时,它也能很好地工作;"睡着了";。有什么办法解决这个问题吗?这是我的服务代码。

package ru.volganap.nikolay.kids_monitor_ably;
import android.annotation.SuppressLint;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.location.LocationManager;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.provider.Settings;
import android.telephony.SmsManager;
import android.util.Log;
import android.app.Service;
import android.os.IBinder;
import android.widget.Toast;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import androidx.core.app.NotificationCompat;
import io.ably.lib.realtime.AblyRealtime;
import io.ably.lib.realtime.Channel;
import io.ably.lib.realtime.CompletionListener;
import io.ably.lib.types.AblyException;
import io.ably.lib.types.ErrorInfo;
import io.ably.lib.types.Message;
public class KidService extends Service implements KM_Constants {*emphasized text*
private SharedPreferences sharedPrefs;
BroadcastReceiver mainBroadcastReceiver;
private String parent_sender;
FindGeoPos fg;
private NotificationManager notificationManager;
private static final int NOTIFY_ID = 101;
private static final String NOTIFY_CHANNEL_ID = "CHANNEL_ID";
public static final int DEFAULT_NOTIFICATION_ID = 101;
private Channel channel;
public void onCreate() {
super.onCreate();
Log.d(LOG_TAG, "Service: onCreate");
//EventBus eventBus = EventBus.builder().addIndex(new MyEventBusIndex()).build();
sharedPrefs = getSharedPreferences(PREF_ACTIVITY, MODE_PRIVATE);
notificationManager = (NotificationManager) this.getSystemService(this.NOTIFICATION_SERVICE);
try {   //Init ABLY
AblyRealtime ablyRealtime = new AblyRealtime(ABLY_API_KEY);
channel = ablyRealtime.channels.get(ABLY_ROOM);
channel.subscribe(PARENT_PHONE, new Channel.MessageListener() {
@Override
public void onMessage(Message messages) {
Log.d(LOG_TAG, "Service - Ably message received: " + messages.data);
if (messages.name.equals(PARENT_PHONE) && messages.data.equals(getResources().getString(R.string.parent_sms))) {
getPosition();
}
}
});
} catch (AblyException e) {
e.printStackTrace();
}
}
@SuppressLint("MissingPermission")
public int onStartCommand(Intent intent, int flags, int startId) {
if (startId > 1) {
stopSelf(startId);
}
Log.d(LOG_TAG, "Service: onStartCommand, starId = " + startId + ", flags = " + flags);
//Send Foreground Notification
sendNotification("KMService","");
if (!EventBus.getDefault().hasSubscriberForEvent(KidService.class)) {
EventBus.getDefault().register(this);
}
//Init SMS Receiver
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_FROM_BR);
mainBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (intent != null) {
parent_sender = intent.getStringExtra("sender");
Log.d(LOG_TAG, "Service: Get back with Sender-parent");
getPosition();
}
}
};
registerReceiver(mainBroadcastReceiver, filter);
return START_STICKY;
}
public void sendNotification(String Title,String Text) {
Intent notificationIntent = new Intent(getApplicationContext(), MainActivity.class);
//notificationIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
notificationIntent.setAction(Intent.ACTION_MAIN);
PendingIntent contentIntent = PendingIntent.getActivity(getApplicationContext(), 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder builder = new NotificationCompat.Builder(getApplicationContext(), NOTIFY_CHANNEL_ID)
.setOngoing(true)
.setSmallIcon(R.drawable.ic_stat_name)
.setWhen(System.currentTimeMillis())
.setContentIntent(contentIntent)
.setContentTitle(Title)
.setContentText(Text);
//.setPriority(PRIORITY_HIGH);
createChannelIfNeeded(notificationManager);
Notification notification = builder.build();
//notificationManager.notify(NOTIFY_ID, notification);
startForeground(NOTIFY_ID, notification);
}
public static void createChannelIfNeeded(NotificationManager manager) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel notificationChannel = new NotificationChannel(NOTIFY_CHANNEL_ID, NOTIFY_CHANNEL_ID, NotificationManager.IMPORTANCE_DEFAULT);
manager.createNotificationChannel(notificationChannel);
}
}
// Find the location
protected void getPosition () {
if (isLocationEnabled()) {
Log.d(LOG_TAG, "Service: new FindGeoPos call");
Handler handler = new Handler(Looper.getMainLooper());
Runnable myRunnable = new Runnable() {
@Override
public void run() {
fg = new FindGeoPos(getBaseContext());
}
};
handler.post(myRunnable);
} else {
Toast.makeText(getApplicationContext(), "Service: Please turn on your location", Toast.LENGTH_LONG).show();
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(intent);
Log.d(LOG_TAG, "Service: Please turn on your location");
}
}
private boolean isLocationEnabled() {
LocationManager locationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) || locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
}
@Subscribe//(threadMode = ThreadMode.MAIN)
public void onEvent(EventBus_Kid event){
Log.d(LOG_TAG, "Service: EventBus is worked, position is:  " + event.location_message);
fg = null;
parent_sender = sharedPrefs.getString(PARENT_PHONE, "" );
try { // ABLY PUBLISH a message
channel.publish(KID_PHONE,  event.location_message, new CompletionListener() {
@Override
public void onSuccess() {
Log.d(LOG_TAG,"Service - onSuccess - Message sent");
}
@Override
public void onError(ErrorInfo reason) {
Log.d(LOG_TAG,"Service - onError - Message not sent, error occurred: " + reason.message);
sendSMSMessage (parent_sender, event.location_message);
}
});
} catch (AblyException e) {
Log.d(LOG_TAG,"Service - AblyException - Message not sent: " + e.toString());
sendSMSMessage (parent_sender, event.location_message);
}
//OkHttp is starting
String user = KID_PHONE;
OkHttpRequest serverReguest = new OkHttpRequest();
serverReguest.serverGetback(user, event.location_message);
}
protected void sendSMSMessage (String phoneNo, String message) {
try {
SmsManager smsManager = SmsManager.getDefault();
smsManager.sendTextMessage(phoneNo, null, message, null, null);
Toast.makeText(getApplicationContext(), "SMS sent.", Toast.LENGTH_LONG).show();
Log.d(LOG_TAG, "Service: SMS sent to number: " + phoneNo + " with message: " + message);
} catch (Exception e) {
Toast.makeText(getApplicationContext(),"SMS faild, please try again later", Toast.LENGTH_LONG).show();
e.printStackTrace();
Log.d(LOG_TAG, "Service: SMS failed. SMS Exception: " + e.toString());
}
}
public void onDestroy() {
super.onDestroy();
Log.d(LOG_TAG, "Service: onDestroy");
unregisterReceiver(mainBroadcastReceiver);
EventBus.getDefault().unregister(this);
channel.unsubscribe();
notificationManager.cancel(DEFAULT_NOTIFICATION_ID);
stopSelf();
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
return null;
//throw new UnsupportedOperationException("Service: Not yet implemented");
}

}

此处为Ably工程师。这里的问题主要与android在应用程序不在前台时处理服务的方式有关。使用Ably有帮助,但我们无法阻止操作系统暂停线程:D。

SMS的处理方式与设备不同,系统不受用户空间控制。不管怎样,它们都会被收到,然后你的应用程序就可以处理它们了。

在这篇文章中,有一个关于后台线程/任务中的websocket的答案。这或多或少是正确的做法。关于如何在flutter中的android上做到这一点,有几个例子:https://medium.com/stuart-engineering/keep-flutter-running-background-on-android-6ffc85be0234

相关内容

  • 没有找到相关文章

最新更新