从 Android 中的内部存储获取图像时出现 NullPointerException
NullPointerException when getting image from internal storage in Android
我正在按照教程在 Android 上开发学生注册应用程序。我需要创建一个新学生,将照片保存在 phone。
问题是我无法从检索到的 URI 加载图像。
我的 "Script" 日志打印:
Img uri: content://com.android.providers.media.documents/document/image%3A30
但是我的 imgString 是空的。
顺便说一句,我正在使用genymotion模拟器。
这是调用图库的代码...
public void loadImage(View view){
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("image/*");
startActivityForResult(intent, IMG_SDCARD_ACTIVITY);
}
这是处理图库答案的 onActivityResult...
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
File file;
String pass = null;
Log.i("Script", "RequestCode: "+requestCode+" ResultCode: "+resultCode);
if(requestCode == IMG_SDCARD_ACTIVITY && resultCode == Activity.RESULT_OK){
try{
Uri img = data.getData();
Log.i("Script", "Img uri: "+img.toString());
String[] cols = {MediaStore.Images.Media.DATA};
Cursor cursor = getContentResolver().query(img, cols, null, null, null);
cursor.moveToFirst();
int indexCol = cursor.getColumnIndex(cols[0]);
String imgString = cursor.getString(indexCol);
cursor.close();
file = new File(imgString); //this is the line 108 where the problem is...
ivImg.setImageBitmap(ImageUtil.setPic(Uri.fromFile(file), 100, 100));
ivImg.setContentDescription(file.getPath());
pass = "passou";
}
catch (NullPointerException e){e.printStackTrace();}
catch (Exception e){e.printStackTrace();}
finally {
if(pass==null){
ivImg.setImageResource(R.drawable.person);
Toast.makeText(SalvarAlunoActivity.this, "Fail! Try again.", Toast.LENGTH_SHORT).show();
}
}
}
}
这是 ImageUtil class...
public class ImageUtil {
public static Bitmap setPic(Uri uriFile, int width, int height){
//Get the dimensions of the view
int targetW = width;
int targetH = height;
//Get the dimensions of the Bitmap
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(uriFile.getPath(), bmOptions);
int photoW = bmOptions.outWidth;
int photoH = bmOptions.outHeight;
//Determine how much to scale down the image
int scaleFactor = Math.min(photoW/targetW, photoH/targetH);
//Decode the image file into a Bitmap sized to fill the View
bmOptions.inJustDecodeBounds = false;
bmOptions.inSampleSize = scaleFactor;
bmOptions.inPurgeable = true;
Bitmap bitmap = BitmapFactory.decodeFile(uriFile.getPath(), bmOptions);
return(bitmap);
}
}
日志也打印出这个错误...
10-28 08:19:45.602 10874-10874/? W/System.err﹕ java.lang.NullPointerException
10-28 08:19:45.606 10874-10874/? W/System.err﹕ at java.io.File.fixSlashes(File.java:185)
10-28 08:19:45.606 10874-10874/? W/System.err﹕ at java.io.File.<init>(File.java:134)
10-28 08:19:45.606 10874-10874/? W/System.err﹕ at com.XXXX.contentProvider.SalvarAlunoActivity.onActivityResult(SalvarAlunoActivity.java:108)
10-28 08:19:45.606 10874-10874/? W/System.err﹕ at android.app.Activity.dispatchActivityResult(Activity.java:5423)
10-28 08:19:45.606 10874-10874/? W/System.err﹕ at android.app.ActivityThread.deliverResults(ActivityThread.java:3347)
10-28 08:19:45.606 10874-10874/? W/System.err﹕ at android.app.ActivityThread.handleSendResult(ActivityThread.java:3394)
10-28 08:19:45.606 10874-10874/? W/System.err﹕ at android.app.ActivityThread.access00(ActivityThread.java:135)
10-28 08:19:45.606 10874-10874/? W/System.err﹕ at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1244)
10-28 08:19:45.606 10874-10874/? W/System.err﹕ at android.os.Handler.dispatchMessage(Handler.java:102)
10-28 08:19:45.606 10874-10874/? W/System.err﹕ at android.os.Looper.loop(Looper.java:136)
10-28 08:19:45.606 10874-10874/? W/System.err﹕ at android.app.ActivityThread.main(ActivityThread.java:5001)
10-28 08:19:45.606 10874-10874/? W/System.err﹕ at java.lang.reflect.Method.invokeNative(Native Method)
10-28 08:19:45.606 10874-10874/? W/System.err﹕ at java.lang.reflect.Method.invoke(Method.java:515)
10-28 08:19:45.606 10874-10874/? W/System.err﹕ at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
10-28 08:19:45.606 10874-10874/? W/System.err﹕ at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
10-28 08:19:45.606 10874-10874/? W/System.err﹕ at dalvik.system.NativeStart.main(Native Method)
这是我第一次来这里。如果我需要提供更多信息,请告诉我。
提前致谢。
A Uri
is not a file。您从 ACTION_GET_CONTENT
请求返回的 Uri
不必指向文件,更不用说您可以在文件系统上自行访问的文件了。此外,您从 ACTION_GET_CONTENT
请求返回的 Uri
不必是来自 MediaStore
的请求,并且 MediaStore
不必是 return在任何情况下都是 DATA
值。
我不知道 ImageUtil.setPic()
做了什么,但是如果它需要 Uri
作为输入,请传入您在 onActivityResult()
中返回的实际 Uri
。 setPic()
希望 在幕后使用 ContentResolver
和 openInputStream()
。
更好的方法是使用图像加载库,例如 Picasso or Universal Image Loader,这样所有磁盘 I/O 和位图解码都可以在后台线程上完成。
您的文件路径为空。从图库中选择图片时,您可以直接从 uri
中获取 Bitmap
。所以在你的 onActivityResult
方法中做这样的事情:
Uri fileUri = data.getData();
Bitmap b = decodeUri(fileUri);
your_image_view.setImageBitmap(b);
// here decodeUri method will directly return you Bitmap which can be set to imageview
private Bitmap decodeUri(Uri selectedImage) throws FileNotFoundException
{
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(getContentResolver()
.openInputStream(selectedImage), null, o);
final int REQUIRED_SIZE = 72;
int width_tmp = o.outWidth, height_tmp = o.outHeight;
int scale = 1;
while (true)
{
if (width_tmp / 2 < REQUIRED_SIZE || height_tmp / 2 < REQUIRED_SIZE)
{
break;
}
width_tmp /= 2;
height_tmp /= 2;
scale *= 2;
}
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver()
.openInputStream(selectedImage), null, o2);
return bitmap;
}
编辑:
Uri 的解释见@CommonsWare 的回答。他还提到了 Picasso,这是一个非常有用的库,可以让 android 在 android 中有效地加载图像。
我认为上面的答案很好地涵盖了您遇到的错误,但是根据经验,您永远不应假设 cursor.moveToFirst() 会起作用,而是将其包装在 if 中,因为它 returns一个布尔值。
if(cursor.moveToFirst())
{
//Do something here
}
我正在按照教程在 Android 上开发学生注册应用程序。我需要创建一个新学生,将照片保存在 phone。
问题是我无法从检索到的 URI 加载图像。
我的 "Script" 日志打印:
Img uri: content://com.android.providers.media.documents/document/image%3A30
但是我的 imgString 是空的。
顺便说一句,我正在使用genymotion模拟器。
这是调用图库的代码...
public void loadImage(View view){
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("image/*");
startActivityForResult(intent, IMG_SDCARD_ACTIVITY);
}
这是处理图库答案的 onActivityResult...
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
File file;
String pass = null;
Log.i("Script", "RequestCode: "+requestCode+" ResultCode: "+resultCode);
if(requestCode == IMG_SDCARD_ACTIVITY && resultCode == Activity.RESULT_OK){
try{
Uri img = data.getData();
Log.i("Script", "Img uri: "+img.toString());
String[] cols = {MediaStore.Images.Media.DATA};
Cursor cursor = getContentResolver().query(img, cols, null, null, null);
cursor.moveToFirst();
int indexCol = cursor.getColumnIndex(cols[0]);
String imgString = cursor.getString(indexCol);
cursor.close();
file = new File(imgString); //this is the line 108 where the problem is...
ivImg.setImageBitmap(ImageUtil.setPic(Uri.fromFile(file), 100, 100));
ivImg.setContentDescription(file.getPath());
pass = "passou";
}
catch (NullPointerException e){e.printStackTrace();}
catch (Exception e){e.printStackTrace();}
finally {
if(pass==null){
ivImg.setImageResource(R.drawable.person);
Toast.makeText(SalvarAlunoActivity.this, "Fail! Try again.", Toast.LENGTH_SHORT).show();
}
}
}
}
这是 ImageUtil class...
public class ImageUtil {
public static Bitmap setPic(Uri uriFile, int width, int height){
//Get the dimensions of the view
int targetW = width;
int targetH = height;
//Get the dimensions of the Bitmap
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(uriFile.getPath(), bmOptions);
int photoW = bmOptions.outWidth;
int photoH = bmOptions.outHeight;
//Determine how much to scale down the image
int scaleFactor = Math.min(photoW/targetW, photoH/targetH);
//Decode the image file into a Bitmap sized to fill the View
bmOptions.inJustDecodeBounds = false;
bmOptions.inSampleSize = scaleFactor;
bmOptions.inPurgeable = true;
Bitmap bitmap = BitmapFactory.decodeFile(uriFile.getPath(), bmOptions);
return(bitmap);
}
}
日志也打印出这个错误...
10-28 08:19:45.602 10874-10874/? W/System.err﹕ java.lang.NullPointerException
10-28 08:19:45.606 10874-10874/? W/System.err﹕ at java.io.File.fixSlashes(File.java:185)
10-28 08:19:45.606 10874-10874/? W/System.err﹕ at java.io.File.<init>(File.java:134)
10-28 08:19:45.606 10874-10874/? W/System.err﹕ at com.XXXX.contentProvider.SalvarAlunoActivity.onActivityResult(SalvarAlunoActivity.java:108)
10-28 08:19:45.606 10874-10874/? W/System.err﹕ at android.app.Activity.dispatchActivityResult(Activity.java:5423)
10-28 08:19:45.606 10874-10874/? W/System.err﹕ at android.app.ActivityThread.deliverResults(ActivityThread.java:3347)
10-28 08:19:45.606 10874-10874/? W/System.err﹕ at android.app.ActivityThread.handleSendResult(ActivityThread.java:3394)
10-28 08:19:45.606 10874-10874/? W/System.err﹕ at android.app.ActivityThread.access00(ActivityThread.java:135)
10-28 08:19:45.606 10874-10874/? W/System.err﹕ at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1244)
10-28 08:19:45.606 10874-10874/? W/System.err﹕ at android.os.Handler.dispatchMessage(Handler.java:102)
10-28 08:19:45.606 10874-10874/? W/System.err﹕ at android.os.Looper.loop(Looper.java:136)
10-28 08:19:45.606 10874-10874/? W/System.err﹕ at android.app.ActivityThread.main(ActivityThread.java:5001)
10-28 08:19:45.606 10874-10874/? W/System.err﹕ at java.lang.reflect.Method.invokeNative(Native Method)
10-28 08:19:45.606 10874-10874/? W/System.err﹕ at java.lang.reflect.Method.invoke(Method.java:515)
10-28 08:19:45.606 10874-10874/? W/System.err﹕ at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
10-28 08:19:45.606 10874-10874/? W/System.err﹕ at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
10-28 08:19:45.606 10874-10874/? W/System.err﹕ at dalvik.system.NativeStart.main(Native Method)
这是我第一次来这里。如果我需要提供更多信息,请告诉我。
提前致谢。
A Uri
is not a file。您从 ACTION_GET_CONTENT
请求返回的 Uri
不必指向文件,更不用说您可以在文件系统上自行访问的文件了。此外,您从 ACTION_GET_CONTENT
请求返回的 Uri
不必是来自 MediaStore
的请求,并且 MediaStore
不必是 return在任何情况下都是 DATA
值。
我不知道 ImageUtil.setPic()
做了什么,但是如果它需要 Uri
作为输入,请传入您在 onActivityResult()
中返回的实际 Uri
。 setPic()
希望 在幕后使用 ContentResolver
和 openInputStream()
。
更好的方法是使用图像加载库,例如 Picasso or Universal Image Loader,这样所有磁盘 I/O 和位图解码都可以在后台线程上完成。
您的文件路径为空。从图库中选择图片时,您可以直接从 uri
中获取 Bitmap
。所以在你的 onActivityResult
方法中做这样的事情:
Uri fileUri = data.getData();
Bitmap b = decodeUri(fileUri);
your_image_view.setImageBitmap(b);
// here decodeUri method will directly return you Bitmap which can be set to imageview
private Bitmap decodeUri(Uri selectedImage) throws FileNotFoundException
{
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(getContentResolver()
.openInputStream(selectedImage), null, o);
final int REQUIRED_SIZE = 72;
int width_tmp = o.outWidth, height_tmp = o.outHeight;
int scale = 1;
while (true)
{
if (width_tmp / 2 < REQUIRED_SIZE || height_tmp / 2 < REQUIRED_SIZE)
{
break;
}
width_tmp /= 2;
height_tmp /= 2;
scale *= 2;
}
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver()
.openInputStream(selectedImage), null, o2);
return bitmap;
}
编辑:
Uri 的解释见@CommonsWare 的回答。他还提到了 Picasso,这是一个非常有用的库,可以让 android 在 android 中有效地加载图像。
我认为上面的答案很好地涵盖了您遇到的错误,但是根据经验,您永远不应假设 cursor.moveToFirst() 会起作用,而是将其包装在 if 中,因为它 returns一个布尔值。
if(cursor.moveToFirst())
{
//Do something here
}