web-dev-qa-db-fra.com

La caméra ne fonctionne pas dans Nougat 7.0

Le code de mon appareil photo fonctionne dans toutes les versions d'Android mais dans Nougat 7.0, l'erreur suivante apparaît: 

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

Il fonctionne parfaitement sur toutes les autres versions d'Android sauf sur Android 7.0. J'ai donné l'autorisation pour la caméra et la galerie, mais la caméra ne fonctionne toujours pas. Voici le code pertinent:

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

        }
    }
}

Voici mon 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)
8
Anand Jain

Essayez ceci, ce n'est pas l'intention qui crée le problème une fois que vous avez pris la photo, sauvegardé sur la carte SD et récupéré l'URI est différent dans Nougat ....

Il est assez facile d'implémenter FileProvider sur votre application. Vous devez d’abord ajouter une balise FileProvider dans AndroidManifest.xml sous la balise comme ci-dessous: 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>

Et créez ensuite un fichier provider_paths.xml dans le dossier xml sous le dossier res. Un dossier peut être nécessaire pour créer s'il n'existe pas.

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>

Terminé! FileProvider est maintenant déclaré et prêt à être utilisé.

La dernière étape consiste à modifier la ligne de code ci-dessous dans MainActivity.Java.

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

à

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

Et fait ! Votre application devrait maintenant fonctionner parfaitement sur toutes les versions d'Android, y compris Android Nougat. À votre santé !

3
Jaydip Bhensdadiya

Cela pourrait être lié au changement de Nougat qui n'autorise pas l'attachement du schéma "fichier: //" à une intention.

Découvrez ce blogpost pour plus de détails

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

1
Themasterhimself

Faites-le en cliquant sur le bouton de la caméra ou en cliquant sur l'événement

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

Faites cela dans la méthode 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();
     }        
 }
0
Urvish. Isoft

J'ai téléchargé l'image sur le serveur à l'aide de la caméra pour 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;
    }

}
     }

cela fonctionne avec le nougat Android.

0
Kishor N R