【问题标题】:Camera is not working in Nougat 7.0相机在 Nougat 7.0 中不工作
【发布时间】:2017-01-31 13:09:04
【问题描述】:

我的相机代码适用于所有 Android 版本,但在 Nougat 7.0 中会出现以下错误:

java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.net.Uri.toString()' on a null object reference

它在除 android 7.0 之外的所有其他版本的 android 上都能完美运行。我已授予相机和图库的运行时许可,但相机仍然无法工作。以下是相关代码:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {

    if (resultCode == RESULT_OK) {
        if(requestCode == Constants.CROPPED_PIC_REQUEST_CODE){
            CropImage.ActivityResult result = (CropImage.ActivityResult) data.getExtras().get(CropImage.CROP_IMAGE_EXTRA_RESULT);
            Uri selectedImageUri = result == null ? null : result.getUri();
            Bitmap bitmap = null;
            Log.d("SetUpProfile","Uri cropped is "+outputFileUri);
            bitmap = getBitmap(selectedImageUri);
    //                    bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), selectedImageUri);
            circleImageView.setImageBitmap(bitmap);
            finalBitmap = bitmap;
        }
        else if (requestCode == Constants.YOUR_SELECT_PICTURE_REQUEST_CODE) {
            final boolean isCamera;
            if (data == null) {
                isCamera = true;
            } else {
                final String action = data.getAction();
                if (action == null) {
                    isCamera = false;
                } else {
                    isCamera = action.equals(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
                }
            }

            Uri selectedImageUri;
            if (isCamera) {
                SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
                String value = prefs.getString("path", "error");
                selectedImageUri = Uri.parse(value);
            } else {
                selectedImageUri = data == null ? null : data.getData();
            }

            Intent i = new Intent(Five.this,CropImageActivity.class);
            i.putExtra("ImageURI", selectedImageUri.toString());
            startActivityForResult(i,Constants.CROPPED_PIC_REQUEST_CODE);

        }
    }
}

这是我的日志:-

FATAL EXCEPTION: main
Process: com.sancsvision.wayndr, PID: 31570
java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=11, result=-1, data=Intent {  }} to activity {com.sancsvision.wayndr/com.sancsvision.wayndr.Five}: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.net.Uri.toString()' on a null object reference                     
    at android.app.ActivityThread.deliverResults(ActivityThread.java:4053)              
    at android.app.ActivityThread.handleSendResult(ActivityThread.java:4096)        
    at android.app.ActivityThread.-wrap20(ActivityThread.java)                      
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1516)         
    at android.os.Handler.dispatchMessage(Handler.java:102)                     
    at android.os.Looper.loop(Looper.java:154)                      
    at android.app.ActivityThread.main(ActivityThread.java:6077)                        
    at java.lang.reflect.Method.invoke(Native Method)                       
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)      
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)                                                     
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.net.Uri.toString()' on a null object reference
    at com.sancsvision.wayndr.Five.onActivityResult(Five.java:259)
    at android.app.Activity.dispatchActivityResult(Activity.java:6917)
    at android.app.ActivityThread.deliverResults(ActivityThread.java:4049)
    at android.app.ActivityThread.handleSendResult(ActivityThread.java:4096) 
    at android.app.ActivityThread.-wrap20(ActivityThread.java) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1516) 
    at android.os.Handler.dispatchMessage(Handler.java:102) 
    at android.os.Looper.loop(Looper.java:154) 
    at android.app.ActivityThread.main(ActivityThread.java:6077) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)

【问题讨论】:

  • 请提供minimal reproducible example 证明您的问题。这将包括完整的 Java 堆栈跟踪,以及堆栈跟踪中引用的所有 Java 代码。我的猜测是您正在使用ACTION_IMAGE_CAPTURE 并试图从返回的Intent 中获取Uri,这不是ACTION_IMAGE_CAPTURE 的工作方式。
  • @CommonsWare 检查已编辑的问题。
  • 请提供minimal reproducible example 证明您的问题。这将包括完整的 Java 堆栈跟踪,以及堆栈跟踪中引用的所有 Java 代码。
  • 检查此链接可能会有所帮助github.com/nguyenhoanglam/ImagePicker/issues/9
  • @CommonsWare 检查已编辑的问题。

标签: android camera android-7.0-nougat


【解决方案1】:

尝试一下,一旦您拍照并保存到 SD 卡并取回 URI 在 Nougat 中不同,这不是造成问题的意图......

在您的应用程序上实现 FileProvider 非常容易。首先,您需要在 AndroidManifest.xml 中添加一个 FileProvider 标签,如下所示:AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    ...
    <application
        ...
        <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="${applicationId}.provider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/provider_paths"/>
        </provider>
    </application>
</manifest>

然后在res文件夹下的xml文件夹中创建provider_paths.xml文件。如果文件夹不存在,可能需要创建它。

res/xml/provider_paths.xml

 <?xml version="1.0" encoding="utf-8"?>
    <paths xmlns:android="http://schemas.android.com/apk/res/android">
        <external-path name="external_files" path="."/>
    </paths>

完成! FileProvider 现在已声明并可以使用了。

最后一步是在 MainActivity.java 中更改下面的代码行

 Uri photoURI = Uri.fromFile(createImageFile());

Uri photoURI = FileProvider.getUriForFile(MainActivity.this,
        BuildConfig.APPLICATION_ID + ".provider",
        createImageFile());

然后....完成了!您的应用程序现在应该可以在包括 Android Nougat 在内的任何 Android 版本上完美运行。干杯!

【讨论】:

    【解决方案2】:

    这可能与 Nougat 中的更改有关,该更改不允许将“file://”方案附加到意图。

    查看这篇博文了解更多详情

    https://inthecheesefactory.com/blog/how-to-share-access-to-file-with-fileprovider-on-android-nougat/en

    【讨论】:

    • 如果@Themasterhimself 提供的不仅仅是一个链接,这应该是公认的答案。我的意思是,如果你提供一个完整的例子或者给出与之相关的sn-p
    【解决方案3】:

    我已经使用摄像头将图像上传到服务器,用于 android api >21

    import android.Manifest;
    import android.app.Activity;
    import android.app.ProgressDialog;
    import android.content.Intent;
    import android.content.pm.PackageManager;
    import android.database.Cursor;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.net.Uri;
    import android.os.Build;
    import android.os.Environment;
    import android.provider.MediaStore;
    import android.support.v4.app.ActivityCompat;
    import android.support.v4.content.ContextCompat;
    import android.support.v4.content.FileProvider;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.View;
    import android.widget.Button;
    import android.widget.ImageView;
    import android.widget.RelativeLayout;
    import android.widget.TextView;
    import android.widget.Toast;
    
    import java.io.ByteArrayOutputStream;
    import java.io.DataOutputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.IOException;
    import java.net.HttpURLConnection;
    import java.net.MalformedURLException;
    import java.net.URL;
    import java.text.SimpleDateFormat;
    import java.util.ArrayList;
    import java.util.Date;
    import java.util.Random;
    
    
    public class MainActivity extends AppCompatActivity implements         View.OnClickListener {
    
    private static final int PICK_FILE_REQUEST = 1;
    private static final String TAG = MainActivity.class.getSimpleName();
    private ArrayList<String> selectedFilePath;
    private String SERVER_URL =     "http://192.168.1.10:8080/imageUploadWebApi.php";
    Button btAttachment;
    Button btCamera;
    Button bUpload;
    TextView tvFileName;
    ProgressDialog dialog;
    public static final int MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE = 123;
    Uri outputFileUri;
    String mCurrentPhotoPath;
    
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    
        int permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
    
        if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE);
        } else {
            Init();
        }
    
        if ( Build.VERSION.SDK_INT >= 23 && ContextCompat.checkSelfPermission( this, android.Manifest.permission.CAMERA ) != PackageManager.PERMISSION_GRANTED) {
            requestPermissions(new String[]{android.Manifest.permission.CAMERA},
                    MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE);
        }
    }
    
    @Override
    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
        switch (requestCode) {
            case MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE:
                if ((grantResults.length > 0) && (grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
                    Init();
                }
                break;
            default:
                break;
        }
    }
    
    private void Init() {
        btAttachment = (Button)findViewById(R.id.btAttachment);
        btCamera=(Button)findViewById(R.id.btCamera);
        bUpload = (Button) findViewById(R.id.b_upload);
        tvFileName = (TextView) findViewById(R.id.tv_file_name);
        btAttachment.setOnClickListener(this);
        btCamera.setOnClickListener(this);
        bUpload.setOnClickListener(this);
        selectedFilePath=new ArrayList<>();
    }
    
    @Override
    public void onClick(View v) {
    
        switch (v.getId())
        {
            case R.id.btAttachment:
                if(selectedFilePath.size()<5) {
                    //on attachment icon click
                    showFileChooser();
                }
                else
                    Toast.makeText(this,"You can upload only 5 Images at a time ",Toast.LENGTH_LONG).show();
    
                break;
    
            case R.id.btCamera:
                if(selectedFilePath.size()<5) {
                    try {
    
                        Intent cameraIntent= new Intent(
                                android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
    
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                            cameraIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                            outputFileUri = FileProvider.getUriForFile(getApplicationContext(), BuildConfig.APPLICATION_ID + ".provider", createImageFile());
                            cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
                        } else {
                            File imagesFolder = new File(Environment.getExternalStorageDirectory(), "Images");
                            imagesFolder.mkdirs()
                            String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
                            String imageFileName = "Img_" + timeStamp;
                            String fname =  imageFileName + ".png";
                            File file = new File(imagesFolder, fname);
                            outputFileUri = Uri.fromFile(file);
                            cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
                        }
    
                        startActivityForResult(cameraIntent, 100);
                    }catch(Exception e) {
                        e.printStackTrace();
                    }
                }
                else
                    Toast.makeText(this,"You can upload only 5 Images at a time ",Toast.LENGTH_LONG).show();
                break;
    
            case R.id.b_upload:
                selectedFile();
                break;
    
        }
            }
    
    private File createImageFile() throws IOException {
        // Create an image file name
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
        String imageFileName = "Img_" + timeStamp;
        File storageDir = new File(Environment.getExternalStorageDirectory(), "Images");
        File file=new File(storageDir,imageFileName+".png");
        // Save a file: path for use with ACTION_VIEW intents
        mCurrentPhotoPath = file.getAbsolutePath();//"file:" + image.getAbsolutePath();
        return file;
    }
    
    private void selectedFile()
    {
        if(selectedFilePath.size() != 0){
            dialog = ProgressDialog.show(MainActivity.this,"","Uploading File...",true);
    
            for (final String selectedFile:selectedFilePath) {
    
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        //creating new thread to handle Http Operations
                        uploadFile(selectedFile);
                    }
                }).start();
            }
        }else{
            Toast.makeText(MainActivity.this,"Please choose a File First", Toast.LENGTH_SHORT).show();
        }
    }
    
    private void showFileChooser() {
        Intent intent = new Intent();
        //sets the select file to all types of files
        intent.setType("*/*");
        //allows to select data and return it
        intent.setAction(Intent.ACTION_GET_CONTENT);
        //starts new activity to select file and return data
        startActivityForResult(Intent.createChooser(intent,"Choose File to Upload.."),PICK_FILE_REQUEST);
    }
    
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if(resultCode == Activity.RESULT_OK){
            if(requestCode == PICK_FILE_REQUEST){
                if(data == null){
                    //no data present
                    return;
                }
    
                Uri selectedFileUri =data.getData();
                selectedFilePath.add(FilePath.getPath(this,selectedFileUri));
                Log.i(TAG,"Selected File Path:" + selectedFilePath);
    
                if(selectedFilePath.size() != 0 ){
                    String fileName="";
                    for(int i=0;i<selectedFilePath.size();i++)
                    {
                        String[] parts = selectedFilePath.get(i).split("/");
                        final String RelativefileName = parts[parts.length-1];
                        fileName=RelativefileName+"\n"+fileName;
                    }
                    tvFileName.setText(fileName);
    
                }else{
                    Toast.makeText(this,"Cannot upload file to server",Toast.LENGTH_SHORT).show();
                }
            }
            else if(requestCode == 100)
            {
                try {
    
                    if(Build.VERSION.SDK_INT <= Build.VERSION_CODES.N) {
                        // Bitmap bitmap;
                        File file = null;
                        FileInputStream fis;
                        BitmapFactory.Options opts;
                        int resizeScale;
                        Bitmap bmp;
                        file = new File(outputFileUri.getPath());
                        // This bit determines only the width/height of the
                        // bitmap
                        // without loading the contents
                        opts = new BitmapFactory.Options();
                        opts.inJustDecodeBounds = true;
                        fis = new FileInputStream(file);
                        BitmapFactory.decodeStream(fis, null, opts);
                        fis.close();
    
    
                        selectedFilePath.add(FilePath.getPath(this,outputFileUri));
                    }
                    else
                    {
                        selectedFilePath.add(mCurrentPhotoPath);
                    }
    
                    Log.i(TAG,"Selected File Path:" + selectedFilePath);
    
                    if(selectedFilePath.size() != 0 ){
                        String fileName="";
                        for(int i=0;i<selectedFilePath.size();i++)
                        {
                            String[] parts = selectedFilePath.get(i).split("/");
                            final String RelativefileName = parts[parts.length-1];
                            fileName=RelativefileName+"\n"+fileName;
                        }
                        tvFileName.setText(fileName);
                    }else{
                        Toast.makeText(this,"Cannot upload file to server",Toast.LENGTH_SHORT).show();
                    }
    
                } catch (Exception e) {
    
                    e.printStackTrace();
                }
            }
        }
    }
    
    public String getPath(Uri uri) {
        String[] projection = { MediaStore.Images.Media.DATA };
        Cursor cursor = getContentResolver().query(uri, null, null, null, null);
        cursor.moveToFirst();
        return cursor.getString(0);
    }
    
    
    //android upload file to server
    public int uploadFile(final String selectedFilePath){
    
        int serverResponseCode = 0;
    
        HttpURLConnection connection;
        DataOutputStream dataOutputStream;
        String lineEnd = "\r\n";
        String twoHyphens = "--";
        String boundary = "*****";
    
        int bytesRead,bytesAvailable,bufferSize;
        byte[] buffer;
        int maxBufferSize = 1 * 1024 * 1024;
        File selectedFile = new File(selectedFilePath);
    
    
        String[] parts = selectedFilePath.split("/");
        final String fileName = parts[parts.length-1];
    
        if (!selectedFile.isFile()){
            dialog.dismiss();
    
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    tvFileName.setText("Source File Doesn't Exist: " + selectedFilePath);
                }
            });
            return 0;
        }else{
            try{
                FileInputStream fileInputStream = new FileInputStream(selectedFile);
                URL url = new URL(SERVER_URL);
                connection = (HttpURLConnection) url.openConnection();
                connection.setDoInput(true);//Allow Inputs
                connection.setDoOutput(true);//Allow Outputs
                connection.setUseCaches(false);//Don't use a cached Copy
                connection.setRequestMethod("POST");
                connection.setRequestProperty("Connection", "Keep-Alive");
                connection.setRequestProperty("ENCTYPE", "multipart/form-data");
                connection.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
                connection.setRequestProperty("uploaded_file",selectedFilePath);
    
                //creating new dataoutputstream
                dataOutputStream = new DataOutputStream(connection.getOutputStream());
    
                //writing bytes to data outputstream
                dataOutputStream.writeBytes(twoHyphens + boundary + lineEnd);
                dataOutputStream.writeBytes("Content-Disposition: form-data; name=\"uploaded_file\";filename=\""
                        + selectedFilePath + "\"" + lineEnd);
    
                dataOutputStream.writeBytes(lineEnd);
    
                //returns no. of bytes present in fileInputStream
                bytesAvailable = fileInputStream.available();
                //selecting the buffer size as minimum of available bytes or 1 MB
                bufferSize = Math.min(bytesAvailable,maxBufferSize);
                //setting the buffer as byte array of size of bufferSize
                buffer = new byte[bufferSize];
    
                //reads bytes from FileInputStream(from 0th index of buffer to buffersize)
                bytesRead = fileInputStream.read(buffer,0,bufferSize);
    
                //loop repeats till bytesRead = -1, i.e., no bytes are left to read
                while (bytesRead > 0){
                    //write the bytes read from inputstream
                    dataOutputStream.write(buffer,0,bufferSize);
                    bytesAvailable = fileInputStream.available();
                    bufferSize = Math.min(bytesAvailable,maxBufferSize);
                    bytesRead = fileInputStream.read(buffer,0,bufferSize);
                }
    
                dataOutputStream.writeBytes(lineEnd);
                dataOutputStream.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
    
                serverResponseCode = connection.getResponseCode();
                String serverResponseMessage = connection.getResponseMessage();
    
                Log.i(TAG, "Server Response is: " + serverResponseMessage + ": " + serverResponseCode);
    
                //response code of 200 indicates the server status OK
                if(serverResponseCode == 200){
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            tvFileName.setText("File Upload completed.");
                        }
                    });
                }
    
                //closing the input and output streams
                fileInputStream.close();
                dataOutputStream.flush();
                dataOutputStream.close();
                this.selectedFilePath.clear();
    
            } catch (FileNotFoundException e) {
                e.printStackTrace();
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(MainActivity.this,"File Not Found",Toast.LENGTH_SHORT).show();
                    }
                });
            } catch (MalformedURLException e) {
                e.printStackTrace();
                Toast.makeText(MainActivity.this, "URL error!", Toast.LENGTH_SHORT).show();
    
            } catch (IOException e) {
                e.printStackTrace();
                Toast.makeText(MainActivity.this, "Cannot Read/Write File!", Toast.LENGTH_SHORT).show();
            }
            dialog.dismiss();
    
            return serverResponseCode;
        }
    
    }
         }
    

    它正在使用 android nougat。

    【讨论】:

      【解决方案4】:

      在点击相机按钮或相机图像点击事件时执行此操作

      Uri fileUri;
      Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
      
      if (cameraIntent.resolveActivity(getPackageManager()) != null) {
           ContentValues values = new ContentValues(1);
           values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpg");
           fileUri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
           cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
           Log.d("FILEURI",fileUri+"");
           editor.putString("Fileurl", fileUri+"");
           editor.commit();
           cameraIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
           startActivityForResult(cameraIntent, CAMERA_REQUEST);
      }
      

      在 onActivityResult 方法中执行此操作

      if (requestCode == CAMERA_REQUEST && resultCode == Activity.RESULT_OK) {
      
          try {
               String utlstr =preferences.getString("Fileurl","");
               Log.d("sad",utlstr);
               Uri uri = Uri.parse(utlstr);
      
               final File file = inputStreamToFile(getContentResolver().openInputStream(uri), "png");
      
           } catch (FileNotFoundException e) {
               e.printStackTrace();
           }        
       }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-03-04
        • 1970-01-01
        • 1970-01-01
        • 2017-10-19
        • 1970-01-01
        • 2011-11-23
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多