之前好好的代码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;
}
}