Firebase не может получить доступ к базе данных в фоновом потоке (с закрытым приложением) Невозможно создать обработчик внутри потока, который не вызвал Looper.prepare () - PullRequest
0 голосов
/ 08 октября 2018

Моему приложению нужно запускать геозоны в фоновом режиме (приложение закрыто), поэтому я создал класс с JobIntentService, чтобы запустить это геозону, но когда срабатывает какая-то геозона, приложение должно прочитать базу данных firebase и поэтому происходит сбой приложения с помощью этого logcat:

    --------- beginning of crash
2018-10-07 09:02:33.952 11623-14893/com.app.GNV E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #1
    Process: com.app.GNV, PID: 11623
    java.lang.RuntimeException: An error occurred while executing doInBackground()
        at android.os.AsyncTask$3.done(AsyncTask.java:318)
        at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:354)
        at java.util.concurrent.FutureTask.setException(FutureTask.java:223)
        at java.util.concurrent.FutureTask.run(FutureTask.java:242)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
        at java.lang.Thread.run(Thread.java:762)
     Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
        at android.os.Handler.<init>(Handler.java:200)
        at android.os.Handler.<init>(Handler.java:114)
        at com.google.firebase.database.zza.<init>(com.google.firebase:firebase-database@@16.0.2:1024)
        at com.google.firebase.database.obfuscated.zzb.zza(com.google.firebase:firebase-database@@16.0.2:77)
        at com.google.firebase.database.obfuscated.zzu.zza(com.google.firebase:firebase-database@@16.0.2:2234)
        at com.google.firebase.database.obfuscated.zzad.zzb(com.google.firebase:firebase-database@@16.0.2:92)
        at com.google.firebase.database.obfuscated.zzad.zza(com.google.firebase:firebase-database@@16.0.2:42)
        at com.google.firebase.database.FirebaseDatabase.zza(com.google.firebase:firebase-database@@16.0.2:357)
        at com.google.firebase.database.FirebaseDatabase.getReference(com.google.firebase:firebase-database@@16.0.2:188)
        at com.app.GNV.Service.GeofenceNotification.displayNotification(GeofenceNotification.java:44)
        at com.app.GNV.Service.GeofenceTransitionsJobIntentService.onHandleWork(GeofenceTransitionsJobIntentService.java:61)
        at android.support.v4.app.JobIntentService$CommandProcessor.doInBackground(JobIntentService.java:392)
        at android.support.v4.app.JobIntentService$CommandProcessor.doInBackground(JobIntentService.java:383)
        at android.os.AsyncTask$2.call(AsyncTask.java:304)
        at java.util.concurrent.FutureTask.run(FutureTask.java:237)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133) 
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607) 
        at java.lang.Thread.run(Thread.java:762) 

Я думаю, проблема была в том, что JobIntentService запускается в фоновом потоке, а firebase не работает в фоновом потоке.Может быть, мне нужно использовать другой способ для чтения базы данных Firebase ... любое предложение?

Примечание: приложение должно быть закрыто и запускать геозоны в фоновом режиме.

GeofenceTransitionJobIntentService.class

    public class GeofenceTransitionsJobIntentService extends JobIntentService {
        private static final int JOB_ID = 2018;
        private static final String TAG = "GeofenceTransitionsIS";

        public static void enqueueWork(@NonNull Context context, Intent intent) {
            enqueueWork(context, GeofenceTransitionsJobIntentService.class, JOB_ID, intent);
        }

        @Override
        protected void onHandleWork(@NonNull Intent intent) {
            // Initialize SharedPreferences editor
            SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
            SharedPreferences.Editor editor = sharedPreferences.edit();

            // Carrega coordenadas atual e do ultimo abastecimento registrado
            boolean cfgSaiuDoPosto  = sharedPreferences.getBoolean("CfgSaiuDoPosto", false);
            boolean cfgTempoMinimo  = sharedPreferences.getBoolean("CfgTempoMinimo", false);

            GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
            if (geofencingEvent.hasError()) {
                String errorMessage = GeofenceErrorMessages.getErrorString(this, geofencingEvent.getErrorCode());
                Log.e(TAG, errorMessage);
                return;
            }

            int transitionType = geofencingEvent.getGeofenceTransition();
            if (transitionType == Geofence.GEOFENCE_TRANSITION_DWELL || transitionType == Geofence.GEOFENCE_TRANSITION_EXIT) {

                List<Geofence> triggeringGeofences = geofencingEvent.getTriggeringGeofences();

                for (Geofence geofence : triggeringGeofences) {

                    switch (transitionType) {
                        case Geofence.GEOFENCE_TRANSITION_DWELL:
                            String mPostoID = geofence.getRequestId();
                            long dataNofif = System.currentTimeMillis();
                            if ( cfgTempoMinimo && cfgSaiuDoPosto ) {
                                GeofenceNotification geofenceNotification = new GeofenceNotification(this);
                                geofenceNotification.displayNotification(mPostoID, dataNofif);
                                Log.w(TAG,"Notificando possível abastecimento");
                            }
                            break;

                        case Geofence.GEOFENCE_TRANSITION_EXIT:
                            editor.putBoolean("CfgGeofencesAdded", false).apply();
                            Log.w(TAG,"Reiniciando GeofenceService pois saiu do raio de MasterGeo");

                            // Restart GeofenceService
                            GeofencesDataSource gds = new GeofencesDataSource(getApplicationContext());
                            gds.CarregaGeofenceService();
                            break;
                    }
                }

            } else {
                // Log the error.
                Log.e(TAG, getString(R.string.geofence_transition_invalid_type, transitionType));
            }
        }
    }

GeofenceNotification.class

public class GeofenceNotification {
    private static final String TAG = "GeofenceNotification";
    private static final Integer NOTIFICATION_ID = 99;
    protected Context context;
    private static NotificationManager mNotificationManager;
    private static AlarmManager alarmManager;

    GeofenceNotification(Context context) {
        this.context = context;
        mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
    }

    void displayNotification(final String postoID, final long dataNotif) {

        DatabaseReference mPostosDBRef = Utils.getDatabase().getReference().child("postos");
        mPostosDBRef.child(postoID).addListenerForSingleValueEvent(new ValueEventListener() {
            public void onDataChange(@NonNull DataSnapshot dtSnap) {
                String mNome = "Nome do posto";
                if (dtSnap.exists())    { mNome = dtSnap.child("nome").getValue(String.class); }

                SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
                boolean cfgNotif = sharedPreferences.getBoolean("CfgNotif", true);
                if (cfgNotif) {
                    startNotification(context, postoID, mNome, dataNotif);
                } else {
                    gravaAbastecimento(context, postoID, dataNotif);
                }
            }
            public void onCancelled(@NonNull DatabaseError databaseError) {
                Log.e(TAG,"****** The read failed: " + databaseError);
            }
        });
    }

//... some irrelevant code ...
}

OK

1 Ответ

0 голосов
/ 10 октября 2018

Я просто нахожу обходной путь для выполнения GeofenceNotification / Чтение базы данных Firebase на mainThread:

                case Geofence.GEOFENCE_TRANSITION_DWELL:
                    final String mPostoID = geofence.getRequestId();
                    final long dataNofif = System.currentTimeMillis();
                    Log.w(TAG,"========== POSSIVEL ABASTECIMENTO =========");

                    if ( cfgTempoMinimo && cfgSaiuDoPosto ) {
                        Handler h = new Handler(Looper.getMainLooper());
                        h.post(new Runnable() {
                            public void run() {
                                GeofenceNotification geofenceNotification = new GeofenceNotification(GeofenceTransitionsJobIntentService.this);
                                geofenceNotification.displayNotification(mPostoID, dataNofif);
                                Log.w(TAG,"Notificando possível abastecimento");
                            }
                        });
                    }
                    break;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...