问题
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