【问题标题】:How to create firebase background service in Android?如何在 Android 中创建 Firebase 后台服务?
【发布时间】:2019-10-08 10:16:57
【问题描述】:

我是 Android 新手。我想在 android 中创建后台服务,以侦听在 Firestore 中创建的新文档。我已经准备好所有代码,但服务却一次又一次地启动。

  • 你能告诉我应该怎么做才能只启动一次服务。每当我打开应用程序时,它都会在控制台中打印 >> 附加监听器。我希望它只执行一次并保持在后台运行。

  • 如果我在 Play 商店中更新应用程序会发生什么情况,它会使用应用程序中更新的新代码重新启动服务吗?

我遵循的示例代码:https://gist.github.com/vikrum/6170193

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.demo">

    <uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />
    <uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" />
    <uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WRITE_CONTACTS" />
    <uses-permission android:name="android.permission.READ_CONTACTS" />
    <uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".SignUp">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
       <!-- Other activities -->

        <!-- authentication service -->

        <service android:name=".service.firestore.listener.FirestoreActivityListener"
            android:exported="false"
            android:process=":remote">
        </service>
    </application>
</manifest>

FirestoreActivityListener.java

package com.demo.service.firestore.listener;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;

import com.google.firebase.FirebaseApp;
import com.google.firebase.firestore.DocumentChange;
import com.google.firebase.firestore.EventListener;
import com.google.firebase.firestore.FirebaseFirestore;
import com.google.firebase.firestore.FirebaseFirestoreException;
import com.google.firebase.firestore.FirebaseFirestoreSettings;
import com.google.firebase.firestore.QuerySnapshot;

import javax.annotation.Nullable;

import static com.google.firebase.firestore.DocumentChange.Type.ADDED;

/**
 * @author vicky.thakor
 * @since 2019-02-06
 */
public class FirestoreActivityListener extends Service {

    private static final String COLLECTION = "users/%s/activities";
    private FirebaseFirestore firestore;

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

    @Override
    public void onCreate() {
        super.onCreate();
        FirebaseApp.initializeApp(this);
        this.firestore = FirebaseFirestore.getInstance();
        FirebaseFirestoreSettings settings = new FirebaseFirestoreSettings.Builder()
                .setTimestampsInSnapshotsEnabled(true)
                .build();
        firestore.setFirestoreSettings(settings);
        activitiesListener();
    }

    public void activitiesListener(){
        System.err.println(">> listener attached");
        firestore.collection(String.format(COLLECTION, "xxxxxxxxx"))
                .addSnapshotListener(new EventListener<QuerySnapshot>() {
                    @Override
                    public void onEvent(@Nullable QuerySnapshot querySnapshot, @Nullable FirebaseFirestoreException e) {
                        for (DocumentChange dc : querySnapshot.getDocumentChanges()) {
                            switch (dc.getType()) {
                                case ADDED:
                                    System.err.println(">> " + dc.getDocument().toString());
                                    break;
                            }
                        }
                    }
                });
    }
}

SignUp.java

package com.demo;

import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.Button;
import android.widget.EditText;

import com.google.firebase.FirebaseApp;
import com.google.firebase.FirebaseException;
import com.google.firebase.FirebaseTooManyRequestsException;
import com.google.firebase.auth.FirebaseAuthInvalidCredentialsException;
import com.google.firebase.auth.PhoneAuthCredential;
import com.google.firebase.auth.PhoneAuthProvider;
import com.demo.home.Home;
import com.demo.model.ParcelableUser;
import com.demo.repository.SharedPreferencesRepository;
import com.demo.repository.impl.SharedPreferencesRepositoryImpl;
import com.demo.service.firestore.listener.FirestoreActivityListener;
import com.demo.util.AlertUtil;
import com.demo.util.IntentConstants;
import com.demo.util.StringUtil;

import java.util.concurrent.TimeUnit;

public class SignUp extends AppCompatActivity {

    private SharedPreferencesRepository sharedPreferencesRepository;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        /* initialization */
        sharedPreferencesRepository = new SharedPreferencesRepositoryImpl(this);
        startService(new Intent(this, FirestoreActivityListener.class));
        verifyRegisteredUser();

        setContentView(R.layout.signup);
        registerNewUser();
    }

    private void verifyRegisteredUser() {
        .....
    }

    private void registerNewUser() {
        .....
    }
}

【问题讨论】:

  • 所以你希望你的服务经常执行一些任务,我说对了吗?
  • 不,我想收听在 Firestore 中创建的新文档。该服务应在后台运行。通知之类的东西。
  • 抱歉,我对此不够清楚。我的意思是您想使用该服务来经常检查更新,而您的问题是让该服务每隔一定的时间间隔重新进行此检查?

标签: java android firebase google-cloud-firestore


【解决方案1】:

我想在 android 中创建后台服务,以侦听在 Firestore 中创建的新文档。

您确实可以在 Android 服务中执行此操作,但请记住,服务仅代表一种方式,您可以通过该方式告诉操作系统您有一些必须完成的后台工作,而这并不真正需要附加视图(活动)。

根据有关Android services的官方文档,如果您想尽可能地从正在运行的服务中受益:

前台服务执行一些用户可以注意到的操作。例如,音频应用程序将使用前台服务来播放音轨。前台服务必须显示通知。即使用户没有与应用交互,前台服务也会继续运行。

换句话说,您需要为通知提供一个图标,以便通知用户该应用正在消耗资源。

根据您的评论:

不,我想收听在 Firestore 中创建的新文档。

是的,您可以将侦听器附加到数据库中的某个文档,甚至是查询,它会随着结果的变化而更新。但是请记住,您必须为获得的每个更新支付读取操作,这基本上意味着用户还将承担带宽成本以及电池消耗的成本。所以我总是推荐remove the listeners according to the life-cycler of the activity

当你想在后台收听一些文件时,这是你处理 Firestore 的一种方式,但也请考虑使用Cloud Functions for Firebase

Cloud Functions for Firebase 可让您自动运行后端代码,以响应由 Firebase 功能和 HTTPS 请求触发的事件。您的代码存储在 Google 的云中并在托管环境中运行。无需管理和扩展您自己的服务器。

编辑:

云函数实际上是如何工作的?

与客户端的情况一样,Cloud Functions 还允许您将侦听器附加到单个文档甚至查询。因此,当数据库中发生特殊情况时,可以触发云函数,例如,当某些文档被写入 Firestore 集合时。触发该功能后,您可以采取一些措施。正如 Frank van Puffelen 在他的评论中提到的,例如,您可以发送通知。对于 Android,请看下面一个简单的示例:

也许这不是你想要的,发送通知,但这是一个简单的例子,我想你会明白的。

【讨论】:

  • 很好的答案亚历克斯!我从中学到了更多关于 Android 服务的知识。 :)
  • 对于使用 Cloud Functions 的方法,添加它的工作方式可能会很有用。 IE。当文档写入 Firestore 时调用 Cloud Function,然后它使用 FCM 向应用程序发送通知,然后唤醒应用程序中的 onMessageReceived 代码,该代码可以显示通知(或执行其他任何操作)需要)。
  • @FrankvanPuffelen 谢谢你这么说 ?。是的,你是对的,我应该首先添加更多关于 Cloud Functions 的信息。刚刚更新了我的答案。
  • 嗨维姬!我可以帮助您了解其他信息吗?如果您认为我的回答对您有所帮助,请考虑采纳(✔️)。我真的很感激。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-03-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-26
  • 2022-09-23
  • 2022-10-18
相关资源
最近更新 更多