首页 > 解决方案 > AirLocation 库的问题

问题描述

我有一个项目,我正在使用空位库进行一项活动来获取位置。应用程序在我的最后运行良好,但 Playstore 报告显示一些频繁的崩溃,我正在尝试调试它。

这是我的活动代码

public class Selfie extends AppCompatActivity {
    private AirLocation airLocation;
    public static final String TAG = "SelfieAct";
    private static final int REQUEST = 1856;
    private TextView Time, location;
    Button time_stamp, lcn_btn, Atten_btn;
    private static final String TIME_STAMP = null;
    NetworkController networkController;
    private Button cptrm_btn;
    private ImageView imgview;
    private static final int CAMERA_REQUEST = 1888;
    SharedPreferences prefs;
    Gson gson = new Gson();
    OkHttpClient okHttpClient = new OkHttpClient.Builder().build();
    private SharedPreferences.Editor editor;
    CheckBox checkBox;
    Bitmap lesimg;
    private LocationManager locationManager;
    private String locationText;
    static final int REQUEST_IMAGE_CAPTURE = 1;
    private Bitmap mImageBitmap;
    private String mCurrentPhotoPath;
    private ImageView mImageView;
    File photoFile;
    boolean facelocationset = false;
    TextView textView;
    Uri photoUri;
    SwipeRefreshLayout swipeRefreshLayout;



    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_selfie_activity);

        StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
        StrictMode.setVmPolicy(builder.build());
        swipeRefreshLayout = findViewById(R.id.swiperefresh);

        swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                finish();
                startActivity(getIntent());
            }
        });


        networkController = RetrofitClientInstance.getRetrofitInstance().create(NetworkController.class);if (Build.VERSION.SDK_INT >= 23) {
            String[] PERMISSIONS = {android.Manifest.permission.READ_EXTERNAL_STORAGE,android.Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.ACCESS_FINE_LOCATION};
            if (!hasPermissions(Selfie.this, PERMISSIONS)) {
                Toast.makeText(this, "Please allow location permission", Toast.LENGTH_SHORT).show();
                ActivityCompat.requestPermissions(Selfie.this, PERMISSIONS, REQUEST );
            } else {
                //do here
            }
        } else {
            //do here
        }

        locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            // TODO: Consider calling
            //    ActivityCompat#requestPermissions
            // here to request the missing permissions, and then overriding
            //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
            //                                          int[] grantResults)
            // to handle the case where the user grants the permission. See the documentation
            // for ActivityCompat#requestPermissions for more details.
            Toast.makeText(this, "Cannot Continue Without Location Permission", Toast.LENGTH_SHORT).show();
            finish();
            return;
        }

        Time = findViewById(R.id.time);
        prefs = getSharedPreferences(getResources().getString(R.string.prefs), MODE_PRIVATE);
        editor = getSharedPreferences(getResources().getString(R.string.prefs), MODE_PRIVATE).edit();
        Atten_btn = findViewById(R.id.mark_Attendence);


        cptrm_btn = findViewById(R.id.cptr_btn);
        imgview = findViewById(R.id.imageView10);
        textView=findViewById(R.id.Waitmsg);

        airLocation = new AirLocation(this, true, true, new AirLocation.Callbacks() {
            @Override
            public void onSuccess(@NotNull Location location) {
                Geocoder geocoder = new Geocoder(Selfie.this, Locale.getDefault());
                List<Address> addresses = null;
                try {
                    addresses = geocoder.getFromLocation(location.getLatitude(), location.getLongitude(), 1);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                locationText = addresses.get(0).getAddressLine(0);
                textView.setText(locationText);
                facelocationset = true;
            }

            @Override
            public void onFailed(@NotNull AirLocation.LocationFailedEnum locationFailedEnum) {
                // do something
            }
        });

        cptrm_btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                cameraIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                cameraIntent.setFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);



                if (cameraIntent.resolveActivity(getPackageManager()) != null) {



                    // Create the File where the photo should go
                    photoFile = null;
                    try {
                        photoFile = createImageFile();
                    } catch (IOException ex) {
                        // Error occurred while creating the File
                        Log.i(TAG, "IOException");
                        ex.printStackTrace();
                        Log.d(TAG, "onClick: " + ex.getMessage());
                        Log.d(TAG, "onClick: " + ex.toString());
                    }
                    // Continue only if the File was successfully created
                    if (photoFile != null) {

                        photoUri = FileProvider.getUriForFile(Selfie.this, BuildConfig.APPLICATION_ID + ".provider", photoFile);
                        cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);
                        startActivityForResult(cameraIntent, REQUEST_IMAGE_CAPTURE);
                    }
                }

            }
        });

        Atten_btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                if(facelocationset && mImageBitmap != null) {
                    Date dt = new Date(System.currentTimeMillis());
                    DateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");

                    RequestBody requestFile = RequestBody.create(
                                    MediaType.parse(getContentResolver().getType(FileProvider.getUriForFile(Selfie.this, BuildConfig.APPLICATION_ID + ".provider", photoFile))),
                                    photoFile
                            );
                    MultipartBody.Part body =
                            MultipartBody.Part.createFormData("file", photoFile.getName(), requestFile);
                    MultipartBody.Part io_time =
                            MultipartBody.Part.createFormData("io_time", df.format(dt));
                    MultipartBody.Part user_id =
                            MultipartBody.Part.createFormData("user_id", prefs.getString("uid", null));
                    MultipartBody.Part loc =
                            MultipartBody.Part.createFormData("loc", locationText);

                    RequestBody enctype = RequestBody.create(
                            okhttp3.MultipartBody.FORM, "multipart/form-data");


                    networkController.mark_attendance("Bearer " + prefs.getString("token", null), enctype, body, io_time, user_id, loc).enqueue(new Callback<JsonObject>() {
                        @Override
                        public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
                            if (response.code() == 200) {
                                if(response.body().get("ok").getAsString().equals("true")){
                                    Log.d(TAG, "onResponse: " + "Done");
                                    Toast.makeText(Selfie.this, "Punch Success", Toast.LENGTH_SHORT).show();
                                    finish();
                                }
                            }
                        }

                        @Override
                        public void onFailure(Call<JsonObject> call, Throwable t) {
                            Log.d(TAG, "onFailure: "+ Log.getStackTraceString(t));
                        }
                    });

                }
                else{
                    Toast.makeText(Selfie.this, "Waiting for Location or Image" , Toast.LENGTH_SHORT).show();
                }



            }
        });


    }

    private File createImageFile() throws IOException {
        // Create an image file name
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
        String imageFileName = "JPEG_" + timeStamp + "_";
        File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
        File image = File.createTempFile(
                imageFileName,  /* prefix */
                ".jpg",         /* suffix */
                storageDir      /* directory */
        );

        // Save a file: path for use with ACTION_VIEW intents
        mCurrentPhotoPath = image.getAbsolutePath();
        return image;
    }




    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        airLocation.onActivityResult(requestCode, resultCode, data);
        if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
            try {
                InputStream ims = getContentResolver().openInputStream(photoUri);
                mImageBitmap = BitmapFactory.decodeStream(ims);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }

            try {
                Bitmap mImageDisplayBitmap = handleSamplingAndRotationBitmap(getApplicationContext(), photoUri);
                imgview.setImageBitmap(mImageDisplayBitmap);
            }
            catch (IOException io){}
            File file = new File (String.valueOf(photoFile));
            try {
                mImageBitmap = new Compressor(this)
                        .setMaxHeight(200) //Set height and width
                        .setMaxWidth(200)
                        .setQuality(100) // Set Quality
                        .compressToBitmap(photoFile);
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                OutputStream fOut = new FileOutputStream(file);
                mImageBitmap.compress(Bitmap.CompressFormat.JPEG, 100, fOut);
            }
            catch(FileNotFoundException f){}
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        airLocation.onRequestPermissionsResult(requestCode, permissions, grantResults);
        switch (requestCode) {
            case REQUEST: {
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    //do here
                } else {
                    Toast.makeText(Selfie.this, "The app was not allowed to read your store.", Toast.LENGTH_LONG).show();

                }
            }
        }
    }

    private static boolean hasPermissions(Context context, String... permissions) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && context != null && permissions != null) {
            for (String permission : permissions) {
                if (ActivityCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) {
                    return false;
                }
            }
        }
        return true;
    }


    public static Bitmap handleSamplingAndRotationBitmap(Context context, Uri selectedImage)
            throws IOException {
        int MAX_HEIGHT = 1024;
        int MAX_WIDTH = 1024;

        // First decode with inJustDecodeBounds=true to check dimensions
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        InputStream imageStream = context.getContentResolver().openInputStream(selectedImage);
        BitmapFactory.decodeStream(imageStream, null, options);
        imageStream.close();

        // Calculate inSampleSize
        options.inSampleSize = calculateInSampleSize(options, MAX_WIDTH, MAX_HEIGHT);

        // Decode bitmap with inSampleSize set
        options.inJustDecodeBounds = false;
        imageStream = context.getContentResolver().openInputStream(selectedImage);
        Bitmap img = BitmapFactory.decodeStream(imageStream, null, options);

        img = rotateImageIfRequired(context, img, selectedImage);
        return img;
    }

    private static int calculateInSampleSize(BitmapFactory.Options options,
                                             int reqWidth, int reqHeight) {
        // Raw height and width of image
        final int height = options.outHeight;
        final int width = options.outWidth;
        int inSampleSize = 1;

        if (height > reqHeight || width > reqWidth) {

            // Calculate ratios of height and width to requested height and width
            final int heightRatio = Math.round((float) height / (float) reqHeight);
            final int widthRatio = Math.round((float) width / (float) reqWidth);

            // Choose the smallest ratio as inSampleSize value, this will guarantee a final image
            // with both dimensions larger than or equal to the requested height and width.
            inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;

            // This offers some additional logic in case the image has a strange
            // aspect ratio. For example, a panorama may have a much larger
            // width than height. In these cases the total pixels might still
            // end up being too large to fit comfortably in memory, so we should
            // be more aggressive with sample down the image (=larger inSampleSize).

            final float totalPixels = width * height;

            // Anything more than 2x the requested pixels we'll sample down further
            final float totalReqPixelsCap = reqWidth * reqHeight * 2;

            while (totalPixels / (inSampleSize * inSampleSize) > totalReqPixelsCap) {
                inSampleSize++;
            }
        }
        return inSampleSize;
    }

    private static Bitmap rotateImageIfRequired(Context context, Bitmap img, Uri selectedImage) throws IOException {

        InputStream input = context.getContentResolver().openInputStream(selectedImage);
        ExifInterface ei;
        if (Build.VERSION.SDK_INT > 23)
            ei = new ExifInterface(input);
        else
            ei = new ExifInterface(selectedImage.getPath());

        int orientation = ei.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);

        switch (orientation) {
            case ExifInterface.ORIENTATION_ROTATE_90:
                return rotateImage(img, 90);
            case ExifInterface.ORIENTATION_ROTATE_180:
                return rotateImage(img, 180);
            case ExifInterface.ORIENTATION_ROTATE_270:
                return rotateImage(img, 270);
            default:
                return img;
        }
    }

    private static Bitmap rotateImage(Bitmap img, int degree) {
        Matrix matrix = new Matrix();
        matrix.postRotate(degree);
        Bitmap rotatedImg = Bitmap.createBitmap(img, 0, 0, img.getWidth(), img.getHeight(), matrix, true);
        img.recycle();
        return rotatedImg;
    }

}

Playstore 报告在此代码块中显示 NullPointerException

airLocation = new AirLocation(this, true, true, new AirLocation.Callbacks() {
    @Override
    public void onSuccess(@NotNull Location location) {
        Geocoder geocoder = new Geocoder(Selfie.this, Locale.getDefault());
        List<Address> addresses = null;
        try {
            addresses = geocoder.getFromLocation(location.getLatitude(), location.getLongitude(), 1);
        } catch (IOException e) {
            e.printStackTrace();
        }
        locationText = addresses.get(0).getAddressLine(0);
        textView.setText(locationText);
        facelocationset = true;
    }

任何人都可以找出哪一行代码可能是导致此问题的原因以及我该如何解决它。

标签: androidnullpointerexception

解决方案


    airLocation = new AirLocation(this, true, true, new AirLocation.Callbacks() {
        @Override
        public void onSuccess(@NotNull Location location) {
            Geocoder geocoder = new Geocoder(Selfie.this, Locale.getDefault());
            List<Address> addresses = null;
            try {
                addresses = geocoder.getFromLocation(location.getLatitude(), location.getLongitude(), 1);
            } catch (IOException e) {
                e.printStackTrace();
            }

            // ***** Changes *****
            if (addresses != null) {
                locationText = addresses.get(0).getAddressLine(0);
                if (locationText != null) {
                    textView.setText(locationText);
                }
                facelocationset = true;
            }
        }
    }

推荐阅读