完美解决三星手机拍照后横竖屏切换导致的回调为null以致程序崩溃的问题(包括三星note3的特殊适配)

场景:安卓开发中我们经常会有拍照上传的需求,比如上传图片,或者上传头像等等,方法也比较常规,通过调用startActivityForResult(Intent intent, int requestCode)方法调起系统的拍照,然后在onActivityResult(int requestCode, int resultCode, Intent data)方法中对回调结果进行处理。相信很多同学会遇到这种问题,就是部分三星手机,回调回来的结果是null,从而会导致程序崩溃的情况。
原因:这是因为部分三星手机(之所以说部分,是因为三星手机那么多没法都验证。。),拍照后会有一个横竖屏切换的过程,或者说旋转的过程,大家都知道,横竖屏切换会改变Activity的生命周期,从而就导致了回调的结果为null
解决:知道原因后接下来我们来分两种情况来解决下这个问题,之所以说分两种情况,是因为三星note3非常特别(目前只知道这一款手机这样),用一般的方法已经无法解决了
1、除三星note3外的三星手机,以及其他品牌手机的解决方案

第一步在清单文件中配置configChanges属性,使之在横竖屏切换时不重新创建生命周期
android:configChanges="orientation|keyboardHidden|screenSize"
第二步同时重写onConfigurationChanged(Configuration newConfig)方法
@Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
            Configuration o = newConfig;
            o.orientation = Configuration.ORIENTATION_PORTRAIT;
            newConfig.setTo(o);
        } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
        }
    }

这样可以完美解决除三星note3外的三星手机的回调为null的问题,关于configChanges属性以及onConfigurationChanged()方法后面会单独写一篇博客介绍,这里就不赘述了。


2、对三星note3的特殊适配(包括但不限于三星note3,因为目前只知道这一款机型)的解决方案
为什么单独适配,是因为这款机型,非常特别,按第一种方案处理后,依然会进行横竖屏切换,这时候我们只能换个思路,就是不在当前Activity中进行拍照的请求,而是新建一个专门的帮助类来进行拍照的逻辑处理,原来的回调依旧不变

if (android.os.Build.MODEL.equals("SM-N9008V")){
Intent intent = new Intent(this, PhotographAssistActivity.class);
                startActivityForResult(intent, REQUEST_SM_N9008V_CAMERA)
};
注:如上代码块,这里我是通过获取手机型号的方法来判断是不是三星note3的
代码块中的REQUEST_SM_N9008V_CAMERA参数为自定义的code
private static final int REQUEST_SM_N9008V_CAMERA = 0x03;
/**
 * 三星note3特殊适配的帮助类
 */
public class PhotographAssistActivity extends AppCompatActivity {
    private String mImageFilePath;
    public static final String IMAGE_FILEPATH = "ImageFilePath";
    public static final String IMAGE_PATH = "image_path";
    private Activity mContext;
    public int GET_IMAGE_REQ = 5000;
    private static Context applicationContext;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //判断 activity被销毁后 有没有数据被保存下来
        if (savedInstanceState != null) {
            mImageFilePath = savedInstanceState.getString(IMAGE_FILEPATH);
            Log.i("--------------", mImageFilePath);
            File mFile = new File(IMAGE_FILEPATH);
            if (mFile.exists()) {
                Intent rsl = new Intent();
                rsl.putExtra(IMAGE_PATH, mImageFilePath);
                setResult(Activity.RESULT_OK, rsl);
                Log.i("--------------", "图片拍摄成功");
                finish();
            } else {
                Log.i("--------------", "图片拍摄失败");
            }
        }
        mContext = this;
        applicationContext = getApplicationContext();
        if (savedInstanceState == null) {
            initialUI();
        }
    }

    public void initialUI() {
        //根据时间生成 后缀为  .jpg 的图片
        long ts = System.currentTimeMillis();
        mImageFilePath = getCameraPath() + ts + ".jpg";
        File out = new File(mImageFilePath);
        showCamera(out);
    }

    private void showCamera(File out) {
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(out)); // set
        startActivityForResult(intent, GET_IMAGE_REQ);
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent intent) {
        if (GET_IMAGE_REQ == requestCode && resultCode == Activity.RESULT_OK) {
            Intent rsl = new Intent();
            rsl.putExtra(IMAGE_PATH, mImageFilePath);
            mContext.setResult(Activity.RESULT_OK, rsl);
            mContext.finish();
        } else {
            mContext.finish();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putString("ImageFilePath", mImageFilePath + "");
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
    }

    public static String getCameraPath() {
        String filePath = getImageRootPath() + "/camera/";
        File file = new File(filePath);
        if (!file.isDirectory()) {
            file.mkdirs();
        }
        file = null;
        return filePath;
    }

    public static String getImageRootPath() {
        String filePath = getAppRootPath() + "/image";
        File file = new File(filePath);
        if (!file.exists()) {
            file.mkdirs();
        }
        file = null;
        return filePath;
    }

    public static String getAppRootPath() {
        String filePath = "/a";
        if (Environment.getExternalStorageState().equals(
                Environment.MEDIA_MOUNTED)) {
            filePath = Environment.getExternalStorageDirectory() + filePath;
        } else {
            filePath = applicationContext.getCacheDir() + filePath;
        }
        File file = new File(filePath);
        if (!file.exists()) {
            file.mkdirs();
        }
        file = null;
        File nomedia = new File(filePath + "/.nomedia");
        if (!nomedia.exists())
            try {
                nomedia.createNewFile();
            } catch (IOException e) {
            }
        return filePath;
    }

}

通过上述的两种方式,就可以完美解决包括三星note3在内的三星手机拍照后横竖屏切换导致的回调为null以致程序崩溃的问题。如有任何疑问,欢迎留言讨论。

你可能感兴趣的:(安卓开发进阶)