Tôi mất một lúc để làm cho nó hoạt động và tôi đã thực hiện một số điều và cuối cùng nó hoạt động. Tôi không thể chắc chắn rằng những điều tôi đã làm là giải pháp cho vấn đề, nhưng tất cả chúng cùng tạo thành giải pháp làm việc.
Có nhiều lý do khiến hoạt động của máy ảnh không trả lại. Hai người chính là:
đường dẫn cho các bức tranh mới là không hợp lệ, hoặc không tồn tại, hoặc nó không thể được tạo
ứng dụng đã bị đình chỉ và lưu con đường bị lạc.
Vì vậy, đây là mã của tôi giải quyết tất cả những vấn đề này, tất cả cùng nhau làm việc.
Trước tiên tôi tạo ra lớp helper ImageServices
:
class ImageServices {
private static String getTempDirectoryPath(Context ctx) {
File cache;
// SD Card Mounted
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
cache = new File(Environment.getExternalStorageDirectory().getAbsolutePath() +
"/Android/data/" + ctx.getPackageName() + "/cache/");
}
// Use internal storage
else {
cache = ctx.getCacheDir();
}
// Create the cache directory if it doesn't exist
if (!cache.exists()) {
cache.mkdirs();
}
return cache.getAbsolutePath();
}
public static Uri getOutputImageFileUri(Context ctx) {
// TODO: check the presence of SDCard
String tstamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File file = new File(getTempDirectoryPath(ctx), "IMG_" + tstamp + ".jpg");
return Uri.fromFile(file);
}
}
Mã này được lấy cảm hứng từ một phần bởi developer.android.com và một phần bởi CameraLauncher class của dự án Apache Cordova.
Trong hoạt động của tôi xử lý sự kiện cho nút để chụp một bức ảnh trông như thế này:
private Uri imageFileUri;
private static final int MAKE_PHOTO_RESULT_CODE = 100;
private static final int PICK_PHOTO_RESULT_CODE = 101;
public void onMakePhoto(View v) {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
imageFileUri = ImageServices.getOutputImageFileUri(this);
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageFileUri);
Log.i("babies", "Taking picture: requested " + imageFileUri);
startActivityForResult(intent, MAKE_PHOTO_RESULT_CODE);
}
Phương pháp onActivityResult
không thực sự chứa nhiều, như imageFileUri đã chỉ vào tập tin hiện hành và dựng hình cần thiết được thực hiện trong onResume
phương pháp, được gọi là khi hoạt động sẽ trở lại vào foreground:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
switch(requestCode) {
case MAKE_PHOTO_RESULT_CODE:
assert imageFileUri != null;
break;
case ...
...other cases...
break;
}
}
}
Nhưng điều này vẫn là chưa đủ, như imageFileUri
bị mất như ứng dụng của bạn bị treo. Và trên thiết bị thông thường, cơ hội gần 100%.Vì vậy, tiếp theo bạn cần để lưu trữ các giá trị của imageFileUri
trạng thái dụ:
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (imageFileUri == null) {
outState.putString("file-uri", "");
}
else {
outState.putString("file-uri", imageFileUri.toString());
}
};
và tải nó một lần nữa trong - dễ nhất là trực tiếp trong onCreate
:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
if (savedInstanceState != null) {
String fileUri = savedInstanceState.getString("file-uri");
if (!fileUri.equals("")) imageFileUri = Uri.parse(fileUri);
}
}
Vì vậy, một lần nữa, trên đầu trang của nhiều giải pháp khác được trình bày trên trang web này cũng như ở những nơi khác, có hai sự khác biệt lớn:
- thông minh hơn
getTempDirectoryPath
lấy cảm hứng từ Apache Cordova
- cho phép
imageFileUri
để tồn tại ứng dụng bị tạm ngưng
Và bây giờ - ít nhất là cho tôi - mọi thứ đều hoạt động tốt.
Bạn quên gọi 'Toast.show(); 'inside' onActivityResult() '. Nó phải là 'Toast.makeText (điều này," Đã đăng ký thành công! ", Toast.LENGTH_LONG) .show();' –