简体   繁体   English

屏幕关闭后Firestore无法更新

[英]Firestore not updating after screen is turned off

I am running my app on my physical device and the real time Firestore update works fine till the screen is turned off. 我正在物理设备上运行我的应用程序,实时Firestore更新可以正常工作,直到屏幕关闭为止。

Here is the function I use to update my data: 这是我用来更新数据的函数:

private void updateNotifyGroup(String groupCreator, final String groupKey) {

    // IT WORKS EXACTLY AS IN addChildEventListener()
    // ADD groupRepository.getCreatorGroup(groupKeyMsg) instead of currentUser
    Log.i("debinf callfrag", "groupCreator" + groupCreator);
    Log.i("debinf callfrag", "groupKey" + groupKey);
    CollectionReference collectionReference = CallRoot.collection(groupCreator).document(groupKey).collection("ClientList");

    collectionReference.addSnapshotListener(new EventListener<QuerySnapshot>() {
        @Override
        public void onEvent(@javax.annotation.Nullable QuerySnapshot queryDocumentSnapshots, @javax.annotation.Nullable FirebaseFirestoreException e) {

            if (e != null) {
                Log.i("debinf callfrag", "Listen failed.", e);
                return;
            }

            if (queryDocumentSnapshots != null && !queryDocumentSnapshots.isEmpty()){

                for (DocumentChange documentChange : queryDocumentSnapshots.getDocumentChanges()) {
                    //Log.i("debinf callfrag", "entering in loop = " + documentChange.getDocument().getData());
                    switch (documentChange.getType()) {
                        case ADDED:
                            Log.i("debinf callfrag", "data added = " + documentChange.getDocument().getData().get("notifyGroup"));

                            for (int i = 0; i < clientList.size(); i++) {

                                if (clientList.get(i).getCid().equals(documentChange.getDocument().getId())) {
                                    //Toast.makeText(getContext(), "Client name is " + clientList.get(i).getName(), Toast.LENGTH_SHORT).show();
                                    clientList.get(i).setNotifygroup(documentChange.getDocument().getData().get("notifyGroup").toString());
                                    mClientListAdapter.notifyDataSetChanged();
                                    break;

                                }
                            }
                            break;

                        case MODIFIED:
                            Log.i("debinf callfrag", "data modified = " + documentChange.getDocument().getId());
                            for (int i = 0; i < clientList.size(); i++) {

                                if (clientList.get(i).getCid().equals(documentChange.getDocument().getId())) {
                                    Toast.makeText(getContext(), "Client name is " + clientList.get(i).getName(), Toast.LENGTH_SHORT).show();
                                    clientList.get(i).setNotifygroup(documentChange.getDocument().getData().get("notifyGroup").toString());
                                    mClientListAdapter.notifyDataSetChanged();
                                    break;

                                }
                            }
                            break;

                        case REMOVED:
                            Log.i("debinf callfrag", "data removed = " + documentChange.getDocument().getData());
                            break;
                    }
                }

            }

        }
    });

}

That is the result before the screen is turned off: 这是屏幕关闭之前的结果:

02-10 16:42:32.890 20019-20019/com.example.aliton.myapp I/debinf callfrag: groupCreatorAJ0uyrTm95ODvCuua71cB17ueBt2
02-10 16:42:32.890 20019-20019/com.example.aliton.myapp I/debinf callfrag: groupKey-LXM0N48OOHTpwa8kNmJ
02-10 16:42:32.981 20019-20019/com.example.aliton.myapp I/debinf callfrag: data added = Desligado
02-10 16:42:32.982 20019-20019/com.example.aliton.myapp I/debinf callfrag: data added = Agendado
02-10 16:42:32.983 20019-20019/com.example.aliton.myapp I/debinf callfrag: data added = Ligar
02-10 16:42:32.984 20019-20019/com.example.aliton.myapp I/debinf callfrag: data added = Nao Atende
02-10 16:42:32.985 20019-20019/com.example.aliton.myapp I/debinf callfrag: data added = Andamento
02-10 16:42:32.987 20019-20019/com.example.aliton.myapp I/debinf callfrag: data added = Finalizado
02-10 16:42:32.988 20019-20019/com.example.aliton.myapp I/debinf callfrag: data added = Recusado

When my device turns the screen off , the lifecycle is onPause and onStop . 当我的设备关闭屏幕时,生命周期为onPauseonStop When turning the screen on, the lifecycle is onStart and onResume . 打开屏幕时,生命周期为onStartonResume

My app works similarly to the app presented in this link: 我的应用程序的工作类似于此链接中提供的应用程序:

android fragment to fragment communication : update recyclerView of the ReceiverFragment via interface android片段到片段的通信:通过接口更新ReceiverFragment的recyclerView

After I turn the screen on, I manually change the value of the field from Ligar to AnyThing and my physical device does not get notified about the change in Firestore. 打开屏幕后,我将该字段的值从Ligar手动更改为AnyThing,并且我的物理设备未收到有关Firestore中更改的通知。

Just my Emulator gets notified about the change in Firestore. 只是我的模拟器收到有关Firestore更改的通知。

My physical device only gets notified after re-running on Android Studio: 只有在Android Studio上重新运行后,我的物理设备才会收到通知:

02-10 17:25:33.296 21287-21287/com.example.aliton.myapp I/debinf callfrag: groupCreatorAJ0uyrTm95ODvCuua71cB17ueBt2
02-10 17:25:33.296 21287-21287/com.example.aliton.myapp I/debinf callfrag: groupKey-LXM0N48OOHTpwa8kNmJ
02-10 17:25:33.903 21287-21287/com.example.aliton.myapp I/debinf callfrag: data added = Desligado
02-10 17:25:33.904 21287-21287/com.example.aliton.myapp I/debinf callfrag: data added = Agendado
02-10 17:25:33.905 21287-21287/com.example.aliton.myapp I/debinf callfrag: data added = AnyThing
02-10 17:25:33.906 21287-21287/com.example.aliton.myapp I/debinf callfrag: data added = Nao Atende
02-10 17:25:33.907 21287-21287/com.example.aliton.myapp I/debinf callfrag: data added = Andamento
02-10 17:25:33.908 21287-21287/com.example.aliton.myapp I/debinf callfrag: data added = Finalizado
02-10 17:25:33.909 21287-21287/com.example.aliton.myapp I/debinf callfrag: data added = Recusado
02-10 17:25:34.945 21287-21287/com.example.aliton.myapp I/debinf callfrag: data modified = 629584107

How do I make permanent connection to Firestore even atfer the screen is turned on again? 即使屏幕再次打开,如何与Firestore建立永久连接?

Android will stop your app from functioning when the user isn't actively using it. 当用户未积极使用应用时,Android会阻止其运行。 This is to prevent apps from draining the battery. 这是为了防止应用耗尽电池电量。 You should allow for this to happen - read about doze and app standby modes in the Android documentation. 您应该允许这种情况发生-阅读Android文档中有关打do和应用待机模式的信息。

If you really must continue doing work when the screen is off, you need to create a foreground service . 如果确实必须在屏幕关闭时继续进行工作,则需要创建一个前台服务 Note that the documentation warns you about limiting use of foreground services. 请注意,文档警告您有关限制使用前台服务的信息。 If you are just trying to maintain a connection to Firestore, that is not a very good use of a foreground service. 如果您只是想维护与Firestore的连接,则不是很好地使用前台服务。

This is not a solution, but it made me think that it solved the problem. 这不是解决方案,但使我认为它解决了问题。

I do not know if the solution that I am presenting here is the appropriated solution, but it seems to solve the problem of reestablishing the connection with Firestore after turning on the screen (returning from Doze Mode ). 我不知道我在这里介绍的解决方案是否是适当的解决方案,但是似乎可以解决打开屏幕后(从“ 打ze模式”返回)与Firestore重新建立连接的问题。

I implemented a connection with Firestore in onStart : 我在onStart实现了与Firestore的连接:

@Override
public void onStart() {
    super.onStart();
    Log.i("debinf callfrag", "onStart");
    if (groupKeyFromSender != null) {
        updateNotifyGroup(groupCreatorFromSender, groupKeyFromSender);
    }

}

For those who are starting in Android Studio like me and are interested in the code to understand new functionalities, here comes the code: 对于像我这样开始使用Android Studio并对代码了解新功能感兴趣的用户,请参考以下代码:

public class CallFragment extends Fragment {

    View view;
    private RecyclerView mClientList;
    private RecyclerView.Adapter mClientListAdapter;
    private RecyclerView.LayoutManager mClientListLayoutManager;

    private String receivedFromSender;
    private String currentUser, groupKeyFromSender, groupCreatorFromSender;

    ArrayList<ClientObject> clientList;

    SQLiteDatabase clientListTable;
    ClientRepository clientRepository;

    private FirebaseAuth mAuth;
    FirebaseFirestore CallRoot;

    static Context mContext;

    private static String rootPath = Environment.getExternalStorageDirectory()+"/";


    public CallFragment() {
        // Required empty public constructor
    }

    public void getDataFromGroupFragment(String groupCreatorFromSender, String groupKeyFromSender, boolean addToCall) {
        if (groupKeyFromSender != null) {
            this.groupCreatorFromSender = groupCreatorFromSender;
            this.groupKeyFromSender = groupKeyFromSender;
            if (new File(rootPath + groupKeyFromSender, "client.db").isFile()) {
                if (addToCall) {
                    addClientToCall(groupCreatorFromSender, groupKeyFromSender);
                } else if (!addToCall) {
                    removeClientOfCall(groupKeyFromSender);
                }
            }
        }
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        view = inflater.inflate(R.layout.call_fragment, container, false);

        setHasOptionsMenu(true);

        mAuth = FirebaseAuth.getInstance();
        currentUser = mAuth.getCurrentUser().getUid();
        CallRoot = FirebaseFirestore.getInstance();

        mContext = container.getContext();
        //Log.i("debinf recgfrag", "mContext in onCreate : " + getContext());

        clientList = new ArrayList<>();

        initializeRecyclerView();

        return view;
    }


    private void removeClientOfCall(String pathToClientTable) {

        //Log.i("debinf recgfrag", "mContext in clientReading" + mContext);

        ClientDatabaseHelper clientDatabaseHelper = new ClientDatabaseHelper(mContext,"client.db", rootPath+pathToClientTable+"/");

        clientListTable = clientDatabaseHelper.getReadableDatabase();
        clientRepository = new ClientRepository(clientListTable);
        ArrayList<ClientObject> clientObjects = clientRepository.SearchAllClients();

        clientList.removeAll(clientObjects);
        Log.i("debinf recfrag", "clientList.size() Remove in clientReading is " + clientList.size());
        mClientListAdapter = new CallAdapter(mContext,clientList);
        //Log.i("debinf recfrag", "mClientList in clientReading is " + mClientList);
        mClientList.setAdapter(mClientListAdapter);
        mClientListAdapter.notifyDataSetChanged();

    }

    private void addClientToCall(String groupCreator, String groupKey) {

        ClientDatabaseHelper clientDatabaseHelper = new ClientDatabaseHelper(mContext,"client.db", rootPath+groupKey+"/");

        clientListTable = clientDatabaseHelper.getReadableDatabase();
        clientRepository = new ClientRepository(clientListTable);
        ArrayList<ClientObject> clientObjects = clientRepository.SearchAllClients();

        clientList.addAll(clientObjects);
        Log.i("debinf recfrag", "clientList in clientReading is " + clientList.get(0).getName());

        updateNotifyGroup(groupCreator, groupKey);

        mClientListAdapter = new CallAdapter(mContext,clientList);
        //Log.i("debinf recfrag", "mClientList in clientReading is " + mClientList);
        mClientList.setAdapter(mClientListAdapter);
        //mClientListAdapter.notifyDataSetChanged();

    }

    private void updateNotifyGroup(String groupCreator, final String groupKey) {

        // IT WORKS EXACTLY AS IN addChildEventListener()
        // ADD groupRepository.getCreatorGroup(groupKeyMsg) instead of currentUser
        Log.i("debinf callfrag", "groupCreator" + groupCreator);
        Log.i("debinf callfrag", "groupKey" + groupKey);
        CollectionReference collectionReference = CallRoot.collection(groupCreator).document(groupKey).collection("ClientList");

        collectionReference.addSnapshotListener(new EventListener<QuerySnapshot>() {
            @Override
            public void onEvent(@javax.annotation.Nullable QuerySnapshot queryDocumentSnapshots, @javax.annotation.Nullable FirebaseFirestoreException e) {

                if (e != null) {
                    Log.i("debinf callfrag", "Listen failed.", e);
                    return;
                }

                if (queryDocumentSnapshots != null && !queryDocumentSnapshots.isEmpty()){

                    for (DocumentChange documentChange : queryDocumentSnapshots.getDocumentChanges()) {
                        //Log.i("debinf callfrag", "entering in loop = " + documentChange.getDocument().getData());
                        switch (documentChange.getType()) {
                            case ADDED:
                                Log.i("debinf callfrag", "data added = " + documentChange.getDocument().getData().get("notifyGroup"));

                                for (int i = 0; i < clientList.size(); i++) {

                                    if (clientList.get(i).getCid().equals(documentChange.getDocument().getId())) {
                                        //Toast.makeText(getContext(), "Client name is " + clientList.get(i).getName(), Toast.LENGTH_SHORT).show();
                                        clientList.get(i).setNotifygroup(documentChange.getDocument().getData().get("notifyGroup").toString());
                                        mClientListAdapter.notifyDataSetChanged();
                                        break;

                                    }
                                }
                                break;

                            case MODIFIED:
                                Log.i("debinf callfrag", "data modified = " + documentChange.getDocument().getId());
                                for (int i = 0; i < clientList.size(); i++) {

                                    if (clientList.get(i).getCid().equals(documentChange.getDocument().getId())) {
                                        Toast.makeText(getContext(), "Client name is " + clientList.get(i).getName(), Toast.LENGTH_SHORT).show();
                                        clientList.get(i).setNotifygroup(documentChange.getDocument().getData().get("notifyGroup").toString());
                                        mClientListAdapter.notifyDataSetChanged();
                                        break;

                                    }
                                }
                                break;

                            case REMOVED:
                                Log.i("debinf callfrag", "data removed = " + documentChange.getDocument().getData());
                                break;
                        }
                    }

                }

            }
        });

    }

    private void initializeRecyclerView() {

        mClientList = (RecyclerView) view.findViewById(R.id.clientList);
        mClientList.setNestedScrollingEnabled(false);
        mClientList.setHasFixedSize(false);
        mClientListLayoutManager = new LinearLayoutManager(mContext,LinearLayout.VERTICAL,false);
        mClientList.setLayoutManager(mClientListLayoutManager);

        mClientListAdapter = new CallAdapter(mContext,clientList);
        mClientList.setAdapter(mClientListAdapter);

    }


    @Override
    public void onStart() {
        super.onStart();
        Log.i("debinf callfrag", "onStart");
        if (groupKeyFromSender != null) {
            updateNotifyGroup(groupCreatorFromSender, groupKeyFromSender);
        }

    }


    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        menu.clear();
        inflater.inflate(R.menu.options_call, menu);
        super.onCreateOptionsMenu(menu, inflater);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        super.onOptionsItemSelected(item);

        switch (item.getItemId()){
            case R.id.play_option:
                Toast.makeText(getContext(), "PlayOption Selected", Toast.LENGTH_SHORT).show();
                doSomething();
                return true;

            case R.id.stop_option:
                Toast.makeText(mContext, "option Stop", Toast.LENGTH_SHORT).show();
                return true;

        }

        return false;

    }

    private void doSomething() {
        Toast.makeText(mContext, "didSomething", Toast.LENGTH_SHORT).show();
    }

}

To make my code a bit clearer, I am updating the button text: 为了使代码更清晰,我正在更新按钮文本:

Good luck! 祝好运!

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

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