之前好好的代码6.0以前都没事,但是在7.0手机调系统相机拍照就崩溃了,查看7.0系统权限问题,网上收罗许久,

发现解决方案:

1、(推荐)7.0之后你的app就算有权限,给出一个URI之后手机也认为你没有权限。
不用修改原有代码,在Application的oncreate方法中:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
    StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
    StrictMode.setVmPolicy(builder.build());
}



2、在调用相机的时候添加7.0系统的判断,


/*获取当前系统的android版本号*/
int currentapiVersion = android.os.Build.VERSION.SDK_INT;
Log.e("currentapiVersion","currentapiVersion====>"+currentapiVersion);
if (currentapiVersion<24){
    intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(pathFile));
    startActivityForResult(intent, TAKE_PICTURE);
}else {
    ContentValues contentValues = new ContentValues(1);
    contentValues.put(MediaStore.Images.Media.DATA, pathFile.getAbsolutePath());
    Uri uri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,contentValues);
    intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
    startActivityForResult(intent, TAKE_PICTURE);}


另外给大家推荐一个轻量级Android照片处理框架 TakePhoto-TakePhoto是一款用于在Android设备上获取照片(拍照或从相册、文件中选择)、裁剪图片、压缩图片的开源工具库,目前最新版本4.0.3。 3.0以下版本及API说明,详见TakePhoto2.0+。

导包

compile 'com.jph.takephoto:takephoto_library:4.0.3'




源码地址:https://github.com/crazycodeboy/TakePhoto

支持通过相机拍照获取图片
支持从相册选择图片
支持从文件选择图片
支持批量图片选取
支持图片压缩以及批量图片压缩
支持图片裁切以及批量图片裁切
支持照片旋转角度自动纠正
支持自动权限管理(无需关心SD卡及摄像头权限等问题)
支持对裁剪及压缩参数个性化配置
提供自带裁剪工具(可选)
支持智能选取及裁剪异常处理
支持因拍照Activity被回收后的自动恢复
支持Android7.0
+支持多种压缩工具
+支持多种图片选择工具

使用TakePhoto有以下两种方式:

方式一:通过继承的方式

继承TakePhotoActivity、TakePhotoFragmentActivity、TakePhotoFragment三者之一。
通过getTakePhoto()获取TakePhoto实例进行相关操作。
重写以下方法获取结果
void takeSuccess(TResult result);
void takeFail(TResult result,String msg);
void takeCancel();
此方式使用简单,满足的大部分的使用需求,具体使用详见simple。如果通过继承的方式无法满足实际项目的使用,可以通过下面介绍的方式。

方式二:通过组装的方式

可参照:TakePhotoActivity,以下为主要步骤:

1.实现TakePhoto.TakeResultListener,InvokeListener接口。

2.在 onCreate,onActivityResult,onSaveInstanceState方法中调用TakePhoto对用的方法。

3.重写onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults),添加如下代码。

@Override
 public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
 super.onRequestPermissionsResult(requestCode, permissions, grantResults);
 //以下代码为处理Android6.0、7.0动态权限所需
 TPermissionType type=PermissionManager.onRequestPermissionsResult(requestCode,permissions,grantResults);
 PermissionManager.handlePermissionsResult(this,type,invokeParam,this);
 }


4.重写TPermissionType invoke(InvokeParam invokeParam)方法,添加如下代码:

@Override
 public TPermissionType invoke(InvokeParam invokeParam) {
 TPermissionType type=PermissionManager.checkPermission(TContextWrap.of(this),invokeParam.getMethod());
 if(TPermissionType.WAIT.equals(type)){
 this.invokeParam=invokeParam;
 }
 return type;
 }


5.添加如下代码获取TakePhoto实例:

/**
 * 获取TakePhoto实例
 * @return
 */
 public TakePhoto getTakePhoto(){
 if (takePhoto==null){
 takePhoto= (TakePhoto) TakePhotoInvocationHandler.of(this).bind(new TakePhotoImpl(this,this));
 }
 return takePhoto;
 }

下面贴一个我使用的类,详情去源码链接

import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.support.annotation.RequiresApi;
import android.view.KeyEvent;
import android.view.View;
import android.webkit.JavascriptInterface;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;

import com.jph.takephoto.app.TakePhoto;
import com.jph.takephoto.app.TakePhotoImpl;
import com.jph.takephoto.compress.CompressConfig;
import com.jph.takephoto.model.InvokeParam;
import com.jph.takephoto.model.LubanOptions;
import com.jph.takephoto.model.TContextWrap;
import com.jph.takephoto.model.TResult;
import com.jph.takephoto.model.TakePhotoOptions;
import com.jph.takephoto.permission.InvokeListener;
import com.jph.takephoto.permission.PermissionManager;
import com.jph.takephoto.permission.TakePhotoInvocationHandler;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.File;

public class StartScanActivity extends BaseActivity implements TakePhoto.TakeResultListener, InvokeListener {
    @ViewInject(id = R.id.webView)
    TinyWebView webView;
    @ViewInject(id = R.id.rl_content)
    RelativeLayout rl_content;
    @ViewInject(id = R.id.progress)
    LinearLayout progress;
    @ViewInject(id = R.id.top_layout)
    RelativeLayout top_layout;
    @ViewInject(id = R.id.top_left)
    LinearLayout top_left;
    private int index = -1;
    private String url = "", titled = "";
    private MyHandler handler;
    private static final int MSG_AUTH_SHOW = 1;
    //---------------------------------------
    private TakePhoto takePhoto;
    private InvokeParam invokeParam;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_start_scan);
        initViewd();
        getTakePhoto().onCreate(savedInstanceState);
        handler = new MyHandler();
    }

    @OnClick(R.id.top_left)
    void onlick(View v) {
        switch (v.getId()) {
            case R.id.top_left:
                StartScanActivity.this.finish();
                break;
        }
    }

    public void initViewd() {
        Bundle bd = getIntent().getExtras();
        if (bd != null) {
            url = bd.getString("url");
            titled = bd.getString("title");
        }
//        getWindow().setFlags(
//                WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
//                WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
        //---------------
        WebSettings settings = webView.getSettings();
        settings.setAppCacheEnabled(true);
        settings.setAppCacheMaxSize(1024 * 1024 * 8);
        String appCachePath = this.getCacheDir().getAbsolutePath();
        settings.setAppCachePath(appCachePath);
        settings.setJavaScriptEnabled(true);
        settings.setUseWideViewPort(true);
        settings.setLoadWithOverviewMode(true);
        settings.setAppCacheEnabled(true);
        settings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);
        settings.setSupportZoom(false);
        if (Build.VERSION.SDK_INT >=Build.VERSION_CODES.KITKAT){
            WebView.setWebContentsDebuggingEnabled(true);
        }
        settings.setAllowFileAccess(true);
        settings.setDomStorageEnabled(true);
//        settings.setDefaultTextEncodingName("utf-8");
//        settings.setRenderPriority(WebSettings.RenderPriority.HIGH);
        webView.addJavascriptInterface(new CourseList(), "NativeBridge");
//        webView.setWebChromeClient(new ChromeClient());
        webView.loadUrl("file:///android_asset/index.html");
        webView.setWebViewClient(new PicClient());
    }


    public final class CourseList {
        @JavascriptInterface
        public void scancode(String s) {
            if (StartScanActivity.this instanceof org.aisen.android.ui.activity.basic.BaseActivity) {
                org.aisen.android.ui.activity.basic.BaseActivity aisenBaseActivity = (org.aisen.android.ui.activity.basic.BaseActivity) StartScanActivity.this;
                new IAction(aisenBaseActivity, new CameraPermissionAction(aisenBaseActivity, null)) {
                    @Override
                    public void doAction() {
                        Intent intent = new Intent(StartScanActivity.this, CaptureActivity.class);
                        startActivityForResult(intent, 12);
                    }
                }.run();
            }
        }

        @JavascriptInterface
        public void imagePicker(String s) {
            String type = "";
            try {
                JSONObject obj = new JSONObject(s);
                type = obj.getString("type");

            } catch (JSONException e) {
                e.printStackTrace();
            }

            File file = new File(Environment.getExternalStorageDirectory(), "/temp/" + System.currentTimeMillis() + ".jpg");
            if (!file.getParentFile().exists()) file.getParentFile().mkdirs();
            CompressConfig config;
            LubanOptions option = new LubanOptions.Builder()
                    .setMaxHeight(1000)
                    .setMaxWidth(1000)
                    .setMaxSize(512)
                    .create();
            config = CompressConfig.ofLuban(option);
            config.enableReserveRaw(false);
            takePhoto.onEnableCompress(config, false);
            TakePhotoOptions.Builder builder = new TakePhotoOptions.Builder();
            builder.setWithOwnGallery(true);
            builder.setCorrectImage(true);//纠正角度
            takePhoto.setTakePhotoOptions(builder.create());

            if (type.equals("takePhoto")) {
                takePhoto.onPickFromCapture(FileUtil.geturi());//相机不裁剪
            } else {
                takePhoto.onPickFromGallery();//不裁剪
            }
        }

        @JavascriptInterface
        public void colseDlb(String s) {
            Intent intent = new Intent(StartScanActivity.this, MainActivity.class);
            startActivity(intent);
        }

        @JavascriptInterface
        public void renderFinish(String s) {
            Message msg = new Message();
            msg.what = MSG_AUTH_SHOW;
            handler.sendMessage(msg);
        }


        //分享
        @JavascriptInterface
        public void shareToWechat(String s) {
            String title = "", image = "", url = "", scene = "";
            try {
                JSONObject obj = new JSONObject(s);
                title = obj.getString("title");
                image = obj.getString("image");
                url = obj.getString("url");
                scene = obj.getString("scene");

            } catch (JSONException e) {
                e.printStackTrace();
            }
            if (scene.equals("SESSION")) {//好有
                ShareUtil.showShare(StartScanActivity.this, Wechat.NAME, title, "", url, image);
            } else {//朋友圈
                ShareUtil.showShare(StartScanActivity.this, WechatMoments.NAME, title, "", url, image);
            }
        }

        @JavascriptInterface
        public void nextPageDlb(String s) {
            String title = "", image = "", url = "";
            try {
                JSONObject obj = new JSONObject(s);
                title = obj.getString("title");
                url = obj.getString("url");
            } catch (JSONException e) {
                e.printStackTrace();
            }
            if(url.endsWith("pdf")){
                Intent intent = new Intent(StartScanActivity.this, ReadPdfActivity.class);
                intent.putExtra("title", title);
                intent.putExtra("url", url);
                startActivity(intent);
            }else {
                Intent intent = new Intent(StartScanActivity.this, ShopWebActivity.class);
                intent.putExtra("title", title);
                intent.putExtra("url", url);
                startActivity(intent);
            }
        }
    }

    @Override
    public void onPause() {
        super.onPause();
        // 加载空白页
    }

    @Override
    public void onResume() {
//        initViewd();
        super.onResume();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (webView != null) {
            rl_content.removeView(webView);
            webView.clearCache(true);
            webView.removeAllViews();
            webView.destroy();
            webView = null;
        }
    }

    private class PicClient extends WebViewClient {
        @Override
        public void onPageStarted(WebView view, String url, Bitmap favicon) {
            super.onPageStarted(view, url, favicon);
            progress.setVisibility(View.VISIBLE);
        }

        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            if (url != null) view.loadUrl(url);
            return true;
        }

        @Override
        public void onPageFinished(WebView view, String url) {
            super.onPageFinished(view, url);
        }
    }
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent keyEvent) {
        if (keyCode == keyEvent.KEYCODE_BACK) {
            if (webView.canGoBack()) {
                webView.goBack();
                return true;
            } else {
                Intent intent = new Intent(StartScanActivity.this, MainActivity.class);
                startActivity(intent);
            }
        }
        return super.onKeyDown(keyCode, keyEvent);
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        getTakePhoto().onActivityResult(requestCode, resultCode, data);
        //--------------
        if (requestCode == 12) {
            if (data == null) {
                return;
            }
            String result = data.getExtras().getString("result");//得到新Activity关闭后返回的数据
             String url = "javascript:$app.$store.dispatch('nativeCallJs',{fnname:'scancode',param:" + "'" + result + "'" + "})";
            webView.loadUrl(url);
        }
        super.onActivityResult(requestCode, resultCode, data);
    }

    @Override
    public void finish() {
        // TODO Auto-generated method stub
        moveTaskToBack(true);
        Intent intent = new Intent(StartScanActivity.this, MainActivity.class);
        startActivity(intent);
    }


    class MyHandler extends Handler {
        public MyHandler() {
        }

        public MyHandler(Looper L) {
            super(L);
        }

        // 子类必须重写此方法,接受数据
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_AUTH_SHOW: {
                    progress.setVisibility(View.GONE);
                    top_layout.setVisibility(View.GONE);
                }
                break;
            }
        }
    }

    //---------------------
    @Override
    protected void onSaveInstanceState(Bundle outState) {
        getTakePhoto().onSaveInstanceState(outState);
        super.onSaveInstanceState(outState);
    }

    @Override
    public void takeSuccess(TResult result) {
        Bitmap bitmap = FileUtil.getbtm(result.getImage().getCompressPath());
        if (bitmap != null) {
        final  String url = "javascript:$app.$store.dispatch('nativeCallJs',{fnname:'pictureBase64',param:" + "'" + "data:image/jpg;base64," + Base64Utils.bitmapToBase64(bitmap) + "'" + "})";
        StartScanActivity.this.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                webView.loadUrl(url);
            }
        });
        }
    }

    @Override
    public void takeFail(TResult result, String msg) {

    }

    @Override
    public void takeCancel() {

    }

    @Override
    public PermissionManager.TPermissionType invoke(InvokeParam invokeParam) {
        PermissionManager.TPermissionType type = PermissionManager.checkPermission(TContextWrap.of(this), invokeParam.getMethod());
        if (PermissionManager.TPermissionType.WAIT.equals(type)) {
            this.invokeParam = invokeParam;
        }
        return type;
    }


    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        PermissionManager.TPermissionType type = PermissionManager.onRequestPermissionsResult(requestCode, permissions, grantResults);
        PermissionManager.handlePermissionsResult(this, type, invokeParam, this);
    }

    /**
     * 获取TakePhoto实例
     *
     * @return
     */
    public TakePhoto getTakePhoto() {
        if (takePhoto == null) {
            takePhoto = (TakePhoto) TakePhotoInvocationHandler.of(this).bind(new TakePhotoImpl(this, this));

        }
        return takePhoto;
    }

}