简体   繁体   English

应用程式因java.lang.SecurityException而当机

[英]App crashes due to java.lang.SecurityException

I am working on the project of capturing photos or picking images from gallery and show it in the recycler view, the app is working good in Android-lollipop but crashes in marshmallow one as soon as camera button is clicked giving the exception 我正在研究从画廊中捕获照片或挑选图像并在回收器视图中显示的项目,该应用程序在Android棒棒糖中运行良好,但是一旦单击相机按钮,棉花糖就会崩溃,这是例外

 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()                                                                           

Here is the code: Manifest 这是代码: 清单

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.urjapawar.bevypart2">
<uses-permission tools:node="replace" android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission tools:node="replace" android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-feature
    android:name="android.hardware.camera"
    android:required="false"/>
<uses-permission
    android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:supportsRtl="true"
    android:theme="@style/AppTheme"
   >
    <activity
        android:name=".MainActivity"
        android:label="@string/app_name"
        android:theme="@style/AppTheme.NoActionBar">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity><!-- ATTENTION: This was auto-generated to add Google Play services to your project for
 App Indexing.  See https://g.co/AppIndexing/AndroidStudio for more information. -->
    <meta-data
        android:name="com.google.android.gms.version"
        android:value="@integer/google_play_services_version" />
</application>
</manifest>

Images.java 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 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> 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 < 19) {
                    selectedImage = data.getData();
                } else {
                    selectedImage = data.getData();
                }

                String[] filePathColumn = {MediaStore.Images.Media.DATA};
                Cursor cursor = getContentResolver()
                        .query(selectedImage, filePathColumn, null, null,
                                null);
                if (cursor != null && cursor.getCount() > 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 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<ImageAdapter.ImgViewHolder> {
List<Images> images;

ImageAdapter(List<Images> 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);
}

}

I have checked many answers but not able to fix it, kindly help! 我检查了很多答案,但无法解决,请帮忙! Also while selecting images from gallery blank card shows up in marshmallow (no image content), it says Make sure the Cursor is initialized correctly before accessing data from it. 同样,从图库空白卡中选择图像时,显示为棉花糖(无图像内容),它表示在访问游标之前确保已正确初始化游标。 while it works fine in lollipop one. 虽然在棒棒糖之一中效果很好。 Any suggestions will be deeply appreciated. 任何建议将不胜感激。

You need to give android.hardware.Camera permission programmatically. 您需要以编程方式授予android.hardware.Camera权限。

manifeast permission not work on Android Marshmallow 清单权限在Android棉花糖上不起作用

In marshmallow,We require runtime permissions for Storage,Contacts,Camera, etc. In edition to give these permissions in manifest for older version, We need to request them from users at Runtime for marshmallow. 在棉花糖中,我们需要存储,联系人,相机等的运行时权限。在版本中,要在清单中为这些旧版本提供这些权限,我们需要在运行时向用户请求使用棉花糖。 For more details refer this : Marshmallow permissions 有关更多详细信息,请参见: 棉花糖权限

You must put Camera permission in code since android 6 + version checks for runtime permission. 由于android 6 +版本会检查运行时权限,因此您必须在代码中添加Camera权限。

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;
    }
}

you will need this permission too. 您也将需要此权限。

<uses-permission android:name="android.permission.CAMERA"/>

and for writing data to storage you will need runtime permission 为了将数据写入存储,您将需要运行时权限
make request 提出要求

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

and check if user granted or decline to the permission request. 并检查用户是否授予或拒绝该权限请求。

     @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;
        }
    }
}

您需要添加

<uses-permission android:name="android.permission.CAMERA" />

只是想一想,您是否允许您的应用在清单中访问您的手机或SD卡?

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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