ArthurHub / Android-Image-Cropper

Image Cropping Library for Android, optimized for Camera / Gallery.
Apache License 2.0
6.39k stars 1.37k forks source link

Field crash - RuntimeException #237

Open ankitbatra11 opened 7 years ago

ankitbatra11 commented 7 years ago

I have below crashed reported in production:

Fatal Exception: java.lang.RuntimeException: Unable to start activity ComponentInfo{com.tools.screenshot/com.tools.screenshot.editing.ui.activities.CropActivity}: java.lang.NullPointerException: Attempt to read from field 'java.lang.String com.theartofdev.edmodo.cropper.CropImageOptions.activityTitle' on a null object reference
       at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2307)
       at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2369)
       at android.app.ActivityThread.access$800(ActivityThread.java:153)
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1287)
       at android.os.Handler.dispatchMessage(Handler.java:111)
       at android.os.Looper.loop(Looper.java:135)
       at android.app.ActivityThread.main(ActivityThread.java:5273)
       at java.lang.reflect.Method.invoke(Method.java)
       at java.lang.reflect.Method.invoke(Method.java:372)
       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
Caused by java.lang.NullPointerException: Attempt to read from field 'java.lang.String com.theartofdev.edmodo.cropper.CropImageOptions.activityTitle' on a null object reference
       at com.theartofdev.edmodo.cropper.CropImageActivity.onCreate(SourceFile:63)
       at com.tools.screenshot.editing.ui.activities.CropActivity.onCreate(SourceFile:90)
       at android.app.Activity.performCreate(Activity.java:6119)
       at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105)
       at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2260)
       at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2369)
       at android.app.ActivityThread.access$800(ActivityThread.java:153)
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1287)
       at android.os.Handler.dispatchMessage(Handler.java:111)
       at android.os.Looper.loop(Looper.java:135)
       at android.app.ActivityThread.main(ActivityThread.java:5273)
       at java.lang.reflect.Method.invoke(Method.java)
       at java.lang.reflect.Method.invoke(Method.java:372)
       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
ankitbatra11 commented 7 years ago

And here is how I start the activity:

CropImage.activity(input)
                .setActivityTitle(activity.getString(R.string.crop))
                .setOutputCompressFormat(compressFormat)
                .setOutputCompressQuality(100)
                .setOutputUri(output)
                .start(activity, CropActivity.class);
ArthurHub commented 7 years ago

It's hard to say what is wrong without looking at CropActivity class. I guess you extended CropImageActivity but I don't see what would cause the intent not to contain the options data object...

ankitbatra11 commented 7 years ago

Yes, I extended the activity.

ArthurHub commented 7 years ago

Something is clearing the intent data... Can you post the code?

ankitbatra11 commented 7 years ago
@RuntimePermissions
public class CropActivity extends CropImageActivity {

    private static final int DEGREES_ROTATE_RIGHT = 90;

    @Inject
    ImageActionHandler imageActionHandler;

    @Inject
    DomainModel domainModel;

    @Inject
    Analytics analytics;

    @Inject
    MediaScanner mediaScanner;

    @Inject
    @Nullable
    @Named(AdsModule.MANAGER_CROPPER)
    AdsManager adsManager;

    private boolean deleteOriginal = false;
    private Image source;
    private final Intent resultIntent = new Intent();

    @Override
    public void onCreate(Bundle savedInstanceState) {
        applyTheme(ThemeSetting.getThemeRes(PreferenceManager.getDefaultSharedPreferences(this)));
        super.onCreate(savedInstanceState);

        DaggerEditingComponent
                .builder()
                .applicationModule(new ApplicationModule(this))
                .adsModule(new AdsModule(this))
                .build()
                .inject(this);

        Uri sourceUri = getIntent().getParcelableExtra(CropImage.CROP_IMAGE_EXTRA_SOURCE);
        source = new Image(sourceUri.getPath());

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            CropActivityPermissionsDispatcher.loadImageWithCheck(this);
        } else {
            loadImage();
        }

        if (adsManager != null) {
            adsManager.loadAd();
        }
    }

    @Override
    public void setContentView(@LayoutRes int layoutResID) {
        super.setContentView(R.layout.activity_crop);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_crop, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int itemId = item.getItemId();
        if (itemId == R.id.action_rotate_right) {
            rotateImage(DEGREES_ROTATE_RIGHT);
            analytics.logRotateEvent("right");
            return true;
        }
        if (itemId == R.id.save_new) {
            item.setChecked(true);
            cropImage();
            analytics.logSaveImageEvent("crop", "save_new");
            return true;
        }
        if (itemId == R.id.replace_original) {
            item.setChecked(true);
            deleteOriginal = true;
            cropImage();
            analytics.logSaveImageEvent("crop", "replace_original");
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    public void setTitle(CharSequence title) {
        super.setTitle(title);
        ActionBar actionBar = getSupportActionBar();
        if (actionBar != null) {
            actionBar.setTitle(title);
        }
    }

    @Override
    public void setTitle(int titleId) {
        setTitle(getString(titleId));
    }

    @Override
    public void onCropImageComplete(CropImageView view, final CropImageView.CropResult result) {
        if (!ActivityUtils.isActive(this)) {
            return;
        }

        Throwable t = result.getError();
        if (t != null) {
            Timber.e(t, "Crop image failed");
            ToastUtils.showShortToast(this, R.string.failed_to_save_image);
        } else {
            final Context context = getApplicationContext();
            final WeakReference<Activity> reference = new WeakReference<>(this);
            Callable<TaskExecutorDialog.OperationResult> callable = () -> {
                final Image image = domainModel.createImage(result.getUri());
                if (image != null) {
                    resultIntent.putExtra(Constants.EXTRA_IMAGES_ADDED, image.getAbsolutePath());
                    if (deleteOriginal) {
                        boolean result1 = domainModel.delete(source);
                        if (result1) {
                            resultIntent.putExtra(Constants.EXTRA_IMAGES_DELETED, source.getAbsolutePath());
                        } else {
                            ToastUtils.showShortToast(context, R.string.deletion_failed);
                        }
                    }
                }
                if (reference.get() != null) {
                    reference.get().setResult(Activity.RESULT_OK, resultIntent);
                }
                return TaskExecutorDialog.createImageResult(image);
            };
            TaskExecutorDialog.execute(this, callable, adsManager);
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        CropActivityPermissionsDispatcher.onRequestPermissionsResult(this, requestCode, grantResults);
    }

    @Override
    protected void onDestroy() {
        if (adsManager != null) {
            adsManager.destroy();
            adsManager = null;
        }
        super.onDestroy();
    }

    @Override
    protected void attachBaseContext(Context newBase) {
        String locale = LanguageSetting.getLocale(newBase, PreferenceManager.getDefaultSharedPreferences(newBase));
        super.attachBaseContext(LanguageContextWrapper.wrap(newBase, new Locale(locale)));
    }

    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
    @NeedsPermission({Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE})
    void loadImage() {
        CropImageViewCustom view = (CropImageViewCustom) findViewById(R.id.cropImageView);
        view.loadImage(source);
    }

    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
    @OnPermissionDenied({Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE})
    void onStoragePermissionDenied() {
        finish();
    }

    private void applyTheme(int themeRes) {
        setTheme(themeRes);
        ActivityUtils.resetStatusBarColor(this);
    }
}
Tarun416 commented 7 years ago

I am also facing the same problem.

nkek1027 commented 6 years ago

me too

cjy37 commented 6 years ago

+1

mianaliasjad commented 5 years ago

+1