我一直在努力创建一个活动,允许用户使用意图拍摄照片并通过电子邮件发送此图像。我创建文件名并将其存储在一个字符串中,但它最终会将其值带走。当它被重置为null时,我最终创建了另一个字符串变量来保存其值,因此我可以确保没有任何东西可以访问更改其值,但第二个字符串也最终为null。我使用字符串的值并将其传递给intent,以便将刚刚拍摄的图像添加为附件。任何人都可以看到这个变量为什么以及如何改变它的价值?
这是我的班级,有评论:
public class ImproveActivity extends Activity implements OnClickListener{
private static final String JPEG_FILE_PREFIX = "Improve_";
private static final String JPEG_FILE_SUFFIX = ".jpg";
private Bitmap mImageBitmap;
private ImageView mImageView;
private File storageDir;
private String mCurrentPhotoPath;
Button share, capture;
private String _path;
private File f;
//This variable holds file name
private String imageFileName;
//I am storing the file name variable here to keep its value
private String temp;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.improve_layout);
mImageView = (ImageView)findViewById(R.id.imgview);
capture = (Button)findViewById(R.id.capture);
share = (Button)findViewById(R.id.share);
capture.setOnClickListener(this);
share.setOnClickListener(this);
}
private void dispatchTakePictureIntent() {
if(isIntentAvailable(getApplicationContext(), MediaStore.ACTION_IMAGE_CAPTURE)){
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
;
try {
//f is the image
f = createImageFile();
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(f));
startActivityForResult(takePictureIntent, 1);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Toast.makeText(getApplicationContext(), "error creating image", Toast.LENGTH_LONG).show();
}
}
else{
Toast.makeText(getApplicationContext(), "no camera available", Toast.LENGTH_LONG).show();
}
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent intent){
Toast.makeText(getApplicationContext(), "returning", Toast.LENGTH_LONG).show();
if (requestCode == 1) {
mImageBitmap = BitmapFactory.decodeFile(mCurrentPhotoPath);
if (mImageBitmap == null) {
// bitmap still null
} else {
// set bitmap in imageview
mImageView.setImageBitmap(mImageBitmap);
}
}
}
private File createImageFile() throws IOException {
// Create an image file name
String timeStamp =
new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
imageFileName = JPEG_FILE_PREFIX + timeStamp + "_";
//display the current image file name
Toast.makeText(getApplicationContext(), imageFileName, Toast.LENGTH_LONG).show();
File file = new File(getAlbumDir().getAbsolutePath());
file.mkdirs();
Toast.makeText(getApplicationContext(), imageFileName, Toast.LENGTH_LONG).show();
File image = File.createTempFile(
imageFileName,
JPEG_FILE_SUFFIX
);
mCurrentPhotoPath = image.getAbsolutePath();
temp = imageFileName;
return image;
}
private File getAlbumDir() {
return storageDir = new File(
Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DCIM
),
"Camera"
);
}
public static boolean isIntentAvailable(Context context, String action) {
final PackageManager packageManager = context.getPackageManager();
final Intent intent = new Intent(action);
List<ResolveInfo> list =
packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
return list.size() > 0;
}
@Override
public void onClick(View v) {
switch(v.getId()){
case R.id.capture :
dispatchTakePictureIntent();
//displaying the value of the string imageFileName, it is what it should be, the file name
Toast.makeText(getApplicationContext(), imageFileName, Toast.LENGTH_LONG).show();
//displaying the file name in temp at this point it is still the file name I need
Toast.makeText(getApplicationContext(), "temp is " +temp, Toast.LENGTH_LONG).show();
break;
//Once the image is saved, clicking share to open chooser
case R.id.share:
//displaying the temp string the file name is gone it is now null ????
Toast.makeText(getApplicationContext(), "temp is " +temp, Toast.LENGTH_LONG).show();
Intent picMessageIntent = new Intent(android.content.Intent.ACTION_SEND);
picMessageIntent.setType("image/jpg");
File downloadedPic = new File(
Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DCIM),
"Camera/"+ temp+"jpg"); //I want to use the file name string to send the image via email
picMessageIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(downloadedPic));
startActivity(Intent.createChooser(picMessageIntent, "Send your picture using:"));
break;
}
}
如果有人能说清楚这是怎么回事,我将不胜感激。
这是logcat,我打开活动,拍照,保存,然后返回到活动视图,我按分享,吐司显示选择器打开时的temp值。
11-25 17:56:34.573: D/dalvikvm(12037): GC_EXTERNAL_ALLOC freed 1176 objects / 87312 bytes in 53ms
11-25 17:56:39.313: W/IInputConnectionWrapper(12037): showStatusIcon on inactive InputConnection
11-25 17:56:49.803: W/System.err(12037): java.lang.NullPointerException: Argument must not be null
11-25 17:56:49.808: W/System.err(12037): at java.io.FileInputStream.<init>(FileInputStream.java:78)
11-25 17:56:49.808: W/System.err(12037): at java.io.FileInputStream.<init>(FileInputStream.java:134)
11-25 17:56:49.808: W/System.err(12037): at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:349)
11-25 17:56:49.808: W/System.err(12037): at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:399)
11-25 17:56:49.808: W/System.err(12037): at com.seweb.app.ImproveActivity.onActivityResult(ImproveActivity.java:94)
11-25 17:56:49.808: W/System.err(12037): at android.app.Activity.dispatchActivityResult(Activity.java:3890)
11-25 17:56:49.808: W/System.err(12037): at android.app.ActivityThread.deliverResults(ActivityThread.java:3511)
11-25 17:56:49.808: W/System.err(12037): at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3115)
11-25 17:56:49.808: W/System.err(12037): at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3143)
11-25 17:56:49.813: W/System.err(12037): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2684)
11-25 17:56:49.813: W/System.err(12037): at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3815)
11-25 17:56:49.813: W/System.err(12037): at android.app.ActivityThread.access$2400(ActivityThread.java:125)
11-25 17:56:49.813: W/System.err(12037): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2037)
11-25 17:56:49.818: W/System.err(12037): at android.os.Handler.dispatchMessage(Handler.java:99)
11-25 17:56:49.818: W/System.err(12037): at android.os.Looper.loop(Looper.java:123)
11-25 17:56:49.818: W/System.err(12037): at android.app.ActivityThread.main(ActivityThread.java:4627)
11-25 17:56:49.818: W/System.err(12037): at java.lang.reflect.Method.invokeNative(Native Method)
11-25 17:56:49.818: W/System.err(12037): at java.lang.reflect.Method.invoke(Method.java:521)
11-25 17:56:49.823: W/System.err(12037): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:858)
11-25 17:56:49.823: W/System.err(12037): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
11-25 17:56:49.823: W/System.err(12037): at dalvik.system.NativeStart.main(Native Method)
11-25 17:56:50.273: D/dalvikvm(12037): GC_EXTERNAL_ALLOC freed 1920 objects / 108152 bytes in 136ms
答案 0 :(得分:4)
您应该在permanently save,数据库或通用文件中SharedPreferences使用字符串。
当您离开活动以使用内置相机应用拍摄照片时,您的应用会进入后台。如果需要额外的内存,后台的任何应用程序都有被操作系统杀死的风险。如果发生这种情况,所有变量都会重置为默认的空值...
<强>加成强>
来自您的LogCat:
java.lang.NullPointerException: Argument must not be null
...
at com.seweb.app.ImproveActivity.onActivityResult(ImproveActivity.java:94)
我猜第94行是:
mImageBitmap = BitmapFactory.decodeFile(mCurrentPhotoPath);
如果应用程序在后台销毁并重新启动,这是有意义的。当应用完全重启时,只会调用 onCreate()
,而不是createImageFile()
或任何其他方法。
将mCurrentPhotoPath
保存在SharedPreferences imageFileName
中,并在onActivityResult()
为空时在mCurrentPhotoPath
中恢复这些值。
使用SharedPreferences
将这些方法添加到您的活动:
private void savePreferences(){
// We need an Editor object to make preference changes.
SharedPreferences.Editor editor = getPreferences(MODE_PRIVATE).edit();
editor.putString("imageFileName", imageFileName);
editor.putString("mCurrentPhotoPath", mCurrentPhotoPath);
// Commit the edits!
editor.commit();
}
private void restorePreferences() {
SharedPreferences settings = getPreferences(MODE_PRIVATE);
imageFileName = settings.getString("imageFileName", "");
mCurrentPhotoPath = settings.getString("mCurrentPhotoPath", "");
}
我忽略了temp
,因为您在调试时说它只是imageFileName
的副本。
现在我们需要在适当的时候调用这些方法。首先让我们在离开活动之前保存两个字符串来拍照:
try {
savePreferences();
...
startActivityForResult(takePictureIntent, 1);
}
然后检查是否需要在onActivityResult()
中重新加载这些值:
if (requestCode == 1) {
if(mCurrentPhotoPath == null)
restorePreferences();
mImageBitmap = BitmapFactory.decodeFile(mCurrentPhotoPath);
...
答案 1 :(得分:0)
尝试初始化变量:
String temp = "";
答案 2 :(得分:0)
是初始化变量阻止获取NullPointerException,但问题是,为什么此时它为null。你确定,如果你得到一个空字符串就拍照吗?请显示堆栈跟踪,也许你的CreateImageFile-Method出了问题,这个方法有些人会引发异常吗?如果是,则无法初始化此String。
答案 3 :(得分:0)
我建议不要将其保存在shareprefrences中,而是将它保存在savedInstanceState中。
你可以打电话到商店:
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
savedInstanceState.putAll(getIntent().getExtras());
savedInstanceState.putString("currentPhotoPath", mCurrentPhotoPath);
super.onSaveInstanceState(savedInstanceState);
}
并在onCreate调用恢复:
if (savedInstanceState != null) {
mCurrentPhotoPath = savedInstanceState.getString("currentPhotoPath", mCurrentPhotoPath);
}
所以这就是:
您还可以查看这些页面以获得更好的表达方式:
https://developer.android.com/training/basics/activity-lifecycle/recreating.html
https://developer.android.com/training/camera/photobasics.html