应用程序因java.lang.SecurityException而崩溃

我正在制作捕捉照片或从画廊中挑选图像并在回收者视图中显示的项目,该应用程序在Android-lollipop中运行良好,但是在点击相机按钮时会在棉花糖中崩溃,给出exception

Caused by: java.lang.SecurityException: Permission Denial: writing com.android.providers.media.MediaProvider uri content://media/external/images/media from pid=1983, uid=10060 requires android.permission.WRITE_EXTERNAL_STORAGE, or grantUriPermission() 

这是代码: Manifest

                 

Images.java

 public class Images { String path; public void setPath(String path) { this.path = path; } public String getPath() { return path; } /** * Gets path. * * @return Value of path. */ @Override public String toString() { return "\nPath:" + path; } } 

MainActivity.java

 import android.content.ContentValues; import android.content.Intent; import android.database.Cursor; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.provider.MediaStore; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.Toolbar; import android.view.View; import com.google.android.gms.appindexing.AppIndex; import com.google.android.gms.common.api.GoogleApiClient; import java.util.ArrayList; public class MainActivity extends AppCompatActivity { private ArrayList images; private ImageAdapter imageAdapter; private RecyclerView rv; private LinearLayoutManager llm; private Uri mCapturedImageURI; private static final int RESULT_LOAD_IMAGE = 1; private static final int REQUEST_IMAGE_CAPTURE = 2; /** * ATTENTION: This was auto-generated to implement the App Indexing API. * See https://g.co/AppIndexing/AndroidStudio for more information. */ private GoogleApiClient client; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); images = new ArrayList(); imageAdapter = new ImageAdapter(images); rv = (RecyclerView) findViewById(R.id.rv); llm = new LinearLayoutManager(this); rv.setLayoutManager(llm); imageAdapter = new ImageAdapter(images); rv.setAdapter(imageAdapter); // ATTENTION: This was auto-generated to implement the App Indexing API. // See https://g.co/AppIndexing/AndroidStudio for more information. client = new GoogleApiClient.Builder(this).addApi(AppIndex.API).build(); } public void activeCamera(View view) { Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); if (takePictureIntent.resolveActivity(getPackageManager()) != null) { String fileName = "temp.jpg"; ContentValues values = new ContentValues(); values.put(MediaStore.Images.Media.TITLE, fileName); mCapturedImageURI = getContentResolver() .insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); takePictureIntent .putExtra(MediaStore.EXTRA_OUTPUT, mCapturedImageURI); startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE); } } public void activeGallery(View view) { Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI); startActivityForResult(intent, RESULT_LOAD_IMAGE); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); switch (requestCode) { case RESULT_LOAD_IMAGE: Uri selectedImage = null; if (requestCode == RESULT_LOAD_IMAGE && resultCode == RESULT_OK && null != data) { if (Build.VERSION.SDK_INT  0) { cursor.moveToFirst(); } // cursor.moveToFirst(); int columnIndex = cursor.getColumnIndex(filePathColumn[0]); String picturePath = cursor.getString(columnIndex); cursor.close(); Images image = new Images(); image.setPath(picturePath); images.add(image); } case REQUEST_IMAGE_CAPTURE: if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) { String[] projection = {MediaStore.Images.Media.DATA}; Cursor cursor = getContentResolver().query(mCapturedImageURI, projection, null, null, null); int column_index_data = cursor.getColumnIndexOrThrow( MediaStore.Images.Media.DATA); cursor.moveToFirst(); String picturePath = cursor.getString(column_index_data); Images image = new Images(); image.setPath(picturePath); images.add(image); cursor.close(); } } } } 

ImageAdapter.java

 import android.graphics.BitmapFactory; import android.media.ThumbnailUtils; import android.net.Uri; import android.support.v7.widget.*; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import java.util.List; public class ImageAdapter extends android.support.v7.widget.RecyclerView.Adapter { List images; ImageAdapter(List img){ this.images = img; } public class ImgViewHolder extends android.support.v7.widget.RecyclerView.ViewHolder { ImageView personPhoto; CardView cv; public ImgViewHolder(View itemView) { super(itemView); cv = (CardView)itemView.findViewById(R.id.card_view); personPhoto=(ImageView)itemView.findViewById(R.id.thumbnail); } } @Override public ImgViewHolder onCreateViewHolder(final ViewGroup viewGroup, int i) { View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.single_card, viewGroup, false); ImgViewHolder pvh = new ImgViewHolder(v); return pvh; } @Override public int getItemCount() { return images.size(); } @Override public void onBindViewHolder(ImgViewHolder holder, int i) { Images image = images.get(i); final int THUMBSIZE = 96; // viewHolder.imgIcon.setImageURI(Uri.fromFile(new File(image // .getPath()))); holder.personPhoto.setImageBitmap(ThumbnailUtils .extractThumbnail(BitmapFactory.decodeFile(image.getPath()), THUMBSIZE, THUMBSIZE)); // holder.personPhoto.setImageURI(Uri.parse("file://" + images.getPath() + "/" + mDataset[position])); } @Override public void onAttachedToRecyclerView(RecyclerView recyclerView) { super.onAttachedToRecyclerView(recyclerView); } } 

我已经检查了很多答案,但无法解决它,请帮忙! 此外,当从画廊空白卡中选择图像显示在棉花糖中时(没有图像内容),它表示确保在从中访问数据之前正确初始化了光标。 虽然它在棒棒糖中工作正常。 任何建议都将深表感谢。

您必须在代码中添加Camera权限,因为android 6 + version会检查运行时权限。

 public void getCameraPermission(){ if (!checkPermission()) { requestPermission(); } } private boolean checkPermission(){ int result = ContextCompat.checkSelfPermission(context, Manifest.permission.CAMERA); if (result == PackageManager.PERMISSION_GRANTED){ return true; } else { return false; } } private void requestPermission(){ if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this, Manifest.permission.CAMERA)){ ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.CAMERA}, PERMISSION_REQUEST_CODE); } else { ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.CAMERA}, PERMISSION_REQUEST_CODE); } } @Override public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { switch (requestCode) { case PERMISSION_REQUEST_CODE: if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { Toast.makeText(MainActivity.this,"Permission granted",Toast.LENGTH_SHORT).show(); //store permission in shared pref } else { Toast.makeText(MainActivity.this,"Permission denied",Toast.LENGTH_SHORT).show(); //store permission in shared pref } break; } } 

您需要以编程方式授予android.hardware.Camera权限。

表示权限不适用于Android Marshmallow

在棉花糖中,我们需要存储,联系人,相机等的运行时权限。在版本中为旧版本的清单中提供这些权限,我们需要在运行时向用户请求marshmallow。 有关详细信息,请参阅: Marshmallow权限

你也需要这个权限。

  

并且要将数据写入存储,您将需要运行时权限
提出要求

  ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_WRITE_STORAGE); 

并检查用户是否授予或拒绝权限请求。

  @Override public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { switch (requestCode) { case REQUEST_WRITE_STORAGE: { if (grantResults.length == 0 || grantResults[0] != PackageManager.PERMISSION_GRANTED) { Log.i(TAG, "Permission has been denied by user"); } else { Log.i(TAG, "Permission has been granted by user"); } return; } } } 

你需要添加

  

只是想一想,您是否允许您的应用程序访问Manifest中的手机或SD卡?