Camera is not working in Nougat 7.0

懵懂的女人 提交于 2019-12-12 07:57:16

问题


My camera code is working in all Android versions but in Nougat 7.0 it gives the following error:

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

It is working perfectly on all other versions of android except on android 7.0. I have given run time permission for the camera & the gallery but the camera is still not working. Here is the relevant code:

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

        }
    }
}

Here is my logcat:-

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)

回答1:


Try this its not the intent that create the problem once you take the picture and save to the SD card and getting back the URI is different in Nougat....

It is quite easy to implement FileProvider on your application. First you need to add a FileProvider tag in AndroidManifest.xml under tag like below: 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>

And then create a provider_paths.xml file in xml folder under res folder. Folder may be needed to create if it doesn't exist.

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>

Done! FileProvider is now declared and be ready to use.

The final step is to change the line of code below in MainActivity.java

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

to

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

And .... done ! Your application should now work perfectly fine on any Android version including Android Nougat. Cheers !




回答2:


This might be related to the change in Nougat which doesn't allow "file://" scheme to be attached to an intent.

Check out this blogpost for more details

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




回答3:


I have done image uploading to server using camera for 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;
    }

}
     }

it is working with android nougat.




回答4:


Do this on click of camera button or camera image click event

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

Do this in onActivityResult method

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


来源:https://stackoverflow.com/questions/41958462/camera-is-not-working-in-nougat-7-0

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!