android调用相机api?保存图片会出现2张解决办法

seosqwseo2个月前 (08-30)测评日记30

一、问答:Android P都更新了哪些功能

Android P的新功能特性集中在了UI、通知体验、室内定位、图像存储几个方面,解决了之前一直存在的痛点。例如WiFi RTT一定程度上弥补了蜂窝网络在室内环境下的定位问题,HEIC图像格式则重点解决了存储容量问题。同时,Android P也在通知丰富度及*作便捷性等功能方面有所增强和提升。

一、WiFi RTT功能——复杂地形精确导航

WiFi RTT功能是Android P新引入的一个功能,从原理上来说与蜂窝网络的定位原理一致,但这个功能极大的弥补了蜂窝网络在室内定位的短板,WiFi RTT将能够在室内提供高精度的定位,这是蜂窝网络很难做到的。

WiFi RTT是全新的功能,在android.wifi包下增加了rtt包,用于存放WiFi RTT相关类和接口。

WiFi RTT的API以WifiRttManager为核心,借助AP热点或WiFi,利用RTT原理完成测距,通过三个以上的测距点就能够准确地定位到设备所在位置。

WiFiRTTManager提供了测距接口,是一个异步测距*作,根据官方文档()说明,其测距接口如下:

void startRanging(RangingRequest request, RangingResultCallback callback, Handler handler);

注:SDK Platforms Android P Preview Revision 1的相关接口定义与此不同,但实际的官方镜像中接口与此一致,开发者需要更新新的Android P Preview Revision 2,此版本中Google已经修正该接口。

接口中,RangingRequest通过RangingRequest.Builder构建,RangingRequest.Builder构建出RangingRequest所需要的参数可以通过WiFiManager等系统服务获取到相关的内容,如List<ScanResult> scanResults= wifiManager.getScanResults();

以下提供一个简单的测试Demo,以供参考:

private WifiRttManager wifiRttManager;

private WifiManager wifiManager;

protected void onCreate(Bundle savedInstanceState){

if(getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_RTT)){

Object service= this.getApplicationContext().getSystemService(Context.WIFI_RTT_RANGING_SERVICE);

if(service instanceof WifiRttManager){

wifiRttManager=(WifiRttManager) service;

Log.i(TAG,"Get WifiRttManager Succ.");

wifiManager=(WifiManager) this.getApplicationContext().getSystemService(Context.WIFI_SERVICE);

IntentFilter wifiFileter= new IntentFilter();

wifiFileter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);

wifiFileter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);

wifiFileter.addAction(WifiManager.SCAN_RESULTS_**AILABLE_ACTION);

registerReceiver(new WifiChangeReceiver(), wifiFileter);

wifiManager.setWifiEnabled(true);

class WifiChangeReceiver extends BroadcastReceiver{

public void onReceive(Context context, Intent intent){

if(intent.getAction().equals(WifiManager.SCAN_RESULTS_**AILABLE_ACTION)){

List<ScanResult> scanResults= wifiManager.getScanResults();

Log.i(TAG,"Wifi Scan size:"+ scanResults.size());

for(ScanResult scanResult: scanResults){

Log.i(TAG, scanResult.toString());

RangingRequest.Builder builder= new RangingRequest.Builder();

builder.addAccessPoint(scanResult);

wifiRttManager.startRanging(builder.build(), new RangingResultCallback(){

public void onRangingFailure(int i){

public void onRangingResults(List<RangingResult> list){

for(RangingResult result: list){

Log.i(TAG, result.toString());

使用WiFi RTT时,需要在AndroidManifest.xml中增加如下声明:

<uses-feature android:name="android.hardware.wifi.rtt"/>

通过上面的简单代码,就能够实现WiFi RTT的功能。

WiFi RTT功能适用于复杂地形的大型室内外场所,如商场、娱乐场所、大型休闲、游乐场等等,提供场所内的局部区域精确化导航等功能。相信在很快的时间内,就能够在各大地图应用内体验到这项便利功能,对于路痴、地图盲的伙伴们将是极大的福音。

随着iPhone X的推出,“刘海屏”达到了空前的**。Android P里提供了对异形屏幕的UI适配兼容方案,通过DisplayCutout类提供的相关接口,能够获取到屏幕中Cutout区域的信息。

借助DisplayCutout,可以获取到如下信息:

DisplayCutout displayCutout= view.getRootWindowInsets().getDisplayCutout();

Region bounds= displayCutout.getBounds();

Log.d(TAG, String.format("Bounds:%s", bounds.toString()));

int top= displayCutout.getSafeInsetTop();

int bottom= displayCutout.getSafeInsetBottom();

int left= displayCutout.getSafeInsetLeft();

int right= displayCutout.getSafeInsetRight();

Log.d(TAG, String.format("Cutout edge:[left:%d, top:%d,right:%d, bottom:%d]", left, top, right, bottom));

public Region getBounds()能够获取到Cutout区域的所有信息,Region就是Cutout区域。

public int getSafeInsetBottom()

public int getSafeInsetRight()

以上四个接口,可以获取到去除Cutout区域后的安全区域边界值。

通过上述数据,开发者能够精准的控制UI的绘制,避免将UI内容绘制到Cutout区域造成UI显示异常。

Android机器里,刘海屏目前还是极为罕见的Google为了方便开发者调试,在Android P Preview镜像中,特别提供了Cutout的支持,具体打开方式可以参考Google提供的特性说明文档cutout小节内容。

cutout小节:

如图所示,笔者使用手头的Pixel 2 XL体验了Android P的Cutout设置。

三、通知优化——*作更多样,内容更丰富

Android P在通知内容的丰富度和*作上做了优化。

近的版本中,Android系统的通知管理方面一直优化升级,Android O提供了更细粒度的Channel功能,通知栏推送时需要指定NotificationChannel,用户可以对通知的Channel选择,只允许感兴趣的Channel推送的通知显示。通过通道设置、免打扰优化等方式,极大增强了消息体验。

Android P继续改进和增强消息通知[v1]。早在Android 7.0时,就提供了在通知中直接应答和输入,Android P对这一功能做了更多的增强。

Android P的通知中支持图像内容,可以通过setData()方法,给出消息的图像内容,在通知上展示给用户。

Android P同样简化了通知的配置形式。Android P中增加了Notification.Person类,用于区分同一个对话的参与者信息,如参与者的头像、URI等。根据官方说明,Android P中,通知消息的其他一些API,也使用Person替代之前的CharSequence。

NotificationChannel channel= new NotificationChannel("WtTestChannel",

"WtTestChannel", NotificationManager.IMPORTANCE_DEFAULT);

channel.enableLights(true);// luncher icon right corner's point

channel.setLightColor(Color.RED);// read point

channel.setShowBadge(true);// whether show this channel notification on long press icon

new Notification.Builder(MainActivity.this,

Notification.Person p= new Notification.Person();

p.setUri(""+

"ui/1.2.0/pc/static/image/newLogo-16042.png");

Notification.MessagingStyle messageStyle= new Notification.MessagingStyle(p);

Notification.MessagingStyle.Message message=

new Notification.MessagingStyle.Message("WeTestMessage", 2000, p);

"");

message.setData("image/png", image);

messageStyle.addMessage(message);

builder.setStyle(messageStyle);

builder.setSmallIcon(R.mipmap.ic_launcher);

Notification notification= builder.build();

NotificationManager notifyManager=

(NotificationManager) getSystemService(

MainActivity.this.getApplicationContext().NOTIFICATION_SERVICE);

notifyManager.createNotificationChannel(channel);

notifyManager.notify("WeTest", 1, notification);

Android P中,重点做了内容丰富上的工作,同时也对Channel的设置方面做了一些简化处理。

Android O版本里,首次推出了NotificationChannel,开发者需要配置相应的Channel,才能够推送通知给用户。用户能够更加细粒度[v1]的针对App的Channel选择,而不是禁止App的所有通知内容。

而在Android P中,对通知的管理做了进一步的优化,包括可以屏蔽通道组、提供新的广播类型和新的免打扰优先级。

屏蔽通道组:用户可以在通知设置中屏蔽App的整个通道组。开发者可以通过isBlocked()来判断某个通道组是否被屏蔽了,并根据结果,不向已经被屏蔽的通道组发送任何通知。另外,开发者可以在App中使用新接口getNotificationChannelGroup()来查询当前的通道组设置。

新的广播类型:新广播类型是针对通道和通道组的功能增加的“通道(组)屏蔽状态变化”广播。开发者App中可以对所拥有的通道(组)接收广播,并根据具体广播内容作出动作。开发者可以通过NotificationManager,查看广播相关的具体信息。针对广播的动作可以通过Broadcasts查看具体的方法和信息。

免打扰优先级:NotificationManager.Policy增加了两个新的优先级常量,PRIORITY_CATEGORY_ALARMS(警告优先),PRIORITY_CATEGORY_MEDIA_SYSTEM_OTHER(媒体、系统和游戏声音优先)。

近一段时间,双摄、多摄等机型纷纷面世。双摄及多摄提供了单摄像头所无法完成的能力,如无缝缩放、散景和立体视觉。Android P在这方面也提供了系统级的API支持。

Android P提供了系统API,支持从两个或者多个物理摄像头同步获取数据流。此前OEM厂商提供的双摄设备多是厂商自行定制系统实现,此时Android P推出了API,从系统层面上制定了API规范。

新的API提供了在不同相机之间切换逻辑数据流或混合数据流的调用能力。在捕捉延迟方面,提供新的会话参数,降低初始捕捉延迟。同时,提供相机共享能力,以解决在多种使用相机的场景下重复停止、开启相机流。闪光灯方面,Android P增加基于显示的闪光灯支持。光学防抖方面,Android P向开发者提供OIS时间戳,用于图像稳定性优化以及其他特效使用。

此外,Android P还支持外部USB/UVC相机,可以使用更强大的外置摄像头模组。

Android P引入了新的ImageDecoder,该类除了支持对各种图片格式的解码、缩放、裁剪之外,其强大之处在于支持对解码后的图像做后期处理(post-process),使用该功能可以添加复杂的自定义特效,比如圆角,或是将图片放在圆形像框中。编写后期处理回调函数,你可以添加任何绘图指令实现需要的效果。

此外,Android P原生支持GIF和WebP格式的动图,新增了AnimatedImageDrawable类,并被新增的解码器类ImageDecoder直接支持,用法跟矢量动画类AnimatedVectorDrawable类似,实现方式也类似,通过新增渲染线程和工作线程,不需要在UI线程处理动图更新,可以说是无痛使用,非常省心。

下面通过编写代码,显示一张gif图,并利用后期处理机制,在图像中间绘制一个绿色的实心圆。

final ImageView image=(ImageView) findViewById(R.id.image);

File gifFile= new File("/data/local/tmp/test.gif");

Log.d(TAG,"gifFile is not exsited!");

ImageDecoder.Source source= ImageDecoder.createSource(gifFile);

d= ImageDecoder.decodeDrawable(source, new ImageDecoder.OnHeaderDecodedListener(){

public void onHeaderDecoded(ImageDecoder imageDecoder, final ImageDecoder.ImageInfo imageInfo, ImageDecoder.Source source){

imageDecoder.setPostProcessor(new PostProcessor(){

public int onPostProcess(Canvas canvas){

int w= imageInfo.getSize().getWidth();

int h= imageInfo.getSize().getHeight();

canvas.drawCircle(w/2, h/2, h/4, new Paint(paint));

image.setVisi**lity(View.VISIBLE);

Button button=(Button) findViewById(R.id.buttonText);

button.setOnClickListener(new View.OnClickListener(){

public void onClick(View view){

if(d!= null&& d instanceof AnimatedImageDrawable){

AnimatedImageDrawable ad=(AnimatedImageDrawable) d;

Android P内置了对HDR VP9和HEIF(heic)图像编码的支持。HEIF是苹果在iOS11推出的一种高效压缩格式,目前在IphoneX、Iphone 8、IPhone 8P上已经支持。该格式的压缩率更高,但是编码该格式需要硬件的支持,解码并不需要。新的支持库中的HeifWriter支持从YUV字节缓冲区、Surface或是Bitmap类转换为HEIF格式的静态图像。

Android P新引入了MediaPlayer2,支持DataSourceDesc创建的播放列表。

在前不久发布的Android 8.1(API level 27)上,Google首次在Android平台上推出了神经网络API,这意味着我们的Android机器智能化水平又提高了一大步。而本次Android P,进一步丰富了神经网络的支持,不仅对之前的相关API进行了优化,并且提供了9个新的*作,为具体的数据*作方面提供了更深入的支持。

Android 8.0(API等级26)中引入了自动填充框架,这使得在应用中填写表单变得更加容易。 Android P引入了自动填充服务并实现了多项改进,得以在填写表单时进一步增强用户体验。

Android P引入了许多新的安全功能,包括统一的指纹验证对话框和敏感交易的高确信度的用户确认。应用程序内的指纹认证UI也将会更加一致。

如果第三方APP想要使用指纹,Android系统框架为应用提供了指纹认证对话框,该功能可以提供统一的外观和使用体验,用户使用起来更放心。如果您的程序还在使用FingerprintManager,现在改用FingerprintDialog替代吧,系统来提供对话框显示。对了,在使用FingerprintDialog之前,别忘了调用hasSystemFeature()方法检查手机设备是否支持指纹。

Android P系统提供了受保护的确认API,借助这组全新的API,应用可以使用ConfirmationDialog对话框向用户提示,请求用户批准一条简短的声明,该声明允许应用提醒用户,即将完成一笔敏感交易,例如支付。

如果用户接受声明,应用将会收到一条key-hash的消息认证码(HMAC),该签名由TEE产生,以保护用于输入和认证对话框的显示。该签名表示用于已经看到了声明并同意了。

Android P还提供了StrongBox Keymaster(强力沙盒秘钥**),一个存储在硬件安全模块的具体实现。在这个硬件安全模块中有自己的CPU、安全存储空间,真随机数生成器,以及额外的机制抵御应用被篡改或是未授权应用的**加载。当检查存储在StrongBox Keymaster中的密钥时,系统通过可信执行环境(TEE)确认密钥的完整性。为了降低能耗,StrongBox支持了一组算法和不同长度的秘钥:

●HMAC-SHA256(支持8字节到64字节任意秘钥长度)

需要说明的是,这个机制需要硬件支持。

使用新的ASN.1编码的秘钥格式添加导入秘钥到Keystore,Android P提供了额外的密码解密安全能力。之后KeyMaster就可以解密KeyStore存储的秘钥,这种工作方式使得秘钥明文永远不会出现在设备内存中。这项特性要求设备支持Keymaster 4。

四、支持客户端侧Android备份加密

Android P支持使用客户端密钥对Android备份进行加密。这项隐私措施,需要设备的PIN、图案密码或标准密码才能从用户设备备份的数据中恢复数据。

为了使App使用更便捷,Android在多个方面为开发者提供了易用性的优化。

Android P在App的场景切换和*作上为开发者提供了很多的优化点。

Android P中对Section提供了新的机制,被称为accessi**lity pane titles, Accessi**lity services能够接收这些标题的变化,使得能够对一些变化提供更加细粒度的信息。

指定Section的标题,可以通过android:accessi**lityPaneTitle新属性来设置,同样运行时可以通过setAccessi**lityPaneTitle()来设置标题。

Android P提供了新的顶部栏导航机制,通过设置View实例的android:accessi**lityHeading属性为true,来显示逻辑标题。通过这些标题,用户就可以从一个标题导航到下一个标题,

针对屏幕阅读器,Android P对View提供了新的属性android:screenReaderFocusable代替原有的android:focusable来做标记,来解决在一些场景下为了使屏幕阅读器工作而设置View为可获取焦点的*作。这时,屏幕阅读器需要同时关注android:screenReaderFocusable和android:focusable设置为ture的View。

Android P中,可以使用getTooltipText()去读取tooltips的文本内容。使用新的ACTION_SHOW_TOOLTIP和ACTION_HIDE_TOOLTIP控制View显示或者隐藏tooltips。

Android P在Accessi**lityService类中提供了两个全新的*作。开发者的Service可以通过GLOBAL_ACTION_LOCK_SCREEN帮助用户锁屏,通过GLOBAL_ACTION_TAKE_SCREENSHOT帮助用户完成屏幕截图。

Android P优化了在App多窗体同步发生变化时的更新内容获取。当出现TYPE_WINDOWS_CHANGED时,开发者可以通过getWindowChanges()API获取窗体变化情况。

当多窗体发生改变时,每个窗体都会发出自己的**,开发者可以通过getSource()获取到**窗体的根View。

如果你的App为View定义了accessi**lity pane titles,UI更新时你的Service就能够识别到相应的改动。当出现TYPE_WINDOW_STATE_CHANGED**时,使用新方法 getContentChangeTypes()返回的类型,就能够获取到当前窗体的变化情况。例如,现在就能够通过上述的机制,检测到一个[v1]窗格是否有了新标题,或者一个窗格的消失。

旋转屏幕,是一些游戏、视频等场景必要的*作,但有一些场景,用户旋转屏幕并不是为了让应用显示从竖屏变成横屏或反过来。为了避免这种误*作,Android P提供了新的机制,开发者可以指定屏幕不随重力感应旋转,而是用户通过一个单独的按钮自行控制屏幕显示转向。

二、Android调用手机相机拍照***保存图片会出现2张解决办法***

1、近项目中使用系统相机拍照,保存图片,发现一些问题。

2、  读取图片旋转角度,然后再旋转回去。

3、  使用BitmapFactory.Options,能更准确的获取图片格式,

4、   判断地址末尾.gif有时候会不准确(不推荐)

5、  上传服务器,一般使用地址,但是用户手动删除图片后,地址是无效的。为了防止地址无效,可以对需要上传图片地址做保存,但又希望系统读取不到,可以对保存地址进行修改。

6、  我们可以去系统相册查看两张图片,会发现两张图片的地址是不一样的,而且两张图片的大小也不同。

7、 (1)调用系统相机,拍照完成我们会生成一个保存地址,而这个地址是:/storage/android/data/包名/Picture/,这张是我们保存的拍照图片。

8、 (2)相同的一张图片在哪?这个地址是:/storage/Pictures/,这张图片是系统**的App目录下Pictures中的图片。

9、  所以就会出现在系统相册两张图片,但两张图片大小不一致,地址不同。

10、  调用系统api,只能读取到一张,是系统**的那张,也就是/storage/Pictures/目录下的这张,但是/storage/android/data/包名/Picture/目录下的没有读取到。

11、  知道了问题,就有解决办法,可分为三种方法:

12、     保存图片的时候,修改下地址(可参照标题 3,这样让系统无法识别出这张图片),结果就是,我读取不到,系统也别想读取不到,在系统相册里也就看不到这张图片。

13、     因为api无法读取到,那我们就直接再读取/storage/android/data/包名/Picture/下的文件,把图片一块加入到同一个**中用于展示,这样所有的图片都有了,但是系统相册中还是有两张图片,为解决这个问题。

14、     在我们保存图片的时候,直接保存到/storage/Pictures/这个目录下,也不用系统帮我们**了,这样就只会出现一张,而且我们也能调用api直接读取到,两个问题全都解决了,完美!

15、(如果以上有错误或者有更优美的方式,感谢指出并改之,与君共勉)

16、这是我项目中出现的问题,希望能够帮助到你,Thanks,Bye!

三、如何解决Android7.0及以上的权限崩溃问题

话说自从google出来Android 7.0系统之后,我们公司的测试小伙伴就向我提出了7.0的bug,接下来就着手查阅了下问题是出在哪里的,该如何来解决呢。

android.os.FileUriExposedException: exposed beyond app through Intent.getData()

at android.os.StrictMode.onFileUriExposed(StrictMode.java:1816)

at android.Uri.checkFileUriExposed(Uri.java:2350)

at android.content.Intent.prepareToLeaveProcess(Intent.java:9076)

at android.content.Intent.prepareToLeaveProcess(Intent.java:9037)

at android.app.Instrumentation.execStartActivity(Instrumentation.java:1530)

at android.app.Activity.startActivityForResult(Activity.java:4391)

at android.support.v4.app.BaseFragmentActivityJB.startActivityForResult(BaseFragmentActivityJB.java)

at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java)

at android.app.Activity.startActivityForResult(Activity.java:4335)

at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java)

at android.app.Activity.startActivity(Activity.java:4697)

at android.app.Activity.startActivity(Activity.java:4665)

at com.ijuyin.prints.news.utils.VersionUtils$1.handleMessage(VersionUtils.java)

at android.os.Handler.dispatchMessage(Handler.java:105)

at android.os.Looper.loop(Looper.java:156)

at android.app.ActivityThread.main(ActivityThread.java:6524)

at java.lang.reflect.Method.invoke(Method.java)

at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:941)

at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:831)

也就是说是在什么情况下会出现呢?

2、是在写入文件的时候,在我这里是强制升级后**完成安装Apk时;

关于FileUriExposedException异常的描述是这样子的:

针对于权限部分,Android7.0是google推出的对权限做了一个更新即不允许出现以file://的形式调用隐式APP系统,也就是说以前呢,Uri的获取方式是以的样式来,那么我们也就是通过Uri.fromFile()来获取如今放在7.0及以上系统呢,这样子就不行啦;

如今的解决关键在哪里呢,需要在应用间共享文件,也就是需要发送一项content://URI,并授予 URI临时访问权限。进行此授权的简单方式是使用FileProvider类。

1、首先我们需要在AndroidManifest中的application下添加provider:

<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android=""

xmlns:tools=""

package="com.ijuyin.prints.news">

android:name="com.ijuyin.prints.news.base.BaseApplication"

android:hardwareAccelerated="true"

android:icon="@mipmap/ic_launcher"

android:label="@string/text_app_name"

android:theme="@style/AppTheme"

android:fullBackupContent="false">

android:name="android.support.v4.content.FileProvider"

android:authorities="com.ijuyin.prints.news.provider"

android:grantUriPermissions="true">

android:name="android.support.FILE_PROVIDER_PATHS"

android:resource="@xml/file_paths"/>

在这里我们需要注意一下其中设置的各种属性的含义:

authorities:是该项目的包名+provider

grantUriPermissions:必须是true,表示授予 URI临时访问权限

resource:中的@xml/file_paths是我们接下来要在资源文件目录下添加的文件

2、在res目录下新建一个xml文件夹,并且新建一个file_paths的xml文件

3、打开file_paths.xml文件添加如下内容

<?xml version="1.0" encoding="utf-8"?>

path="Android/data/com.ijuyin.prints.news/"/>

path:需要临时授权访问的路径(.代表在相机调用时候访问的是所有路径,而文件写入时访问的路径是Android/data/com.ijuyin.prints.news/)

name:是你为设置的这个访问路径起的名字

4、接下来便是修改适配Android 7.0及以上系统的代码

private void showCameraAction(){

if(ContextCompat.checkSelfPermission(getContext(), Manifest.permission

.WRITE_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED){

requestPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE,

getString(R.string.mis_permission_rationale_write_storage),

REQUEST_STORAGE_WRITE_ACCESS_PERMISSION);

Intent intent= new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

if(intent.resolveActivity(getActivity().getPackageManager())!= null){

mTmpFile= FileUtils.createTmpFile(getActivity());

if(mTmpFile!= null&& mTmpFile.exists()){

if(Build.VERSION.SDK_INT>= Build.VERSION_CODES.M){

String authority= getActivity().getPackageName()+".provider";

imageUri= FileProvider.getUriForFile(getActivity(), authority, mTmpFile);

imageUri= Uri.fromFile(mTmpFile);

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);

startActivityForResult(intent, REQUEST_CAMERA);

Toast.makeText(getActivity(), R.string.mis_error_image_not_exist, Toast

Toast.makeText(getActivity(), R.string.mis_msg_no_camera, Toast.LENGTH_SHORT)

第二部分是对文件写入模块的代码修改

private static Handler mHandler= new Handler(){

public void handleMessage(Message msg){

mProgress.setProgress(progress);

} else if(msg.what== DOWN_OVER){

if(null!= downloadDialog&& downloadDialog.isShowing()){

File apkfile= new File(apkPath);

Intent intent= new Intent(Intent.ACTION_VIEW);

if(Build.VERSION.SDK_INT>= Build.VERSION_CODES.N){

intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

String authority= mContext.getPackageName()+".provider";

Uri contentUri= FileProvider.getUriForFile(mContext, authority, apkfile);

intent.setDataAndType(contentUri,"application/vnd.android.package-archive");

intent.setDataAndType(Uri.fromFile(apkfile),"application/vnd.android"+

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

mContext.startActivity(intent);

首先我们对Android系统的型号做出判断

添加flags,表明我们要被授予什么样的临时权限

以前我们直接 Uri.fromFile(apkFile)构建出一个Uri,现在我们使用FileProvider.getUriForFile(getActivity(), getActivity().getPackageName()+".provider", mTmpFile);

其中getActivity().getPackageName()指的是该项目的应用包名(此处调用的是在fragment,所以使用的是getActivity())

通过以上4步的设置*作,就可以完全解决android 7.0及以上权限问题导致的崩溃问题。

相关文章

皓丽智能会议平板电视触摸触屏电视企业版75英寸4K智能办公投影触屏一体机质量测评好不好

皓丽智能会议平板电视触摸触屏电视企业版75英寸4K智能办公投影触屏一体机质量测评好不好

很多小伙伴在关注皓丽智能会议平板电视触摸触屏电视企业版75英寸4K智能办公投影触屏一体机怎么样?质量好不好?使用测评如何?本文综合已购用户的客观使用分享和相应的优惠信息,为...

小米(MI)小米电视EA70英寸4K超高清语音遥控网络智能平板电视机内置小爱图文测评

小米(MI)小米电视EA70英寸4K超高清语音遥控网络智能平板电视机内置小爱图文测评

很多小伙伴在关注小米(MI)小米电视EA70英寸4K超高清语音遥控网络智能平板电视机内置小爱怎么样?质量好不好?使用测评如何?本文综合已购用户的客观使用分享和相应的优惠信息...

小米(MI)电视55英寸4K超高清液晶屏智能WiFi网络彩色平板电视机卧室客厅家用彩电质量测评好不好

小米(MI)电视55英寸4K超高清液晶屏智能WiFi网络彩色平板电视机卧室客厅家用彩电质量测评好不好

很多小伙伴在关注小米(MI)电视55英寸4K超高清液晶屏智能WiFi网络彩色平板电视机卧室客厅家用彩电怎么样?质量好不好?使用测评如何?本文综合已购用户的客观使用分享和相应...

Vidda海信电视X85使用感受如何

Vidda海信电视X85使用感受如何

很多小伙伴在关注Vidda海信电视X85怎么样?质量好不好?使用测评如何?本文综合已购用户的客观使用分享和相应的优惠信息,为大家推荐一款高性价比的产品,一起来看看吧。...

闪魔苹果手表膜apple质量怎么样

闪魔苹果手表膜apple质量怎么样

很多小伙伴在关注闪魔苹果手表膜apple怎么样?质量好不好?使用测评如何?本文综合已购用户的客观使用分享和相应的优惠信息,为大家推荐一款高性价比的产品,一起来看看吧。...

阿尔法蛋超能蛋智能机器人中英学习启蒙早教机好不好用

阿尔法蛋超能蛋智能机器人中英学习启蒙早教机好不好用

很多小伙伴在关注阿尔法蛋超能蛋智能机器人中英学习启蒙早教机怎么样?质量好不好?使用测评如何?本文综合已购用户的客观使用分享和相应的优惠信息,为大家推荐一款高性价比的产品,一...