最近对以前的Android项目进行开发时,因为新的平板Android中系统版本为10,将旧项目的Android API升级为26。然后旧代码中的拍照权限失效,经过查询资料,发现权限并未打开,因此需要提醒用户,手动打开权限。

    // 拍照的requestCode
private static final int CAMERA_REQUEST_CODE = 0x00000010;
// 申请相机权限的requestCode
private static final int PERMISSION_CAMERA_REQUEST_CODE = 0x00000012;/*** 检查权限并拍照。* 调用相机前先检查权限。*/
private void checkPermissionAndCamera() {int hasCameraPermission = ContextCompat.checkSelfPermission(getApplication(),Manifest.permission.CAMERA);if (hasCameraPermission == PackageManager.PERMISSION_GRANTED) {//有权限,调起相机拍照。openCamera();} else {//没有权限,申请权限。ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.CAMERA},PERMISSION_CAMERA_REQUEST_CODE);}
}/*** 处理权限申请的回调。** @param requestCode* @param permissions* @param grantResults*/
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {if (requestCode == PERMISSION_CAMERA_REQUEST_CODE) {if (grantResults.length > 0&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {//允许权限,有调起相机拍照。openCamera();} else {//拒绝权限,弹出提示框。Toast.makeText(this,"拍照权限被拒绝",Toast.LENGTH_LONG).show();}}
}/*** 调起相机拍照*/
private void openCamera() {Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);// 判断是否有相机if (captureIntent.resolveActivity(getPackageManager()) != null) {File photoFile = null;Uri photoUri = null;if (isAndroidQ) {// 适配android 10photoUri = createImageUri();} else {try {photoFile = createImageFile();} catch (IOException e) {e.printStackTrace();}if (photoFile != null) {mCameraImagePath = photoFile.getAbsolutePath();if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {//适配Android 7.0文件权限,通过FileProvider创建一个content类型的UriphotoUri = FileProvider.getUriForFile(this, getPackageName() + ".fileprovider", photoFile);} else {photoUri = Uri.fromFile(photoFile);}}}mCameraUri = photoUri;if(mCameraUri == null)Log.e("Test", "mCameraUri 获取为空");elseLog.e("Test", "mCameraUri 获取不为空");if (photoUri != null) {captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);captureIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);captureIntent.putExtra(MediaStore.EXTRA_SCREEN_ORIENTATION, ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);try {startActivityForResult(captureIntent, CAMERA_REQUEST_CODE);}catch (Exception e){System.out.println(e.getMessage());sendMsg(handler,error,e.getMessage());}}}
}/*** 创建图片地址uri,用于保存拍照后的照片 Android 10以后使用这种方法** @return 图片的uri*/
private Uri createImageUri() {String status = Environment.getExternalStorageState();// 判断是否有SD卡,优先使用SD卡存储,当没有SD卡时使用手机存储if (status.equals(Environment.MEDIA_MOUNTED)) {return getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, new ContentValues());} else {return getContentResolver().insert(MediaStore.Images.Media.INTERNAL_CONTENT_URI, new ContentValues());}
}/*** 创建保存图片的文件* @return* @throws IOException*/
private File createImageFile() throws IOException {String imageName = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date());File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);if (!storageDir.exists()) {storageDir.mkdir();}File tempFile = new File(storageDir, imageName);if (!Environment.MEDIA_MOUNTED.equals(EnvironmentCompat.getStorageState(tempFile))) {return null;}return tempFile;
}

相机拍照成功后的处理

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);switch (requestCode) {case CAMERA_REQUEST_CODE:if (resultCode == RESULT_OK) {if (isAndroidQ) {imgPhoto.setImageURI(mCameraUri);//imgPhoto 为界面中ImageView控件} else {// 使用图片路径加载imgPhoto.setImageBitmap(BitmapFactory.decodeFile(mCameraImagePath));}} else {Toast.makeText(this,"取消",Toast.LENGTH_LONG).show();}break;}
}

至此,已经可以成功调用相机进行拍照。但是在程序的测试过程中,发现并非每次都能够将照片展示出来,且伴随着程序的崩溃,但本地却以将照片存储。且在Android Studio中并未爆出错误,同过不断的进行Log日志的输出,发现mCameraUri有时会null。在Logcat中也无法捕获程序异常。但在每次调用相机时,可看到Logcat中线程标注为DEAD。通过网络查询资料(Android onSaveInstanceState()和onRestoreInstanceState()调用时机_此去正年少的博客-CSDN博客_onsaveinstancestate),发现是Activity被回收导致mCameraUri置为空。

根据资料可得:

总结下,onSaveInstanceState(Bundle outState)会在以下情况被调用:
1、当用户按下HOME键时。
2、从最近应用中选择运行其他的程序时。
3、按下电源按键(关闭屏幕显示)时。
4、从当前activity启动一个新的activity时。
5、屏幕方向切换时(无论竖屏切横屏还是横屏切竖屏都会调用)。

本项目将布局一直固定为横屏,在调用相机时,相机方向可横屏或竖屏,会触发上述第五种情况。

因此在当前Activity中重写 onSaveInstanceState()与 onRestoreInstanceState()两个方法即可。

@Override
protected void onSaveInstanceState(Bundle outState) {super.onSaveInstanceState(outState);String imgUri= mCameraUri.toString();outState.putString("imgUri",imgUri);
}@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {if (savedInstanceState!=null){String imgUri=savedInstanceState.getString("imgUri");mCameraUri = Uri.parse(imgUri);}
}

同样,网上还有一种解决方案,是针对Activity没有被回收,但是成员变量被回收的情况,解决方案为重写onRestoreInstanceState()方法,暂时未遇到,先留存记录。

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {if (mCameraUri == null) {String imgUri=savedInstanceState.getString("imgUri");mCameraUri = Uri.parse(imgUri);}super.onRestoreInstanceState(savedInstanceState);
}

Android 10调用相机拍照相关推荐

  1. android 调用相机拍照。适配到 Android 10

    Photograph 项目地址:donkingliang/Photograph 简介: android 调用相机拍照.适配到 Android 10 更多:作者   提 Bug 标签: android ...

  2. android intent拍照,Android通过Intent方式调用相机拍照取得图片

    Android通过Intent方式调用相机拍照取得图片 AndroidManifest.XML 权限设置: XML布局设置: 代码: public classMainActivityextendsAp ...

  3. Android调用相机拍照高清原图(兼容7.0)

    在安卓更新7.0的版本后,要调用相机拍照获取原图则需要先把拍摄后的内容保存到目录,然后再借助provider调出来显示,相比以前可以说十分繁琐,但为了摆脱马赛克画质的困扰,为了更好的用户体验,还是硬着 ...

  4. Android 调用相机拍照并保存

    不知不觉已经两年多已经没有写文章了,转眼间大学都要毕业了,也是有些唏嘘,今后会定期发表些文章,应该会以Android为主,也会夹杂其他领域的一些文章. 话不多说,今天做了一个小demo,就是调用相机拍 ...

  5. Android中拍照完就给图片加水印,Android调用相机拍照并添加水印

    最近项目提出新需求,要求在拍照后在图片上添加用户信息的水印,so,楼主重新整理封装了一个简单的拍照+水印的工具类,需求不同,仅供参考.文件操作及权限做了适配,支持androidN及以上版本,放心使用. ...

  6. 安卓系统android使用C# .NET Xamarin框架调用相机拍照

    安卓系统android使用C# .NET Xamarin框架调用相机拍照 引言 一.用到的软件.包 二.创建Android应用(Xamarin), 三.增加Nuget中库Xam.Plugin.Medi ...

  7. Android调用相机拍照并添加水印

    最近项目提出新需求,要求在拍照后在图片上添加用户信息的水印,so,楼主重新整理封装了一个简单的拍照+水印的工具类,需求不同,仅供参考.文件操作及权限做了适配,支持androidN及以上版本,放心使用. ...

  8. Android开发之调用相机拍照与本地图库选择图片

    引用链接 Android开发之调用相机拍照与本地图库选择图片 Android调用相机实现拍照功能 部分截图 引言 小项目有一个访问相册的需求,在网上查找得到两位大神博客指点,但博客发布时间过旧,难免因 ...

  9. Java乔晓松-android中调用系统拍照功能并显示拍照的图片

    android中调用系统拍照功能并显示拍照的图片 如果你是拍照完,利用onActivityResult获取data数据,把data数据转换成Bitmap数据,这样获取到的图片,是拍照的照片的缩略图 代 ...

最新文章

  1. hdu 2879【留坑】
  2. Erlang vs Java memory architecture (zz)
  3. ML之LiRDNNEL:基于skflow的LiR、DNN、sklearn的RF对Boston(波士顿房价)数据集进行回归预测(房价)
  4. hibernate教程--抓取策略
  5. iPhone 7卖点不多出货量下降?剧透分析师又发报告
  6. 关于PHP数组方法array_walk的疑问
  7. Spring源码学习的初步体会
  8. 论文 参考文献的格式说明
  9. android将项目添加到github,将github库作为依赖添加到Android-Studio项目中
  10. BZOJ4700: 适者
  11. Linux操作Oracle(3)——Oracle OPatch打补丁遇到问题详细汇总详细记录
  12. spin_lock amp; mutex_lock的差别?
  13. 关注的开源项目-博客搬家工具
  14. 关于删除 srvinstw安装的服务
  15. IBM Watson:好的AI能够在方方面面推动人类文明的发展
  16. Firefox火狐浏览器怎么设置中文 火狐浏览器语言设置方法
  17. 电脑网线水晶头接法图解
  18. 八皇后算法带给我们的启示吧
  19. 小米蓝牙广播数据解析(MiBeacon)
  20. 论文中出现的 cf. i.e. s.t. e.g. w.r.t. et al. etc等英文缩写是什么意思

热门文章

  1. QT中$$PWD的意思
  2. 华硕m80微型计算机,小就不能满足你了?华硕M80迷你台式机评测
  3. 微信api调用限制,45009 reach max api daily quota limit 解决方法
  4. 这车模,就一个字:小巧灵动
  5. 怎么设计出来的网站才更好看
  6. 《Python黑帽子:黑客与渗透测试编程之道》 Scapy:网络的掌控者
  7. android广播不同app,用广播(Broadcast)实现不同app之间的通信
  8. rss源_如何在Windows桌面上显示RSS源
  9. 博客优化 搜索SEO优化 提高搜索量
  10. DELL XPS15 9570 32GB内存升级记