简体   繁体   中英

Android - In fragments, Is onResume() called before onStart()?

In a section of an application I'm building, there's an embedded zxing qr scanner, and I'm using it inside a fragment.

If the app has not granted Manifest.permission.CAMERA permission yet, it asks for the permission and then continue with enabling the scanner.

The problem is, I call barcodeView.resume() inside onResume() and I ask for the permission in onStart() . So it should ask for the permission first and after that call barcodeView.resume() inside the onResume() . But apparently the opposite happens, if the app is not granted the permission yet, it throws this exception

java.lang.NullPointerException: Attempt to invoke virtual method 'void com.journeyapps.barcodescanner.DecoratedBarcodeView.resume()' on a null object reference

How come is that happening ? Isn't onResume() called after onStart() not before?

Here's my fragment code:

package com.lab.rafael.smartattendance;

import android.Manifest;
import android.content.pm.PackageManager;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.Fragment;
import android.support.v4.content.ContextCompat;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.google.zxing.ResultPoint;
import com.google.zxing.client.android.BeepManager;
import com.journeyapps.barcodescanner.BarcodeCallback;
import com.journeyapps.barcodescanner.BarcodeResult;
import com.journeyapps.barcodescanner.DecoratedBarcodeView;

import java.util.List;


public class TakeAttendanceFragment extends Fragment {

    private final int CAMERA_PERM_REQUEST = 0;
    private static final String TAG = TakeAttendanceFragment.class.getSimpleName();
    DecoratedBarcodeView barcodeView = null;
    BeepManager beepManager = null;
    String lastText;

    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        return inflater.inflate(R.layout.fragment_take_attendance, container, false);
    }

    @Override
    public void onStart() {
        super.onStart();
        if(getActivity().getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){
            if(ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED)
            {
                ActivityCompat.requestPermissions(getActivity(), new String[] {Manifest.permission.CAMERA}, CAMERA_PERM_REQUEST);
            } else {
                startCamera();
            }
        }
    }

    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        if(requestCode == CAMERA_PERM_REQUEST) {
            if(grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                startCamera();
            }
        }
    }

    private void startCamera() {
        try {
            if(getView() != null) {
                barcodeView = (DecoratedBarcodeView) getView().findViewById(R.id.barcode_scanner);
                barcodeView.decodeContinuous(barcodeCallback);
                beepManager = new BeepManager(getActivity());
            }
        } catch (Exception e) {
            Log.e(TAG, e.getMessage());
        }
    }

    private BarcodeCallback barcodeCallback = new BarcodeCallback() {
        @Override
        public void barcodeResult(BarcodeResult result) {
            if(result.getText() == null || result.getText().equals(lastText)) return;

            lastText = result.getText();
            barcodeView.setStatusText(lastText);
            beepManager.playBeepSoundAndVibrate();
        }

        @Override
        public void possibleResultPoints(List<ResultPoint> resultPoints) {

        }
    };

    public void onResume()
    {
        super.onResume();
        barcodeView.resume();
    }

    public void onPause() {
        super.onPause();
        barcodeView.pause();
    }
}

onStart is called before onResume, yes.

The Permission request dialog is not blocking, so the fragments lifecycles will continue when you ask for permissions.

So it'll go like this:
- onStart
- Request permission
- onResume (at this point the user hasn't granted permission yet).

You'll need to have a check in onResume to see if the barcodeView is not null and permission have been granted.

If the permission is granted, the onRequestPermissionsResult will be called immediately after onStart, as it's not async if the permission is granted, then this code would work fine.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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