保存图像后由于方向更改导致 Android 显示图像捕获错误
Posted
技术标签:
【中文标题】保存图像后由于方向更改导致 Android 显示图像捕获错误【英文标题】:Android display image capture error due to orientation change after saving of image 【发布时间】:2013-11-25 19:48:23 【问题描述】:目前我正在使用某些设备进行图像捕获。好吧,现在我正在使用 Optimus G 和三星 Galaxy 选项卡对其进行测试,以在设备上进行具体测试。现在我已经设法捕捉到一张图片,保存它然后在 ImageView 上预览它。无论如何它都可以正常工作,但是每当我尝试在纵向模式下捕获图像然后将其保存为横向模式时,意图然后将布局从横向快速更改为纵向,然后横向然后以纵向返回我的应用程序,但应用程序随后停止工作。我不知道为什么会发生这种情况,而且我无法从手机获取日志,因为我没有运行 adb logcat 的驱动程序。无论如何,这种情况最常发生在 optimus G 设备上。虽然如果我在风景上捕捉它然后将它保存在风景上它就可以了。真的很奇怪。
至于我的捕获代码是:
public void captureImage()
try
Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
cameraIntent.putExtra(MediaStore.EXTRA_SCREEN_ORIENTATION, ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
getActivity().startActivityForResult(cameraIntent, capture_image);
catch (Exception e)
e.printStackTrace();
Toast.makeText(getActivity(),"Something went wrong",Toast.LENGTH_SHORT).show();
好的,我尝试使用强制纵向模式,但没有任何反应。
这是我的 onActivityResult:
if(requestCode == capture_image)
if(resultCode == Activity.RESULT_OK)
//Get the path of the captured image
Uri image_uri = data.getData();
String path = getPath(image_uri);
//send path to FragmentCamera
FragmentCamera.file_path = path;
//create thumbnail for display
File file = new File(FragmentCamera.file_path );
try
Bitmap thumbnail;
thumbnail = applyOrientation(decodeSampledBitmapFromFile(file.getAbsolutePath(), 500, 250), resolveBitmapOrientation(file));
FragmentCamera.thumb_receipt.setImageBitmap(thumbnail);
catch (IOException e)
e.printStackTrace();
这是我添加的捕获图像的修复程序:
public static Bitmap decodeSampledBitmapFromFile(String path, int reqWidth, int reqHeight) // BEST QUALITY MATCH
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path, options);
// Calculate inSampleSize
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
options.inPreferredConfig = Bitmap.Config.RGB_565;
int inSampleSize = 1;
if (height > reqHeight)
inSampleSize = Math.round((float)height / (float)reqHeight);
int expectedWidth = width / inSampleSize;
if (expectedWidth > reqWidth)
//if(Math.round((float)width / (float)reqWidth) > inSampleSize) // If bigger SampSize..
inSampleSize = Math.round((float)width / (float)reqWidth);
options.inSampleSize = inSampleSize;
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(path, options);
private int resolveBitmapOrientation(File bitmapFile) throws IOException
ExifInterface exif = null;
exif = new ExifInterface(bitmapFile.getAbsolutePath());
return exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
private Bitmap applyOrientation(Bitmap bitmap, int orientation)
int rotate = 0;
switch (orientation)
case ExifInterface.ORIENTATION_ROTATE_270:
rotate = 270;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
rotate = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_90:
rotate = 90;
break;
default:
return bitmap;
int w = bitmap.getWidth();
int h = bitmap.getHeight();
Matrix mtx = new Matrix();
mtx.postRotate(rotate);
return Bitmap.createBitmap(bitmap, 0, 0, w, h, mtx, true);
希望有人能帮助我为什么会出现这个问题。
更新:
我现在得到了日志,这是我得到的错误:
E/WindowManager: Activity com.mark.exercise.TabMainActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@42cdfff0 that was originally added here
android.view.WindowLeaked: Activity com.mark.exercise.TabMainActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@42cdfff0 that was originally added here
at android.view.ViewRootImpl.<init>(ViewRootImpl.java:378)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:324)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:256)
at android.view.WindowManagerImpl$CompatModeWrapper.addView(WindowManagerImpl.java:153)
at android.view.Window$LocalWindowManager.addView(Window.java:547)
at android.app.Dialog.show(Dialog.java:282)
at com.mark.exercise.TabMainActivity$GetListTask.onPreExecute(TabMainActivity.java:372)
at android.os.AsyncTask.executeOnExecutor(AsyncTask.java:586)
at android.os.AsyncTask.execute(AsyncTask.java:534)
at com.mark.exercise.TabMainActivity.getShoppingList(TabMainActivity.java:330)
at com.mark.exercise.TabMainActivity.onCreate(TabMainActivity.java:78)
at android.app.Activity.performCreate(Activity.java:5236)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1082)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2037)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2098)
at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3576)
at android.app.ActivityThread.access$700(ActivityThread.java:138)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1210)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4911)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:790)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:557)
at dalvik.system.NativeStart.main(Native Method)
11-13 17:55:34.228 747-747/? D/StatusBar.NetworkController: refreshViews connected= wifi level=5 combinedSignalIconId=0x7f02039b/com.android.systemui:drawable/stat_sys_wifi_signal_3_fully combinedActivityIconId=0x7f020393 mobileLabel=Globe wifiLabel=WiFixxxxXXXXxxxxXXXX emergencyOnly=false combinedLabel=WiFixxxxXXXXxxxxXXXX mAirplaneMode=false mDataActivity=0 mPhoneSignalIconId=0x7f020366 mDataDirectionIconId=0x0 mDataSignalIconId=0x7f020366 mDataTypeIconId=0x0 mNoSimIconId=0x0 mThirdTypeIconId=0x0 mWifiIconId=0x7f02039b mBluetoothTetherIconId=0x108054f
11-13 17:55:34.418 12444-12444/? E/CameraApp: [SoundController.java:483:onDestroy()] onDestroy-start, sound_pool release 1/2
11-13 17:55:34.428 12444-12444/? E/CameraApp: [SoundController.java:525:onDestroy()] onDestroy-end, sound_pool release 2/2
11-13 17:55:34.628 13627-13627/com.mark.exercise E/AndroidRuntime: FATAL EXCEPTION: main
java.lang.IllegalArgumentException: View not attached to window manager
at android.view.WindowManagerImpl.findViewLocked(WindowManagerImpl.java:685)
at android.view.WindowManagerImpl.removeView(WindowManagerImpl.java:381)
at android.view.WindowManagerImpl$CompatModeWrapper.removeView(WindowManagerImpl.java:164)
at android.app.Dialog.dismissDialog(Dialog.java:347)
at android.app.Dialog.dismiss(Dialog.java:330)
at com.mark.exercise.TabMainActivity$GetListTask.onPostExecute(TabMainActivity.java:379)
at com.mark.exercise.TabMainActivity$GetListTask.onPostExecute(TabMainActivity.java:337)
at android.os.AsyncTask.finish(AsyncTask.java:631)
at android.os.AsyncTask.access$600(AsyncTask.java:177)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:644)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4911)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:790)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:557)
at dalvik.system.NativeStart.main(Native Method)
11-13 17:55:34.628 536-547/? W/ActivityManager: Force finishing activity com.mark.exercise/.TabMainActivity
11-13 17:55:35.159 536-550/? W/ActivityManager: Activity pause timeout for ActivityRecord42b81c88 com.mark.exercise/.TabMainActivity
11-13 17:55:35.349 1298-1342/? E/ThermalDaemon: [GPU_MON] 0 percent. Current Sampling Time is 4 sec
好吧,我在这里看到的是,应用程序在相机意图之后返回创建活动。因为 getList 方法的一部分仅在创建时触发。这对我来说越来越奇怪了。
添加:
TabMainActivity.java
public class TabMainActivity extends FragmentActivity
private FragmentTabHost mTabHost;
ArrayList<String> ids = new ArrayList<String>();
private Map hash_values = new HashMap();
String uid;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.bottom_tabs);
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
SharedPreferences.Editor editor = preferences.edit();
editor.putString("uid",getIntent().getStringExtra("user_id"));
editor.commit();
uid = getIntent().getStringExtra("user_id");
getShoppingList(uid);
mTabHost = (FragmentTabHost) findViewById(android.R.id.tabhost);
mTabHost.setup(this, getSupportFragmentManager(), R.id.realtabcontent);
Bundle b = new Bundle();
b.putString("0", "Me");
mTabHost.addTab(mTabHost.newTabSpec("me").setIndicator(null,getResources().getDrawable(R.drawable.selector_me)),
FragmentMe.class, b);
b = new Bundle();
b.putString("1", "Social");
mTabHost.addTab(mTabHost.newTabSpec("social").setIndicator(null, getResources().getDrawable(R.drawable.selector_social)),
FragmentSocial.class, b);
b.putString("2", "Promo");
mTabHost.addTab(mTabHost.newTabSpec("promo").setIndicator(null,getResources().getDrawable(R.drawable.selector_promo)),
FragmentPromo.class, b);
b = new Bundle();
b.putString("3", "Camera");
mTabHost.addTab(mTabHost.newTabSpec("camera").setIndicator(null,getResources().getDrawable(R.drawable.selector_capture)),
FragmentCamera.class, b);
b.putString("4", "List");
mTabHost.addTab(mTabHost.newTabSpec("shopping_list").setIndicator(null,getResources().getDrawable(R.drawable.selector_shopping_list)),
FragmentViewPager.class, b);
private static final int capture_image = 1;
private static final int select_image = 2;
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == capture_image)
if(resultCode == Activity.RESULT_OK)
//Get the path of the captured image
Uri image_uri = data.getData();
String path = getPath(image_uri);
//send path to FragmentCamera
FragmentCamera.file_path = path;
//create thumbnail for display
File file = new File(FragmentCamera.file_path );
try
Bitmap thumbnail;
thumbnail = applyOrientation(decodeSampledBitmapFromFile(file.getAbsolutePath(), 500, 250), resolveBitmapOrientation(file));
FragmentCamera.thumb_receipt.setImageBitmap(thumbnail);
catch (IOException e)
e.printStackTrace();
if(requestCode == select_image)
if(resultCode == Activity.RESULT_OK)
Uri selectedImage = data.getData();
String[] filePathColumn = MediaStore.Images.Media.DATA;
Cursor cursor = getContentResolver().query(selectedImage, filePathColumn, null, null, null);
cursor.moveToFirst();
//Get the path of the selected image
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
String path = cursor.getString(columnIndex);
cursor.close();
//send path to FragmentCamera
FragmentCamera.file_path = path;
//create thumbnail for display
FragmentCamera.file_path = path;
//create thumbnail for display
File file = new File(FragmentCamera.file_path );
try
Bitmap thumbnail;
thumbnail = applyOrientation(decodeSampledBitmapFromFile(file.getAbsolutePath(), 500, 250), resolveBitmapOrientation(file));
FragmentCamera.thumb_receipt.setImageBitmap(thumbnail);
catch (IOException e)
e.printStackTrace();
public String getPath(Uri uri)
Cursor cursor = null;
int column_index = 0;
try
String[] projection = MediaStore.Images.Media.DATA ;
cursor = getContentResolver().query(uri, projection, null, null, null);
column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
catch (Exception e)
Log.d("Error", "Exception Occured", e);
return cursor.getString(column_index);
public static Bitmap decodeSampledBitmapFromFile(String path, int reqWidth, int reqHeight) // BEST QUALITY MATCH
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path, options);
// Calculate inSampleSize
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
options.inPreferredConfig = Bitmap.Config.RGB_565;
int inSampleSize = 1;
if (height > reqHeight)
inSampleSize = Math.round((float)height / (float)reqHeight);
int expectedWidth = width / inSampleSize;
if (expectedWidth > reqWidth)
//if(Math.round((float)width / (float)reqWidth) > inSampleSize) // If bigger SampSize..
inSampleSize = Math.round((float)width / (float)reqWidth);
options.inSampleSize = inSampleSize;
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(path, options);
private int resolveBitmapOrientation(File bitmapFile) throws IOException
ExifInterface exif = null;
exif = new ExifInterface(bitmapFile.getAbsolutePath());
return exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
private Bitmap applyOrientation(Bitmap bitmap, int orientation)
int rotate = 0;
switch (orientation)
case ExifInterface.ORIENTATION_ROTATE_270:
rotate = 270;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
rotate = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_90:
rotate = 90;
break;
default:
return bitmap;
int w = bitmap.getWidth();
int h = bitmap.getHeight();
Matrix mtx = new Matrix();
mtx.postRotate(rotate);
return Bitmap.createBitmap(bitmap, 0, 0, w, h, mtx, true);
private Bitmap createThumbnail(String image_path)
Bitmap thumb=null;
Bitmap get_image = BitmapFactory.decodeFile(image_path);
int h = 500;
int w = 500;
thumb = Bitmap.createScaledBitmap(get_image,h, w, true);
return thumb;
public void getShoppingList(String user_id)
try
HashMap params = new HashMap<String,String>();
params.put("uid", user_id);
params.put("url", "http://ec2-54-254-129-196.ap-southeast-1.compute.amazonaws.com/get_shoplist.php");
//pass parameters
hash_values.putAll(params);
//start async task
new GetListTask().execute(hash_values);
catch (Exception e)
e.printStackTrace();
Toast.makeText(getBaseContext(), "Something went wrong", Toast.LENGTH_SHORT).show();
public class GetListTask extends AsyncTask<Map, Integer, Void>
ProgressDialog progressDialog;
String json_response = null;
@Override
protected Void doInBackground(Map... maps)
json_response = getShoppingListResponse(maps[0]);
int i = 0;
while (i <= 10)
try
Thread.sleep(50);
publishProgress(i);
i++;
catch (Exception e)
Log.i("The progress", e.getMessage());
return null;
protected void onProgressUpdate(Integer... progress)
progressDialog.setProgress(progress[0]*10);
@Override
protected void onPreExecute()
/*Do something before the async task starts*/
progressDialog = new ProgressDialog(TabMainActivity.this);
progressDialog.setMessage("Getting your shopping list");
progressDialog.setIndeterminate(false);
progressDialog.setMax(100);
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressDialog.show();
//progressDialog = ProgressDialog.show(getActivity(), "Loading", "Getting the updated list, please wait a moment");
protected void onPostExecute(Void v)
setJSONtoList(json_response);
progressDialog.dismiss();
private void setJSONtoList(String response)
try
JSONArray jArray = new JSONArray(response);
JSONObject json_data=null;
for(int i=0;i<jArray.length();i++)
json_data = jArray.getJSONObject(i);
DatabasePrefs dbPref = new DatabasePrefs(getBaseContext());
dbPref.insertShoppingList(Integer.parseInt(json_data.getString("idlist")),Integer.parseInt(uid),json_data.getString("list_name"));
//TODO check
ids.add(json_data.getString("idlist"));
catch(JSONException e)
Log.v("Problem", "Error parsing data " + e.toString());
new getListThread().execute();
int ctr = 0;
public class getListThread extends AsyncTask<Void, Void, Void>
@Override
protected Void doInBackground(Void... voids)
try
getListContent(ids.get(ctr));
catch (Exception e)
e.printStackTrace();
return null;
@Override
protected void onPostExecute(Void v)
ctr++;
if(ctr < ids.size())
new getListThread().execute();
public void getListContent(String id)
try
HashMap params = new HashMap<String,String>();
params.put("idlist", id);
params.put("url", "http://ec2-54-254-129-196.ap-southeast-1.compute.amazonaws.com/get_list_items.php");
//pass parameters
hash_values.putAll(params);
//start async task
new CreateNewList().execute(hash_values);
catch (Exception e)
e.printStackTrace();
Toast.makeText(TabMainActivity.this, "Something went wrong", Toast.LENGTH_SHORT).show();
public class CreateNewList extends AsyncTask<Map, Void, Void>
FragmentShoppingList fsl = new FragmentShoppingList();
String response;
@Override
protected Void doInBackground(Map... maps)
//reused method
response = fsl.getShoppingListResponse(maps[0]);
return null;
protected void onPostExecute(Void v)
setJSONtoListItems(response);
Log.v("The id of the list", response);
private void setJSONtoListItems(String response)
try
JSONArray jArray = new JSONArray(response);
JSONObject json_data=null;
for(int i=0;i<jArray.length();i++)
json_data = jArray.getJSONObject(i);
String id = json_data.getString("id_list_content");
String list_id = json_data.getString("idlist");
String item_id = json_data.getString("iditem");
String item_name = json_data.getString("name");
String item_price = json_data.getString("price");
String was_price = json_data.getString("was_price");
DatabasePrefs db = new DatabasePrefs(TabMainActivity.this);
db.insertItem(Long.parseLong(id), Integer.parseInt(list_id), Integer.parseInt(item_id), item_name, item_price, was_price);
Log.v("The result",id+","+list_id+","+item_id+","+item_name+","+item_price+","+was_price);
catch(JSONException e)
Log.v("Problem", "Error parsing data " + e.toString());
public String getShoppingListResponse(Map hash_values)
String response = "";
InputStream is = null;
StringBuilder string_builder = null;
String url = hash_values.get("url").toString().replace(" ", "%20"); //get the URL replacing the space with %20
try
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost(url);
MultipartEntity mpEntity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
/*This will convert the hashMap sent into individual part per key per value*/
Set set = hash_values.entrySet();
Iterator iterator = set.iterator();
/*do a loop passing all the data on a string*/
while(iterator.hasNext())
Map.Entry mapEntry = (Map.Entry)iterator.next();
String keyword = String.valueOf(mapEntry.getKey());
String value = String.valueOf(mapEntry.getValue());
/*this will check if the passed data is a URL, file or a simple value*/
if(!keyword.equals("url"))
if(value.matches("(.*)/(.*)"))
File file = new File(value);
Log.v("Does this exists?", String.valueOf(file.exists()));
if(file.exists())
FileBody upload_file;
upload_file = new FileBody(file);
/*not url but file*/
mpEntity.addPart(keyword, upload_file);
else
/*not url and not file*/
mpEntity.addPart(keyword, new StringBody(value));
else
/*not URL and not file*/
mpEntity.addPart(keyword, new StringBody(value));
post.setEntity(mpEntity);
HttpResponse http_res = client.execute(post);
HttpEntity resEntity = http_res.getEntity();
is = resEntity.getContent();
catch (Exception e)
e.printStackTrace();
response = "";
/*convert JSON to string*/
try
BufferedReader reader = new BufferedReader(new InputStreamReader(is,"iso-8859-1"),8);
string_builder = new StringBuilder();
String line = "0";
while ((line = reader.readLine()) != null)
string_builder.append(line + "\n");
is.close();
response = string_builder.toString();
catch(Exception e)
e.printStackTrace();
return response;
【问题讨论】:
没有 logcat,你是瞎子,我们也是。 我们将尝试获取驱动程序并尽快获取 logcat。我认为这是我目前唯一能做的。 当您的设备无法连接到PC时,请使用catlog而不是adb logcat
。
【参考方案1】:
您的分析是正确的。在某些设备上,尤其是 RAM 较小的设备上,摄像头捕获活动(通过意图调用)可能会导致调用活动被破坏。因此,在编写 onCreate() 时应该考虑到这种情况。另请注意,onActivityResult() 通常在 onResume() 之前调用。
很难说更多,因为您还没有公开 onCreate() 的代码或 TabMainActivity 类的其他相关方法。
【讨论】:
嗨,亚历克斯,感谢您的反馈。好吧,无论如何我会分享我的 TabMainActivity 类。希望您能给我一些建议,告诉我该怎么做。我将编辑问题。 我已经通过添加 android:configChanges="orientation|keyboardHidden|screenSize" 解决了这个问题。参考可以在这里找到:***.com/questions/16154279/… 谢谢! :) 您的修复是一个值得欢迎的改进。但仍有可能会在从相机返回时启动onCreate()
,请参阅groups.google.com/d/topic/android-developers/vuumT5oUHTE/…。因此onCreate()
的逻辑应该为这种情况做好准备,而不是假设Activity是用getIntent()
提供的uid启动的。
我明白了,谢谢你的建议。我会尝试找出一种方法来改进这些部分。再次感谢。以上是关于保存图像后由于方向更改导致 Android 显示图像捕获错误的主要内容,如果未能解决你的问题,请参考以下文章