第二次从存储中选择图像时出现 NullPointerException,第一次选择时没有 NullPointerException

NullPointerException while selecting image from the storage for the Second time onwards, No NullPointerException while selecting First time

我设置了一个按钮,用于检查READ_EXTERNAL_STORAGE 权限,然后打开用户phone 存储显示图像。我已通过以下代码成功完成此操作:

所有这一切在第一次尝试时就完美无缺。用户看到权限对话框,按下同意,图像选择器打开,在他们的 phone 上显示图像!但是,我们第二次尝试使用相同的按钮时,应用程序崩溃了。所以基本上在授予权限后,每次按下按钮时应用程序都会崩溃。

显示以下错误:

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.memory.pod.debug, PID: 26684
    java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.pm.PackageManager android.content.Context.getPackageManager()' on a null object reference
        at android.content.ContextWrapper.getPackageManager(ContextWrapper.java:98)
        at com.memory.pod.camerax.ui.home.HomeActivity.selectImage(HomeActivity.java:144)
        at com.memory.pod.camerax.ui.home.HomeActivity.openFileChooser(HomeActivity.java:137)
        at com.memory.pod.view.BottomTabView.onClick(BottomTabView.java:84)
        at android.view.View.performClick(View.java:7259)
        at android.view.View.performClickInternal(View.java:7236)
        at android.view.View.access00(View.java:801)
        at android.view.View$PerformClick.run(View.java:27892)
        at android.os.Handler.handleCallback(Handler.java:883)
        at android.os.Handler.dispatchMessage(Handler.java:100)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:7356)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)

BottomTabView.java


    public class BottomTabView extends FrameLayout implements ViewPager.OnPageChangeListener {

      // Initialize content
      private ImageView mCenterImageView;
      private ImageView mBottomImageView;
      private LinearLayout mStartImageView;
      private LinearLayout mEndImageView;
      private View mIndicator;

      private ArgbEvaluator mArgbEvaluator;

      private int mCenterColor;
      private int mSideColor;

      private int mEndViewsTranslationX;
      private int mIndicatorTranslationX;
      private int mCenterTranslationY;

      public BottomTabView(@NonNull Context context) {
        this(context, null);
      }

      public BottomTabView(@NonNull Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
      }

      public BottomTabView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        init();
      }

      public void setUpWithViewPager(ViewPager viewPager) {
        viewPager.addOnPageChangeListener(this);

        mStartImageView.setOnClickListener(new OnClickListener() {
          @Override
          public void onClick(View view) {
            if (viewPager.getCurrentItem() != 0)
              viewPager.setCurrentItem(0);
          }
        });

        mCenterImageView.setOnClickListener(new OnClickListener() {
          @Override
          public void onClick(View view) {
            if (viewPager.getCurrentItem() != 1)
              viewPager.setCurrentItem(1);
          }
        });

        mEndImageView.setOnClickListener(new OnClickListener() {
          @Override
          public void onClick(View view) {
            if (viewPager.getCurrentItem() != 2)
              viewPager.setCurrentItem(2);
          }
        });
        mBottomImageView.setOnClickListener(new OnClickListener() {
          @Override
          public void onClick(View view) {
            if (viewPager.getCurrentItem() == 1) {
              HomeActivity.openFileChooser(getContext());
            }
          }
        });
      }

      private void init() {
        LayoutInflater.from(getContext()).inflate(R.layout.view_bottom_tabs, this, true);

        // Initialize bottom tab view content
        mCenterImageView = findViewById(R.id.view_bottom_tabs_camera_iv);
        mStartImageView = findViewById(R.id.view_bottom_tabs_start_linear_layout);
        mEndImageView = findViewById(R.id.view_bottom_tabs_end_linear_layout);
        mBottomImageView = findViewById(R.id.view_bottom_tabs_gallery_iv);

        // Initialize bottom tab view indicator, meant to indicate the current tab in view
        mIndicator = findViewById(R.id.view_bottom_tabs_indicator);

        // Set start color and end color for tab view icons
        mCenterColor = ContextCompat.getColor(getContext(), R.color.white);
        mSideColor = ContextCompat.getColor(getContext(), R.color.black);

        // Evaluate the difference between colors
        mArgbEvaluator = new ArgbEvaluator();

        // Change the padding of tab icons based on view
        // This is the min padding accepted (0)
        mIndicatorTranslationX = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 140, getResources().getDisplayMetrics());

        // Wait till GalleryImageView has been drawn, once GalleryImageView is drawn then proceed with relative padding calculation
        mBottomImageView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
          @Override
          public void onGlobalLayout() {

            // Change padding relative to other icons
            mEndViewsTranslationX = (int)((mBottomImageView.getX() - mStartImageView.getX()) - mIndicatorTranslationX);
            mBottomImageView.getViewTreeObserver().removeOnGlobalLayoutListener(this);

            // Change the position of the center image
            mCenterTranslationY = getHeight() - mBottomImageView.getBottom();
          }
        });
      }

      @Override
      public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
        if (position == 0) {

          // Change color of icons based on view
          setColor(1 - positionOffset);

          // Move the start and end images
          moveViews(1 - positionOffset);

          // Change indicator position
          mIndicator.setTranslationX((positionOffset - 1) * mIndicatorTranslationX);

          // Change scale of center image
          moveAndScaleCenter(1 - positionOffset);
        } else if (position == 1) {

          // Change color of icons based on view
          setColor(positionOffset);

          // Move the start and end images
          moveViews(positionOffset);

          // Change indicator position
          mIndicator.setTranslationX(positionOffset * mIndicatorTranslationX);

          // Change scale of center image
          moveAndScaleCenter(positionOffset);
        }
      }

      @Override
      public void onPageSelected(int position) {

      }

      @Override
      public void onPageScrollStateChanged(int state) {

      }

      private void moveAndScaleCenter(float fractionFromCenter) {
        float scale = .7 f + ((1 - fractionFromCenter) * .3 f);

        // Change scale of center image
        mCenterImageView.setScaleX(scale);
        mCenterImageView.setScaleY(scale);

        int translation = (int)(fractionFromCenter * mCenterTranslationY * 2);

        // Move center image down
        mCenterImageView.setTranslationY(translation);
        mBottomImageView.setTranslationY(translation);

        // Fadeout bottom image
        mBottomImageView.setAlpha(1 - fractionFromCenter);
      }

      private void moveViews(float fractionFromCenter) {
        mStartImageView.setTranslationX(fractionFromCenter * mEndViewsTranslationX);
        mEndImageView.setTranslationX(-fractionFromCenter * mEndViewsTranslationX);

        mIndicator.setAlpha(fractionFromCenter);
        mIndicator.setScaleX(fractionFromCenter);
      }

      private void setColor(float fractionFromCenter) {
        int color = (int) mArgbEvaluator.evaluate(fractionFromCenter, mCenterColor, mSideColor);

        /* mCenterImageView.setColorFilter(color);
        mStartImageView.setColorFilter(color);
        mEndImageView.setColorFilter(color);
        mBottomImageView.setColorFilter(color); */
      }

    }

我做了一个log.d来确定哪里失败了,请参考之前的代码看看log.d。

我该如何解决这个问题?

编辑:

主页活动:


    public class HomeActivity extends AppCompatActivity {

      // Initialize image picker
      private static final int PICK_IMAGE_REQUEST = 1;
      private static final int REQUEST_CODE_STORAGE_PERMISSION = 1;
      private static final int REQUEST_CODE_SELECT_IMAGE = 2;

      // TODO: FIREBASE TEMPORARY LOGOUT
      private static FirebaseAuth mAuth;

      private static final String TAG = "HomeActivity";

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

        // Initialize views
        View background = findViewById(R.id.background_view);
        ViewPager viewPager = (ViewPager) findViewById(R.id.view_pager);

        // Initialize adapter
        HomePagerAdapter adapter = new HomePagerAdapter(getSupportFragmentManager());
        viewPager.setAdapter(adapter);

        // Initialize BottomTabView
        BottomTabView bottomTabView = findViewById(R.id.bottom_tabs);
        bottomTabView.setUpWithViewPager(viewPager);

        // Initialize TopSearchView
        TopSearchView topSearchView = findViewById(R.id.top_search);
        topSearchView.setUpWithViewPager(viewPager);

        // Initialize TopProfilePictureView
        TopProfilePictureView topProfilePictureView = findViewById(R.id.top_profile_picture);
        topProfilePictureView.setUpWithViewPager(viewPager);

        // Initialize TopVariableFunctionalityButtonView
        TopVariableFunctionalityButtonView topVariableFunctionalityButtonView = findViewById(R.id.top_variable_functionality_button);
        topVariableFunctionalityButtonView.setUpWithViewPager(viewPager);

        // Initialize color for fade effect
        final int windowBackgroundColor = ContextCompat.getColor(this, R.color.windowBackground);
        final int blackBackgroundColor = ContextCompat.getColor(this, R.color.black);

        // Set the default position of the viewPager
        viewPager.setCurrentItem(1);

        // TODO: Initialize Firebase (TEMPORARY)
        //Initialize Firebase Auth
        mAuth = FirebaseAuth.getInstance();


        bottomTabView.setOnBottomTabViewClickListener(new BottomTabViewClickListener() {
          @Override
          public void onClick(View v) {
            // call your openFileChooser from here,
            //REMOVE THE STATIC
            openFileChooser(HomeActivity.this);
          }
        });

        // Callback each time the fragment is changed
        viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {

          @Override
          public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            if (position == 0) {
              background.setBackgroundColor(windowBackgroundColor);
              background.setAlpha(1 - positionOffset);

            } else if (position == 1) {
              background.setBackgroundColor(blackBackgroundColor);
              background.setAlpha(positionOffset);

            }
          }

          @Override
          public void onPageSelected(int position) {

          }

          @Override
          public void onPageScrollStateChanged(int state) {

          }
        });
      }

      // Choose file extended from BottomTabView, opens all images on device
      // Check for permissions before hand
      public void openFileChooser(Context context) {
        Log.d("HomeActivity", "This is the last place a log is observed");
        if (ContextCompat.checkSelfPermission(getInstance().getApplicationContext(), Manifest.permission.READ_EXTERNAL_STORAGE) !=
          PackageManager.PERMISSION_GRANTED) {

          ActivityCompat.requestPermissions(
            ((Activity) context),
            new String[] {
              Manifest.permission.READ_EXTERNAL_STORAGE
            },
            REQUEST_CODE_STORAGE_PERMISSION
          );
        } else {
          selectImage();
        }
      }

      // Open image selector via phone storage
      private void selectImage() {
        Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
        if (intent.resolveActivity(getPackageManager()) != null) {
          startActivityForResult(intent, REQUEST_CODE_SELECT_IMAGE);
        }
      }

      // Request permission results
      @Override
      public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);

        if (requestCode == REQUEST_CODE_STORAGE_PERMISSION && grantResults.length > 0) {
          if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            selectImage();
          } else {
            Toast.makeText(this, "Permission Denied!", Toast.LENGTH_SHORT).show();
          }
        }
      }

      // TODO: Is it better to use bitmap or URI
      // Check if user has selected file and describe next step
      @Override
      protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (requestCode == REQUEST_CODE_SELECT_IMAGE && resultCode == RESULT_OK) {
          if (data != null) {

            // Get image URI
            Uri selectedImageUri = data.getData();

            if (selectedImageUri != null) {
              try {

                InputStream inputStream = getContentResolver().openInputStream(selectedImageUri);
                Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
                // Do something with image

                // Identify the selected image file, pass onto firebase
                File selectedImageFile = new File(getPathFormUri(selectedImageUri));

              } catch (Exception exception) {
                Toast.makeText(this, exception.getMessage(), Toast.LENGTH_SHORT).show();
              }
            }
          }
        }
      }

      private String getPathFormUri(Uri contentUri) {
        String filePath;
        Cursor cursor = getContentResolver()
          .query(contentUri, null, null, null, null);
        if (cursor == null) {
          filePath = contentUri.getPath();
        } else {
          cursor.moveToFirst();
          int index = cursor.getColumnIndex("_data");
          filePath = cursor.getString(index);
          cursor.close();
        }
        return filePath;
      }

      // TODO: TEMPORARY LOGOUT
      public static void logoutUser(Context context) {
        mAuth.signOut();
      }
    }



BottomTabActivity:

    public class BottomTabView extends FrameLayout implements ViewPager.OnPageChangeListener {

      // Initialize content
      BottomTabViewClickListener bottomTabViewClickListener;
      private ImageView mCenterImageView;
      private ImageView mBottomImageView;
      private LinearLayout mStartImageView;
      private LinearLayout mEndImageView;
      private View mIndicator;

      private ArgbEvaluator mArgbEvaluator;

      private int mCenterColor;
      private int mSideColor;

      private int mEndViewsTranslationX;
      private int mIndicatorTranslationX;
      private int mCenterTranslationY;

      //add this function somewhere
      public void setOnBottomTabViewClickListener(BottomTabViewClickListener bottomTabViewClickListener) {
        this.bottomTabViewClickListener = bottomTabViewClickListener;
      }

      public BottomTabView(@NonNull Context context) {
        this(context, null);
      }

      public BottomTabView(@NonNull Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
      }

      public BottomTabView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        init();
      }

      public void setUpWithViewPager(ViewPager viewPager) {
        viewPager.addOnPageChangeListener(this);

        mStartImageView.setOnClickListener(new OnClickListener() {
          @Override
          public void onClick(View view) {
            if (viewPager.getCurrentItem() != 0)
              viewPager.setCurrentItem(0);
          }
        });

        mCenterImageView.setOnClickListener(new OnClickListener() {
          @Override
          public void onClick(View view) {
            if (viewPager.getCurrentItem() != 1)
              viewPager.setCurrentItem(1);
          }
        });

        mEndImageView.setOnClickListener(new OnClickListener() {
          @Override
          public void onClick(View view) {
            if (viewPager.getCurrentItem() != 2)
              viewPager.setCurrentItem(2);
          }
        });
        mBottomImageView.setOnClickListener(new OnClickListener() {
          @Override
          public void onClick(View view) {
            if (viewPager.getCurrentItem() == 1) {

            }
          }
        });
      }

      private void init() {
        LayoutInflater.from(getContext()).inflate(R.layout.view_bottom_tabs, this, true);

        // Initialize bottom tab view content
        mCenterImageView = findViewById(R.id.view_bottom_tabs_camera_iv);
        mStartImageView = findViewById(R.id.view_bottom_tabs_start_linear_layout);
        mEndImageView = findViewById(R.id.view_bottom_tabs_end_linear_layout);
        mBottomImageView = findViewById(R.id.view_bottom_tabs_gallery_iv);

        // Initialize bottom tab view indicator, meant to indicate the current tab in view
        mIndicator = findViewById(R.id.view_bottom_tabs_indicator);

        // Set start color and end color for tab view icons
        mCenterColor = ContextCompat.getColor(getContext(), R.color.white);
        mSideColor = ContextCompat.getColor(getContext(), R.color.black);

        // Evaluate the difference between colors
        mArgbEvaluator = new ArgbEvaluator();

        // Change the padding of tab icons based on view
        // This is the min padding accepted (0)
        mIndicatorTranslationX = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 140, getResources().getDisplayMetrics());

        // Wait till GalleryImageView has been drawn, once GalleryImageView is drawn then proceed with relative padding calculation
        mBottomImageView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
          @Override
          public void onGlobalLayout() {

            // Change padding relative to other icons
            mEndViewsTranslationX = (int)((mBottomImageView.getX() - mStartImageView.getX()) - mIndicatorTranslationX);
            mBottomImageView.getViewTreeObserver().removeOnGlobalLayoutListener(this);

            // Change the position of the center image
            mCenterTranslationY = getHeight() - mBottomImageView.getBottom();
          }
        });
      }

      @Override
      public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
        if (position == 0) {

          // Change color of icons based on view
          setColor(1 - positionOffset);

          // Move the start and end images
          moveViews(1 - positionOffset);

          // Change indicator position
          mIndicator.setTranslationX((positionOffset - 1) * mIndicatorTranslationX);

          // Change scale of center image
          moveAndScaleCenter(1 - positionOffset);
        } else if (position == 1) {

          // Change color of icons based on view
          setColor(positionOffset);

          // Move the start and end images
          moveViews(positionOffset);

          // Change indicator position
          mIndicator.setTranslationX(positionOffset * mIndicatorTranslationX);

          // Change scale of center image
          moveAndScaleCenter(positionOffset);
        }
      }

      @Override
      public void onPageSelected(int position) {

      }

      @Override
      public void onPageScrollStateChanged(int state) {

      }

      private void moveAndScaleCenter(float fractionFromCenter) {
        float scale = .7 f + ((1 - fractionFromCenter) * .3 f);

        // Change scale of center image
        mCenterImageView.setScaleX(scale);
        mCenterImageView.setScaleY(scale);

        int translation = (int)(fractionFromCenter * mCenterTranslationY * 2);

        // Move center image down
        mCenterImageView.setTranslationY(translation);
        mBottomImageView.setTranslationY(translation);

        // Fadeout bottom image
        mBottomImageView.setAlpha(1 - fractionFromCenter);
      }

      private void moveViews(float fractionFromCenter) {
        mStartImageView.setTranslationX(fractionFromCenter * mEndViewsTranslationX);
        mEndImageView.setTranslationX(-fractionFromCenter * mEndViewsTranslationX);

        mIndicator.setAlpha(fractionFromCenter);
        mIndicator.setScaleX(fractionFromCenter);
      }

      private void setColor(float fractionFromCenter) {
        int color = (int) mArgbEvaluator.evaluate(fractionFromCenter, mCenterColor, mSideColor);

        /* mCenterImageView.setColorFilter(color);
        mStartImageView.setColorFilter(color);
        mEndImageView.setColorFilter(color);
        mBottomImageView.setColorFilter(color); */
      }
    }

    interface BottomTabViewClickListener {
      public void onClick();
    }

你的 else 语句目前是这样的,这意味着你正在尝试创建一个新的 HomeActivity 实例并调用 selectimage(),但它不能那样工作。

else {
        new HomeActivity().selectImage();
    }

请将其更改为

else{
       selectImage();
    }

请试试这个,这应该可以解决您的问题。

编辑:接口和侦听器模式的使用

在您的 BottomTabView 中添加以下内容

public class BottomTabView extends FrameLayout implements ViewPager.OnPageChangeListener {

   // Initialize content 
   // add this at top level.
   BottomTabViewClickListener bottomTabViewClickListener;

   //add this function somewhere
   public void setOnBottomTabViewClickListener(BottomTabViewClickListener bottomTabViewClickListener){
        this.bottomTabViewClickListener = bottomTabViewClickListener;
    }

    // replace HomeActivity.openFileChooser(getContext());
    mBottomImageView.setOnClickListener(new OnClickListener() {
      @Override
      public void onClick(View view) {
        if (viewPager.getCurrentItem() == 1) {
          bottomTabViewClickListener.onClick();
        }
      }
    });
}
//end of BottomTab View

//add this after your BottomTabView not inside
interface BottomTabViewClickListener{
    public void onClick();
}

在您的 HomeActivity 中添加以下内容

 // Initialize BottomTabView
        BottomTabView bottomTabView = findViewById(R.id.bottom_tabs);
        bottomTabView.setUpWithViewPager(viewPager);
        bottomTabView.setOnBottomTabViewClickListener(new BottomTabViewClickListener() {
            @Override
            public void onClick() {
                // call your openFileChooser from here, 
                //REMOVE THE STATIC
                 openFileChooser(HomeActivity.this)
            }
        });