java - 如何在Android中创建firebase后台服务?

标签 java android firebase google-cloud-firestore

我是 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() {
        .....
    }
}

最佳答案

I'd like to create background service in android that listen for new Document created in Firestore.

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

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

A foreground service performs some operation that is noticeable to the user. For example, an audio app would use a foreground service to play an audio track. Foreground services must display a Notification. Foreground services continue running even when the user isn't interacting with the app.

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

根据您的评论:

Nope I want to listen for new documents created in Firestore.

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

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

Cloud Functions for Firebase let you automatically run backend code in response to events triggered by Firebase features and HTTPS requests. Your code is stored in Google's cloud and runs in a managed environment. There's no need to manage and scale your own servers.

编辑:

How do Cloud Functions actually work?

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

也许这不是您想要的发送通知,但这是一个简单的示例,我认为您能够明白这个想法。

关于java - 如何在Android中创建firebase后台服务?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58284392/

相关文章:

java - 对于 MySql DB,在 Hibernate(部署在 JBoss 5.1.0 上)中使用大写(与下划线组合)作为列名时出现奇怪的行为

java - webapps 未获取 tomcat 7 conf/web.xml 自定义错误页面

android - 推荐用于 Android 开发工作站的 Linux 发行版

php - 如何使用 php FCM 同时处理对 Android 和 iOS 的不同通知负载?

android - 当我使用 actionbar searchview android 进行搜索时,searchfragment 多次添加到后退堆栈

firebase - 在 Firebase 中手动记录应用内购买事件

ios - 主题未显示在 firebase 控制台中

java - 如何进行 Java 字节码 active 分析?

KitKat 之前(api 18 之前)的 Android HTML 代码打印

firebase - orderByChild 按字典顺序而不是按指定键对键进行排序