简体   繁体   English

在打盹模式下使用 Ably 的问题

[英]Issue with using Ably in Doze mode

I use Ably API as a way to communicate between two Android devices (mobile phones).我使用 Ably API 作为两个 Android 设备(手机)之间的通信方式。 The first one is a " Master " which sending a request to the second ("slave").第一个是“”,它向第二个(“从”)发送请求。 the main part of " Slave " is background service which is awaiting for the command from the master . Slave ”的主要部分是后台服务,等待主人的命令。 As soon as a request from the master arrives, the slave gets its geo-location and sends it back to the master .一旦来自服务器的请求到达,服务器获取其地理位置并将其发送回服务器。 The trouble is that while the slave is in the doze mode Ably doesn't work (' onMessage ' method doesn't work) until I wake the phone up.问题是,当机处于打盹模式时,Ably 不起作用(' onMessage ' 方法不起作用),直到我唤醒手机。 At the same time, if I use sms reciever (onRecieve method of mainBroadcastReceiver ) with the service of " slave " it works fine even when the phone is "asleep".同时,如果我使用带有“ slave ”服务的短信接收器(mainBroadcastReceiver 的onRecieve方法),即使手机处于“睡眠”状态,它也能正常工作。 Is there any ideas how to resolve that issue?有什么想法可以解决这个问题吗? Here is the code of my Service.这是我的服务的代码。

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 Engineer here.精通工程师在这里。 The issue here is mostly to do with the way android handles services when the app is not in the foreground.这里的问题主要与应用程序不在前台时 android 处理服务的方式有关。 Using Ably helps but we cant stop the OS pausing that thread:D.使用 Ably 会有所帮助,但我们无法阻止操作系统暂停该线程:D。

SMS's are not handled in the same way by the device, the system is not under user-space control.设备处理短信的方式不同,系统不受用户空间控制。 They'll be received no matter what and then your application can handle them.无论如何都会收到它们,然后您的应用程序可以处理它们。

In this post There is an answer about websockets in a background thread/task.这篇文章中,有一个关于后台线程/任务中的 websockets 的答案。 and its more or less the correct way to go about it.它或多或少是关于它的 go 的正确方法。 There are a few examples out there about how to do this on android in flutter: https://medium.com/stuart-engineering/keep-flutter-running-background-on-android-6ffc85be0234有一些关于如何在 flutter 中的 android 上执行此操作的示例: https://medium.com/stuart-engineering/keep-android-running-be02-on4-android-running-background-3ff

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM