如何不断向Firebase发送数据,避免打Do睡和App Standby

问题描述

我开发了此应用,该应用需要在用户按下一个按钮时将数据发送到Firestore,并在用户停止它(通过按下另一个按钮)时结束。即使用户正在做其他事情,或者即使用户将手机放在待机状态达数小时,也必须发送数据(所以我需要避免打ze和App Standby)。

我使用了一项服务来实现这一目标,似乎只有一件事以错误的方式起作用。

服务

public class MyService extends Service {

    public static final String CHANNEL_ID = "ForegroundServiceChannel";

    // vars declaration

    private Date date = null;

    // get every X seconds 
    public static final long DEFAULT_SYNC_INTERVAL = 60000;

    private Runnable runnableService = new Runnable() {
        @Override
        public void run() {

            class GetDataTask extends AsyncTask<String,Void,List<Data>> {

                @Override
                protected void onPreExecute() {
                    super.onPreExecute();
                    if(getPositionData.isCancelled()){
                        return;
                    }
                }

                @SuppressLint({"MissingPermission","HardwareIds"})
                @Override
                protected List<Data> doInBackground(String... v) {

                    // skipping get Timestamp code
                    

                    // skipping get position code
                    
                        myPos = new Data(position.getId(),latitude,longitude,timestamp);

                        // Insert data into Firebase
                        documentReference = firebaseFirestore.collection("data").document();
                        Map<String,Object> data = new HashMap<>();
                        data.put("lat",myPos.getLat());
                        data.put("date",myPos.getDate().toString());
                        documentReference.set(data).addOnSuccessListener(new OnSuccessListener<Void>() {
                            @Override
                            public void onSuccess(Void aVoid) {
                                Log.i("data","data added.\n");
                            }
                        });

                        Toast.makeText(DataPollService.this,"" +
                                "ID: " + myPos.getImei()
                                        + " Latitude: " + myPos.getLat()
                                        + " Longitude " + myPos.getLng()
                                        + " Date: " + myPos.getDate(),Toast.LENGTH_SHORT).show();
                                    }
                                }
                            },Looper.getMainLooper());

                    positionsList.add(myPos);
                    return positionsList;
                }

                protected void onPostExecute(List<Data> result) {
                    Position.getInstance().setPositions(result);
                }
            }


            // RUN TASK
            getPositionData = new GetDataTask();
            getPositionData.execute(position.getId());

            handler.postDelayed(runnableService,DEFAULT_SYNC_INTERVAL);
        }
    };

    @Override
    public int onStartCommand(Intent intent,int flags,int startId) {

        String input = intent.getStringExtra("inputExtra");
        createNotificationChannel();
        Intent notificationIntent = new Intent(this,MainActivity.class);
        PendingIntent pendingIntent = PendingIntent.getActivity(this,notificationIntent,0);
        Notification notification = new NotificationCompat.Builder(this,CHANNEL_ID)
                .setContentTitle("Foreground Service")
                .setContentText(input)
                .setSmallIcon(R.drawable.ksurf)
                .setContentIntent(pendingIntent)
                .build();
        startForeground(1,notification);

        handler = new Handler();
        handler.post(runnableService);

        return START_NOT_STICKY;
    }

    // onBind
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onDestroy() {
        Toast.makeText(this,"Service Stopped",Toast.LENGTH_LONG).show();
        Log.d("show","onDestroy");
        handler.removeCallbacks(runnableService);
        stopSelf();
    }

    private void createNotificationChannel() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel serviceChannel = new NotificationChannel(
                    CHANNEL_ID,"Foreground Service Channel",notificationmanager.IMPORTANCE_DEFAULT
            );
            notificationmanager manager = getSystemService(notificationmanager.class);
            manager.createNotificationChannel(serviceChannel);
        }
    }

}

在MainActivity中,按以下方式启动服务:

Intent serviceIntent = new Intent(this,MyService.class);
serviceIntent.putExtra("inputExtra","run");
ContextCompat.startForegroundService(this,serviceIntent);

如果我不使用电话,而是让应用程序在后台发送数据,则在我再次打开应用程序之前,数据不会发送到Firebase。服务没有停止,我只需要打开应用程序即可将数据发送到Firebase! 我读到有关Firebase Cloud Messaging的信息,但我不知道我是否需要它们。我在做什么错了?

解决方法

即使用户正在做其他事情,或者即使用户将手机搁置几个小时也必须发送数据(所以我需要避免打ze和App Standby)。

通常来说,在“打ze”或“应用待机”模式下让您的应用运行进程不是一个好主意。 Android documentation甚至指出网络访问已暂停;因此,可能无法保证您的进程能够可靠运行或终止于其他优先级更高的应用。

问题是,如果我在1个小时内不使用应用程序(因此手机处于待机状态),则只有在我再次打开应用程序时,firebase上的数据才会添加。就像它们保存在缓存中并在再次打开应用程序时发送到数据库一样。

根据documentation”“ Cloud Firestore支持离线数据持久性。此功能缓存您的应用程序正在使用的Cloud Firestore数据的副本,因此您的应用程序可以在设备上访问数据处于离线状态。您可以写入,阅读,收听和查询缓存的数据。当设备恢复在线状态时,Cloud Firestore会将您的应用所做的所有本地更改同步到Cloud Firestore后端。“

服务没有停止,我只需要打开应用程序即可将数据发送到firebase!我读到有关Firebase Cloud Messaging的信息,但我不知道我是否需要它们。

当客户端应用进入空闲模式时,recommended solution会使用 Firebase Cloud Messaging 从服务器ping您的应用。当您需要向后端服务器发送实时下游消息或仅通知客户端应用程序有新数据可用于同步(这可能是您要查找的)时,此功能很有用。

有关更多详细信息,请参阅上述文档。

,

在每种平台或语言中,都有一种连接Firebase的不同方法,因此,请提供有关该平台的更多信息可以帮助??, 但您可以检查此链接,也许他可以为您提供帮助-> link