簡體   English   中英

在打盹模式下使用 Ably 的問題

[英]Issue with using Ably in Doze mode

我使用 Ably API 作為兩個 Android 設備(手機)之間的通信方式。 第一個是“”,它向第二個(“從”)發送請求。 Slave ”的主要部分是后台服務,等待主人的命令。 一旦來自服務器的請求到達,服務器獲取其地理位置並將其發送回服務器。 問題是,當機處於打盹模式時,Ably 不起作用(' onMessage ' 方法不起作用),直到我喚醒手機。 同時,如果我使用帶有“ slave ”服務的短信接收器(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");
}

}

精通工程師在這里。 這里的問題主要與應用程序不在前台時 android 處理服務的方式有關。 使用 Ably 會有所幫助,但我們無法阻止操作系統暫停該線程:D。

設備處理短信的方式不同,系統不受用戶空間控制。 無論如何都會收到它們,然后您的應用程序可以處理它們。

這篇文章中,有一個關於后台線程/任務中的 websockets 的答案。 它或多或少是關於它的 go 的正確方法。 有一些關於如何在 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