有五子棋入门指南了,有必要再入kf6吗

后使用快捷导航没有帐号?
查看: 7619|回复: 23
TA的每日心情开心4&小时前签到天数: 97 天[LV.6]常住居民II主题帖子积分
地狱级, 积分 2951, 距离下一级还需 49 积分
地狱级, 积分 2951, 距离下一级还需 49 积分
部落币2398
有谁天了刚出的SXK版本kf6&&具体说下感受& &最好和五子棋作下对比&&谢谢
转载请注明文字来源蒸汽部落论坛!
TA的每日心情开心5&小时前签到天数: 225 天[LV.7]常住居民III主题帖子积分
部落币8884
TA的每日心情开心 08:30签到天数: 226 天[LV.7]常住居民III主题帖子积分
神, 积分 4970, 距离下一级还需 4030 积分
神, 积分 4970, 距离下一级还需 4030 积分
部落币1043
TA的每日心情开心4&小时前签到天数: 238 天[LV.7]常住居民III主题帖子积分
部落币9177
有帖子说过,你自己搜索帖子
TA的每日心情郁闷3&小时前签到天数: 307 天[LV.8]以坛为家I主题帖子积分
部落币12211
你去看027的视频吧
TA的每日心情开心8&小时前签到天数: 702 天[LV.9]以坛为家II主题帖子积分
部落币13026
我对测评真心信不过 看测评主要就是看看结构 啥玩意都说的跟神器似的
TA的每日心情开心7&小时前签到天数: 252 天[LV.8]以坛为家I主题帖子积分
渣渣小白一枚
神, 积分 6494, 距离下一级还需 2506 积分
神, 积分 6494, 距离下一级还需 2506 积分
部落币2206
TA的每日心情开心13&小时前签到天数: 721 天[LV.9]以坛为家II主题帖子积分
神, 积分 7572, 距离下一级还需 1428 积分
神, 积分 7572, 距离下一级还需 1428 积分
部落币5975
我用了一周多了,什么解析度层次感啥的说不出来,没大神们那舌头,操作肯定比五子棋方便,上丝加油都方便,口感上比五子棋稍淡那么一点,柔和一些,还是很不错,值得入一个。
TA的每日心情开心 09:12签到天数: 78 天[LV.6]常住居民II主题帖子积分
神, 积分 3171, 距离下一级还需 5829 积分
神, 积分 3171, 距离下一级还需 5829 积分
部落币2402
有钱就入个 呵呵。
TA的每日心情开心8&小时前签到天数: 180 天[LV.7]常住居民III主题帖子积分
神, 积分 4956, 距离下一级还需 4044 积分
神, 积分 4956, 距离下一级还需 4044 积分
部落币3537
人争一口气 佛蒸一炉香
注册账号后积极发帖的会员
经常参与各类话题的讨论,发帖内容较有主见
经常帮助其他会员答疑
北京艾维普科技有限公司正在初始化报价器有哪位了解现在有苹果6吗3个回答严合乐1.单手持时,大拇指可以轻松抵达屏幕右上角和右下角,所以ios里右边的按钮可以轻松操作。
2.单手持握iphone6时,大小刚好。把手机硬塞进手里,大拇指和中指/无名指还能有接触。能达到这种姿势,就可以保证在大拇指从屏幕最左边往右划,进行返回上一页操作时,中指和无名指还能卡住手机,保持对手机的控制。这一点很重要,因为iphone没有实体的返回键,返回就成了单手操作的大问题。使用证明4.7的iphone还是能单手操作的。只是要伸直大拇指!
3.输入法每个字母都变大了,全键盘下变得更好按了。但是,由于目前的输入法都是把候选字从左往右排,以至于要选左上角的候选字的话就要伸直大拇指。还有按“1”和“Q”的时候也是。要伸直大拇指,建议双手打字。
希望可以帮到您,祝您生活愉快!
ttls1xfnv793你好,苹果6s已经上市很长时间了。
苹果iPhone6s及Plus将从9月12日开始预定,本月25日正式发售,中国成为首发国之一。
  配置方面,iPhone6s搭载64位苹果A9处理器,使用新的晶体管架构,号称比A8快70%,GPU比A8快90%,分别是“桌面级别”和“主机级别”。内置M9动作协处理器,Siri可被随时唤醒,不用插电!另外TouchID也升级到第二代。存储空间还是16GB起。
  摄像头部分,iPhone6s采用全新的1200万像素摄像头,比之前的像素多50%,但摄像头依然凸起,苹果称其自动对焦功能更快,采用全新的Deeptrenchisolation技术,色彩还原更加准确,同时支持4K视频录制。前置500万像素摄像头,自拍时屏幕亮度可增强3倍,当闪光灯来用。
  网络方面,iPhone6s支持2倍速LTE网络,支持23个频段,WiFi速度也增加一倍。
西卡酷你好很高兴为你解答,市面上是有苹果6的
主屏尺寸:4英寸
主屏分辨率:像素
后置摄像头:800万像素
前置摄像头:120万像素
电池容量:1560mAh
电池类型:不可拆卸式电池
核心数:双核
希望我的回答能帮助你
热门问答123456789101112131415161718192021222324252627282930相关问答1个回答洂禍牟买房还是需要慎重考虑的。多方面的因素都要考虑下。现在房产泡沫也很多。不过我个人是觉得房价是只会增不会降的。像身边一些客户炒房的,都多少有赚头的。
3个回答饕餮软妹你好,据我的板价格并不是很高的,价格是99哦。真的好便宜啊,我买了一个型号叫做小巧静音南瓜派,名字听上去特别可爱,它的设计上也是小南瓜的色调哦,小巧的机身比较适合喜欢可爱小玩意的女...3个回答【笔记本】00C2文山现在的房价均价都应该在3200了,80平米三室一厅的设计很少的,一般会设计成两室两厅一厨一卫,有的还有一个阳台。首付的话,首套房是30%。具体看你买在哪和具体户型了,目前文山主...4个回答winM79TX98抚州市的房价是8000元每平米,房子的质量还是蛮好的,里面的环境还有周边的设施都是蛮好的。交通也蛮发达的。性价比相对来说还是蛮好的,买菜啊,还有孩子上学也蛮方便的,房产证也是有的。...3个回答if卫欧失魂落魄每个城市的房价都不一样的,但是我觉得现在的房价普遍大城市都还是比较高
3个回答laifuzhen一套100平米的房子在新加坡的大概价值:好地段的价格为30万新币(141万人民币),在一般地段价格为25万新币(117.5万人民币)。(切记,这是套内使用面积,新加坡不算建筑面积的...0个回答3个回答爱刷_棍哥675你好,据我所知新郑现在房价:
小区:富田兴和湾
均价:10000元/㎡
地址:新郑市龙湖宜居教育区祥云路和鸿鹄路交汇处北300米
沿途公交:567路
...3个回答啊是EV83QA69攀枝花房价4086元/平米, 环比上周 下跌-0.3% ,同比去年 下跌-2.8% 宏坤·中央公园 [住宅] 均价5800元/平方米 [房价走势] 开盘日期:2014年7月 物业地...3个回答橅孮皾拉萨市中心房价如: 格桑林卡6800元/平方米,楼盘地址:城关金珠西路131号 格桑林卡附近的交通比较便利,还有学校的配备的,生活也很便捷,可选的户型范围也比较多,3栋4个单元,其...京沪人均可支配收入接近六万,有钱了的我们为啥还仅是温饱?-北京搜狐焦点
热门城市:
京沪人均可支配收入接近六万,有钱了的我们为啥还仅是温饱?
京沪人均可支配收入接近六万,有钱了的我们为啥还仅是温饱?
2月24日国家统计局公布了2017年全国31个省份居民人均可支配收入数据,根据数据显示,10个省份的人均可支配收入超过全国水平。
声明:本文由入驻焦点开放平台的作者撰写,除焦点官方账号外,观点仅代表作者本人,不代表焦点立场。
报名成功,资料已提交审核
扫码关注 “焦点生活服务圈” 微信公众号
及时了解最新的楼盘动态
更多资讯,欢迎关注
血拼自住商品房
为您提供及时、准确的共有产权房新动态。
楼市相对论
我们只做有深度的房地产新闻报道。
搜狐焦点房谈
致力于为购房者提供专业的购房指导。
购房租房一站式资讯生活平台
点击加载更多
没有更多内容了
正在加载中,请稍后...
北京房地产网站。第一时间掌握北京楼市咨询,为您省时省钱并提供购房服务。
由搜狐焦点北京新闻中心打造的原创栏目,为行业带来最前线的楼市观察。
朱晓红:中国豪宅研究院院长,资深房地产专家
中国豪宅研究院是专家、学者密集型的咨询服务机构。包括开发要点的提炼,开发流程优化,融资模式的选择,項目选址,項目定位,用地必要条件的解读,以及交通组织、规划布局,业态组合,招商指导,资源整合利用的指导,以及风险规避的方法和路径。
看透北京楼市
聚焦地产,洞悉中国。
1290万元/套
900万元/套
810万元/套
72000元/平米
770万元/套
热门二手房
开放平台
广告服务
市场合作
帮助中心
微信公众号
扫码关注“焦点生活服务圈”微信公众号,您将获取更多最新楼盘动态。
电子邮箱:focuskf@vip.sohu.com
爱家热线:400-099-0099
每日9:00至18:00点
Copyright (C) 2018 Sohu.com Inc. All Rights Reserved. 搜狐公司Android6.0动态申请权限那些坑以及避免用户选择不再提示后无法获取权限的问题
6.0 为了保护用户隐私,将一些权限的申请放在了应用运行的时候去申请, 比如以往的开发中,开发人员只需要将需要的权限在清单文件中配置即可,安装后用户可以在设置中的应用信息中看到:XX应用以获取****权限。用户点击可以选择给应用相应的权限。此前的应用权限用户可以选择允许、提醒和拒绝。在安装的时候用户是已经知道应用需要的权限的。但是这样存在一个问题,就是用户在安装的时候,应用需要的权限十分的多(有些开发者为了省事,会请求一些不必要的权限或者请求全部的权限),这个时候用户在安装应用的时候也许并没有发现某些侵犯自己隐私的权限请求,安装之后才发现自己的隐私数据被窃取。其实Android6.0 动态权限一方面是为了广大用户考虑,另一方面其实是Google为了避免一些不必要的官司。下面就说一下Android6.0对权限的分割:
下面是对权限的总结:
首先是大家感兴趣的危险权限
这类权限需要在需要的时候,需要我们动态申请,比如:当我们需要打开相机拍摄照片的时候需要我们通过代码的方式在需要的地方去申请权限。Android6.0中权限问题中我们需要注意的是:
1:由于权限API的问题,我们的Actiivty最好是AppCompatActivity类型的,也就是说在你的BaseActivity需要继承AppCompatActivity
2:权限是分组的,同一组的权限申请其中一个,同组的权限就全部都申请了
特殊权限 组:
CALENDAR 日历
CAMERA 相机
CONTACTS 联系人
LOCATION 定位
MICROPHONE 麦克相关,比如录音
PHONE 手机状态
SENSORS 传感器
STORAGE 存储权限
具体的权限分组情况如下表:
以下是需要单独申请的权限,共分为9组,每组只要有一个权限申请成功了,就默认整组权限都可以使用了。
group:android.permission-group.CONTACTS
permission:android.permission.WRITE_CONTACTS permission:android.permission.GET_ACCOUNTS permission:android.permission.READ_CONTACTS group:android.permission-group.PHONE permission:android.permission.READ_CALL_LOG permission:android.permission.READ_PHONE_STATE permission:android.permission.CALL_PHONE permission:android.permission.WRITE_CALL_LOG permission:android.permission.USE_SIP permission:android.permission.PROCESS_OUTGOING_CALLS permission:com.android.voicemail.permission.ADD_VOICEMAIL group:android.permission-group.CALENDAR permission:android.permission.READ_CALENDAR permission:android.permission.WRITE_CALENDAR group:android.permission-group.CAMERA permission:android.permission.CAMERA group:android.permission-group.SENSORS permission:android.permission.BODY_SENSORS group:android.permission-group.LOCATION permission:android.permission.ACCESS_FINE_LOCATION permission:android.permission.ACCESS_COARSE_LOCATION group:android.permission-group.STORAGE permission:android.permission.READ_EXTERNAL_STORAGE permission:android.permission.WRITE_EXTERNAL_STORAGE group:android.permission-group.MICROPHONE permission:android.permission.RECORD_AUDIO group:android.permission-group.SMS permission:android.permission.READ_SMS permission:android.permission.RECEIVE_WAP_PUSH permission:android.permission.RECEIVE_MMS permission:android.permission.RECEIVE_SMS permission:android.permission.SEND_SMS permission:android.permission.READ_CELL_BROADCASTS
普通权限的总结:
ACCESS_LOCATION_EXTRA_COMMANDS 定位权限ACCESS_NETWORK_STATE 网络状态权限ACCESS_NOTIFICATION_POLICY 通知 APP通知显示在状态栏ACCESS_WIFI_STATE WiFi状态权限BLUETOOTH 使用蓝牙权限BLUETOOTH_ADMIN 控制蓝牙开关BROADCAST_STICKY 粘性广播CHANGE_NETWORK_STATE 改变网络状态CHANGE_WIFI_MULTICAST_STATE 改变WiFi多播状态,应该是控制手机热点(猜测)CHANGE_WIFI_STATE 控制WiFi开关,改变WiFi状态DISABLE_KEYGUARD 改变键盘为不可用EXPAND_STATUS_BAR 扩展bar的状态GET_PACKAGE_SIZE 获取应用安装包大小INTERNET 网络权限KILL_BACKGROUND_PROCESSES 杀死后台进程MODIFY_AUDIO_SETTINGS 改变音频输出设置NFC 支付READ_SYNC_SETTINGS 获取手机设置信息READ_SYNC_STATS 数据统计RECEIVE_BOOT_COMPLETED 监听启动广播REORDER_TASKS 创建新栈REQUEST_INSTALL_PACKAGES 安装应用程序SET_TIME_ZONE 允许应用程序设置时间区域SET_WALLPAPER 设置壁纸SET_WALLPAPER_HINTS 设置壁纸上的提示信息,个性化语言TRANSMIT_IR 红外发射USE_FINGERPRINT 指纹识别VIBRATE 震动WAKE_LOCK 锁屏WRITE_SYNC_SETTINGS 改变设置SET_ALARM 设置警告提示INSTALL_SHORTCUT 创建快捷方式UNINSTALL_SHORTCUT 删除快捷方式以上这些只是普通权限,我们开发的时候,正常使用就行了,需要的权限在清单文件配置即可。
将targetSdkVersion设置为23,注意,如果你将targetSdkVersion设置为&=23,则必须按照Android谷歌的要求,动态的申请权限,如果你暂时不打算支持动态权限申请,则targetSdkVersion最大只能设置为22.
2 在AndroidManifest.xml中申请你需要的权限,包括普通权限和需要申请的特殊权限。
3.开始申请权限,此处分为3部。
(1)检查是否由此权限checkSelfPermission(),如果已经开启,则直接做你想做的。
(2)如果未开启,则判断是否需要向用户解释为何申请权限shouldShowRequestPermissionRationale。
(3)如果需要(即返回true),则可以弹出对话框提示用户申请权限原因,用户确认后申请权限requestPermissions(),如果不需要(即返回false),则直接申请权限requestPermissions()。单个权限申请.png
* Requests permission. * * @param activity * @param requestCode request code, e.g. if you need request CAMERA permission,parameters is PermissionUtils.CODE_CAMERA */ public static void requestPermission(final Activity activity, final int requestCode, PermissionGrant permissionGrant) { if (activity == null) { } Log.i(TAG, &requestPermission requestCode:& + requestCode); if (requestCode & 0 || requestCode &= requestPermissions.length) { Log.w(TAG, &requestPermission illegal requestCode:& + requestCode); } final String requestPermission = requestPermissions[requestCode]; //如果是6.0以下的手机,ActivityCompat.checkSelfPermission()会始终等于PERMISSION_GRANTED, // 但是,如果用户关闭了你申请的权限(如下图,在安装的时候,将一些权限关闭了),ActivityCompat.checkSelfPermission()则可能会导致程序崩溃(java.lang.RuntimeException: Unknown exception code: 1 msg null), // 你可以使用try{}catch(){},处理异常,也可以判断系统版本,低于23就不申请权限,直接做你想做的。permissionGrant.onPermissionGranted(requestCode);// if (Build.VERSION.SDK_INT & 23) {// permissionGrant.onPermissionGranted(requestCode);//// } int checkSelfP try { checkSelfPermission = ActivityCompat.checkSelfPermission(activity, requestPermission); } catch (RuntimeException e) { Toast.makeText(activity, &please open this permission&, Toast.LENGTH_SHORT) .show(); Log.e(TAG, &RuntimeException:& + e.getMessage()); } if (checkSelfPermission != PackageManager.PERMISSION_GRANTED) { Log.i(TAG, &ActivityCompat.checkSelfPermission != PackageManager.PERMISSION_GRANTED&); if (ActivityCompat.shouldShowRequestPermissionRationale(activity, requestPermission)) { Log.i(TAG, &requestPermission shouldShowRequestPermissionRationale&); shouldShowRationale(activity, requestCode, requestPermission); } else { Log.d(TAG, &requestCameraPermission else&); ActivityCompat.requestPermissions(activity, new String[]{requestPermission}, requestCode); } } else { Log.d(TAG, &ActivityCompat.checkSelfPermission ==== PackageManager.PERMISSION_GRANTED&); Toast.makeText(activity, &opened:& + requestPermissions[requestCode], Toast.LENGTH_SHORT).show();//得到权限的时候,就可以在回调里面做你想做的事情了 permissionGrant.onPermissionGranted(requestCode); } }
(1)checkSelfPermission:检查是否拥有这个权限
(2)requestPermissions:请求权限,一般会弹出一个系统对话框,询问用户是否开启这个权限。(3)shouldShowRequestPermissionRationale:Android原生系统中,如果第二次弹出权限申请的对话框,会出现&以后不再弹出&的提示框,如果用户勾选了,你再申请权限, 则shouldShowRequestPermissionRationale返回true,意思是说要给用户一个 解释,告诉用户为什么要这个权限。然而,在实际开发中,需要注意的是,很多手机对原生 系统做了修改,比如小米,小米4的6.0的shouldShowRequestPermissionRationale 就一直返回false,而且在申请权限时,如果用户选择了拒绝,则不会再弹出对话框了 。。。。 所以说这个地方有坑,我的解决方法是,在回调里面处理,如果用户拒绝了这个权限,则打开本应用信息界面,由用户自己手动开启这个权限。(4)每个应用都有自己的权限管理界面,里面有本应用申请的权限以及各种状态,即使用户已经同意了你申请的权限,他也随时可以关闭
由于checkSelfPermission和requestPermissions从API 23才加入,低于23版本,需要在运行时判断 或者使用Support Library v4中提供的方法
ContextCompat.checkSelfPermission
ActivityCompat.requestPermissions
ActivityCompat.shouldShowRequestPermissionRationale
多系统问题
当我们支持了6.0必须也要支持4.4,5.0这些系统,所以需要在很多情况下,需要有两套处理。比如Camera权限
[java] view plain copy
if(isMarshmallow()){
requestPermission();//然后在回调中处理
useCamera();//低于6.0直接使用Camera
两个特殊权限
特殊权限,顾名思义,就是一些特别敏感的权限,在Android系统中,主要由两个
SYSTEM_ALERT_WINDOW,设置悬浮窗,进行一些黑科技
WRITE_SETTINGS 修改系统设置
关于上面两个特殊权限的授权,做法是使用startActivityForResult启动授权界面来完成。
请求SYSTEM_ALERT_WINDOW
[java] view plain copy
privatestaticfinalintREQUEST_CODE=1;
privatevoidrequestAlertWindowPermission(){
Intentintent=newIntent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
intent.setData(Uri.parse(&package:&+getPackageName()));
startActivityForResult(intent,REQUEST_CODE);
protectedvoidonActivityResult(intrequestCode,intresultCode,Intentdata){
super.onActivityResult(requestCode,resultCode,data);
if(requestCode==REQUEST_CODE){
if(Settings.canDrawOverlays(this)){
Log.i(LOGTAG,&onActivityResultgranted&);
上述代码需要注意的是
使用Action Settings.ACTION_MANAGE_OVERLAY_PERMISSION启动隐式Intent
使用&package:& + getPackageName()携带App的包名信息
使用Settings.canDrawOverlays方法判断授权结果
请求WRITE_SETTINGS
[java] view plain copy
privatestaticfinalintREQUEST_CODE_WRITE_SETTINGS=2;
privatevoidrequestWriteSettings(){
Intentintent=newIntent(Settings.ACTION_MANAGE_WRITE_SETTINGS);
intent.setData(Uri.parse(&package:&+getPackageName()));
startActivityForResult(intent,REQUEST_CODE_WRITE_SETTINGS);
protectedvoidonActivityResult(intrequestCode,intresultCode,Intentdata){
super.onActivityResult(requestCode,resultCode,data);
if(requestCode==REQUEST_CODE_WRITE_SETTINGS){
if(Settings.System.canWrite(this)){
Log.i(LOGTAG,&onActivityResultwritesettingsgranted&);
上述代码需要注意的是
使用Action Settings.ACTION_MANAGE_WRITE_SETTINGS 启动隐式Intent
使用&package:& + getPackageName()携带App的包名信息
使用Settings.System.canWrite方法检测授权结果
注意:关于这两个特殊权限,一般不建议应用申请。
关于本demo的所有代码:
整个申请权限工具类代码
package com.example.android.system.import android.Mimport android.app.Aimport android.content.DialogIimport android.content.Iimport android.content.pm.PackageMimport android.net.Uimport android.provider.Simport android.support.annotation.NonNimport android.support.v4.app.ActivityCimport android.support.v7.app.AlertDimport android.util.Limport android.widget.Timport java.util.ArrayLimport java.util.HashMimport java.util.Limport java.util.M/** * Created by qianxiaoai on . */public class PermissionUtils { private static final String TAG = PermissionUtils.class.getSimpleName(); public static final int CODE_RECORD_AUDIO = 0; public static final int CODE_GET_ACCOUNTS = 1; public static final int CODE_READ_PHONE_STATE = 2; public static final int CODE_CALL_PHONE = 3; public static final int CODE_CAMERA = 4; public static final int CODE_ACCESS_FINE_LOCATION = 5; public static final int CODE_ACCESS_COARSE_LOCATION = 6; public static final int CODE_READ_EXTERNAL_STORAGE = 7; public static final int CODE_WRITE_EXTERNAL_STORAGE = 8; public static final int CODE_MULTI_PERMISSION = 100; public static final String PERMISSION_RECORD_AUDIO = Manifest.permission.RECORD_AUDIO; public static final String PERMISSION_GET_ACCOUNTS = Manifest.permission.GET_ACCOUNTS; public static final String PERMISSION_READ_PHONE_STATE = Manifest.permission.READ_PHONE_STATE; public static final String PERMISSION_CALL_PHONE = Manifest.permission.CALL_PHONE; public static final String PERMISSION_CAMERA = Manifest.permission.CAMERA; public static final String PERMISSION_ACCESS_FINE_LOCATION = Manifest.permission.ACCESS_FINE_LOCATION; public static final String PERMISSION_ACCESS_COARSE_LOCATION = Manifest.permission.ACCESS_COARSE_LOCATION; public static final String PERMISSION_READ_EXTERNAL_STORAGE = Manifest.permission.READ_EXTERNAL_STORAGE; public static final String PERMISSION_WRITE_EXTERNAL_STORAGE = Manifest.permission.WRITE_EXTERNAL_STORAGE; private static final String[] requestPermissions = { PERMISSION_RECORD_AUDIO, PERMISSION_GET_ACCOUNTS, PERMISSION_READ_PHONE_STATE, PERMISSION_CALL_PHONE, PERMISSION_CAMERA, PERMISSION_ACCESS_FINE_LOCATION, PERMISSION_ACCESS_COARSE_LOCATION, PERMISSION_READ_EXTERNAL_STORAGE, PERMISSION_WRITE_EXTERNAL_STORAGE }; interface PermissionGrant { void onPermissionGranted(int requestCode); } /** * Requests permission. * * @param activity * @param requestCode request code, e.g. if you need request CAMERA permission,parameters is PermissionUtils.CODE_CAMERA */ public static void requestPermission(final Activity activity, final int requestCode, PermissionGrant permissionGrant) { if (activity == null) { } Log.i(TAG, &requestPermission requestCode:& + requestCode); if (requestCode & 0 || requestCode &= requestPermissions.length) { Log.w(TAG, &requestPermission illegal requestCode:& + requestCode); } final String requestPermission = requestPermissions[requestCode]; //如果是6.0以下的手机,ActivityCompat.checkSelfPermission()会始终等于PERMISSION_GRANTED, // 但是,如果用户关闭了你申请的权限,ActivityCompat.checkSelfPermission(),会导致程序崩溃(java.lang.RuntimeException: Unknown exception code: 1 msg null), // 你可以使用try{}catch(){},处理异常,也可以在这个地方,低于23就什么都不做, // 个人建议try{}catch(){}单独处理,提示用户开启权限。// if (Build.VERSION.SDK_INT & 23) {//// } int checkSelfP try { checkSelfPermission = ActivityCompat.checkSelfPermission(activity, requestPermission); } catch (RuntimeException e) { Toast.makeText(activity, &please open this permission&, Toast.LENGTH_SHORT) .show(); Log.e(TAG, &RuntimeException:& + e.getMessage()); } if (checkSelfPermission != PackageManager.PERMISSION_GRANTED) { Log.i(TAG, &ActivityCompat.checkSelfPermission != PackageManager.PERMISSION_GRANTED&); if (ActivityCompat.shouldShowRequestPermissionRationale(activity, requestPermission)) { Log.i(TAG, &requestPermission shouldShowRequestPermissionRationale&); shouldShowRationale(activity, requestCode, requestPermission); } else { Log.d(TAG, &requestCameraPermission else&); ActivityCompat.requestPermissions(activity, new String[]{requestPermission}, requestCode); } } else { Log.d(TAG, &ActivityCompat.checkSelfPermission ==== PackageManager.PERMISSION_GRANTED&); Toast.makeText(activity, &opened:& + requestPermissions[requestCode], Toast.LENGTH_SHORT).show(); permissionGrant.onPermissionGranted(requestCode); } } private static void requestMultiResult(Activity activity, String[] permissions, int[] grantResults, PermissionGrant permissionGrant) { if (activity == null) { } //TODO Log.d(TAG, &onRequestPermissionsResult permissions length:& + permissions.length); Map perms = new HashMap&&(); ArrayList notGranted = new ArrayList&&(); for (int i = 0; i & permissions. i++) { Log.d(TAG, &permissions: [i]:& + i + &, permissions[i]& + permissions[i] + &,grantResults[i]:& + grantResults[i]); perms.put(permissions[i], grantResults[i]); if (grantResults[i] != PackageManager.PERMISSION_GRANTED) { notGranted.add(permissions[i]); } } if (notGranted.size() == 0) { Toast.makeText(activity, &all permission success& + notGranted, Toast.LENGTH_SHORT) .show(); permissionGrant.onPermissionGranted(CODE_MULTI_PERMISSION); } else { openSettingActivity(activity, &those permission need granted!&); } } /** * 一次申请多个权限 */ public static void requestMultiPermissions(final Activity activity, PermissionGrant grant) { final List permissionsList = getNoGrantedPermission(activity, false); final List shouldRationalePermissionsList = getNoGrantedPermission(activity, true); //TODO checkSelfPermission if (permissionsList == null || shouldRationalePermissionsList == null) { } Log.d(TAG, &requestMultiPermissions permissionsList:& + permissionsList.size() + &,shouldRationalePermissionsList:& + shouldRationalePermissionsList.size()); if (permissionsList.size() & 0) { ActivityCompat.requestPermissions(activity, permissionsList.toArray(new String[permissionsList.size()]), CODE_MULTI_PERMISSION); Log.d(TAG, &showMessageOKCancel requestPermissions&); } else if (shouldRationalePermissionsList.size() & 0) { showMessageOKCancel(activity, &should open those permission&, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { ActivityCompat.requestPermissions(activity, shouldRationalePermissionsList.toArray(new String[shouldRationalePermissionsList.size()]), CODE_MULTI_PERMISSION); Log.d(TAG, &showMessageOKCancel requestPermissions&); } }); } else { grant.onPermissionGranted(CODE_MULTI_PERMISSION); } } private static void shouldShowRationale(final Activity activity, final int requestCode, final String requestPermission) { //TODO String[] permissionsHint = activity.getResources().getStringArray(R.array.permissions); showMessageOKCancel(activity, &Rationale: & + permissionsHint[requestCode], new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { ActivityCompat.requestPermissions(activity, new String[]{requestPermission}, requestCode); Log.d(TAG, &showMessageOKCancel requestPermissions:& + requestPermission); } }); } private static void showMessageOKCancel(final Activity context, String message, DialogInterface.OnClickListener okListener) { new AlertDialog.Builder(context) .setMessage(message) .setPositiveButton(&OK&, okListener) .setNegativeButton(&Cancel&, null) .create() .show(); } /** * @param activity * @param requestCode Need consistent with requestPermission * @param permissions * @param grantResults */ public static void requestPermissionsResult(final Activity activity, final int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults, PermissionGrant permissionGrant) { if (activity == null) { } Log.d(TAG, &requestPermissionsResult requestCode:& + requestCode); if (requestCode == CODE_MULTI_PERMISSION) { requestMultiResult(activity, permissions, grantResults, permissionGrant); } if (requestCode & 0 || requestCode &= requestPermissions.length) { Log.w(TAG, &requestPermissionsResult illegal requestCode:& + requestCode); Toast.makeText(activity, &illegal requestCode:& + requestCode, Toast.LENGTH_SHORT).show(); } Log.i(TAG, &onRequestPermissionsResult requestCode:& + requestCode + &,permissions:& + permissions.toString() + &,grantResults:& + grantResults.toString() + &,length:& + grantResults.length); if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { Log.i(TAG, &onRequestPermissionsResult PERMISSION_GRANTED&); //TODO success, do something, can use callback permissionGrant.onPermissionGranted(requestCode); } else { //TODO hint user this permission function Log.i(TAG, &onRequestPermissionsResult PERMISSION NOT GRANTED&); //TODO String[] permissionsHint = activity.getResources().getStringArray(R.array.permissions); openSettingActivity(activity, &Result& + permissionsHint[requestCode]); } } private static void openSettingActivity(final Activity activity, String message) { showMessageOKCancel(activity, message, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Intent intent = new Intent(); intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); Log.d(TAG, &getPackageName(): & + activity.getPackageName()); Uri uri = Uri.fromParts(&package&, activity.getPackageName(), null); intent.setData(uri); activity.startActivity(intent); } }); } /** * @param activity * @param isShouldRationale true: return no granted and shouldShowRequestPermissionRationale permissions, false:return no granted and !shouldShowRequestPermissionRationale * @return */ public static ArrayList getNoGrantedPermission(Activity activity, boolean isShouldRationale) { ArrayList permissions = new ArrayList&&(); for (int i = 0; i & requestPermissions. i++) { String requestPermission = requestPermissions[i]; //TODO checkSelfPermission int checkSelfPermission = -1; try { checkSelfPermission = ActivityCompat.checkSelfPermission(activity, requestPermission); } catch (RuntimeException e) { Toast.makeText(activity, &please open those permission&, Toast.LENGTH_SHORT) .show(); Log.e(TAG, &RuntimeException:& + e.getMessage()); } if (checkSelfPermission != PackageManager.PERMISSION_GRANTED) { Log.i(TAG, &getNoGrantedPermission ActivityCompat.checkSelfPermission != PackageManager.PERMISSION_GRANTED:& + requestPermission); if (ActivityCompat.shouldShowRequestPermissionRationale(activity, requestPermission)) { Log.d(TAG, &shouldShowRequestPermissionRationale if&); if (isShouldRationale) { permissions.add(requestPermission); } } else { if (!isShouldRationale) { permissions.add(requestPermission); } Log.d(TAG, &shouldShowRequestPermissionRationale else&); } } } }}
界面调用代码package com.example.android.system.import android.os.Bimport android.support.annotation.NonNimport android.support.v4.app.ActivityCimport android.support.v4.app.FragmentAimport android.support.v4.app.FragmentTimport android.view.Vimport android.widget.Timport com.example.android.common.logger.L/** * Created by qianxiaoai on . */public class PermissionActivity extends FragmentActivity implements ActivityCompat.OnRequestPermissionsResultCallback{ private static final String TAG = PermissionActivity.class.getSimpleName(); @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_permission); FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); PermissionsFragment fragment = new PermissionsFragment(); transaction.replace(R.id.content_fragment, fragment); transaction.commit(); } /** * Called when the 'show camera' button is clicked. * Callback is defined in resource layout definition. */ public void showCamera(View view) { Log.i(TAG, &Show camera button pressed. Checking permission.&); PermissionUtils.requestPermission(this, PermissionUtils.CODE_CAMERA, mPermissionGrant); } public void getAccounts(View view) { PermissionUtils.requestPermission(this, PermissionUtils.CODE_GET_ACCOUNTS, mPermissionGrant); } public void callPhone(View view) { PermissionUtils.requestPermission(this, PermissionUtils.CODE_CALL_PHONE, mPermissionGrant); } public void readPhoneState(View view) { PermissionUtils.requestPermission(this, PermissionUtils.CODE_READ_PHONE_STATE, mPermissionGrant); } public void accessFineLocation(View view) { PermissionUtils.requestPermission(this, PermissionUtils.CODE_ACCESS_FINE_LOCATION, mPermissionGrant); } public void accessCoarseLocation(View view) { PermissionUtils.requestPermission(this, PermissionUtils.CODE_ACCESS_COARSE_LOCATION, mPermissionGrant); } public void readExternalStorage(View view) { PermissionUtils.requestPermission(this, PermissionUtils.CODE_READ_EXTERNAL_STORAGE, mPermissionGrant); } public void writeExternalStorage(View view) { PermissionUtils.requestPermission(this, PermissionUtils.CODE_WRITE_EXTERNAL_STORAGE, mPermissionGrant); } public void recordAudio(View view) { PermissionUtils.requestPermission(this, PermissionUtils.CODE_RECORD_AUDIO, mPermissionGrant); } private PermissionUtils.PermissionGrant mPermissionGrant = new PermissionUtils.PermissionGrant() { @Override public void onPermissionGranted(int requestCode) { switch (requestCode) { case PermissionUtils.CODE_RECORD_AUDIO: Toast.makeText(PermissionActivity.this, &Result Permission Grant CODE_RECORD_AUDIO&, Toast.LENGTH_SHORT).show(); case PermissionUtils.CODE_GET_ACCOUNTS: Toast.makeText(PermissionActivity.this, &Result Permission Grant CODE_GET_ACCOUNTS&, Toast.LENGTH_SHORT).show(); case PermissionUtils.CODE_READ_PHONE_STATE: Toast.makeText(PermissionActivity.this, &Result Permission Grant CODE_READ_PHONE_STATE&, Toast.LENGTH_SHORT).show(); case PermissionUtils.CODE_CALL_PHONE: Toast.makeText(PermissionActivity.this, &Result Permission Grant CODE_CALL_PHONE&, Toast.LENGTH_SHORT).show(); case PermissionUtils.CODE_CAMERA: Toast.makeText(PermissionActivity.this, &Result Permission Grant CODE_CAMERA&, Toast.LENGTH_SHORT).show(); case PermissionUtils.CODE_ACCESS_FINE_LOCATION: Toast.makeText(PermissionActivity.this, &Result Permission Grant CODE_ACCESS_FINE_LOCATION&, Toast.LENGTH_SHORT).show(); case PermissionUtils.CODE_ACCESS_COARSE_LOCATION: Toast.makeText(PermissionActivity.this, &Result Permission Grant CODE_ACCESS_COARSE_LOCATION&, Toast.LENGTH_SHORT).show(); case PermissionUtils.CODE_READ_EXTERNAL_STORAGE: Toast.makeText(PermissionActivity.this, &Result Permission Grant CODE_READ_EXTERNAL_STORAGE&, Toast.LENGTH_SHORT).show(); case PermissionUtils.CODE_WRITE_EXTERNAL_STORAGE: Toast.makeText(PermissionActivity.this, &Result Permission Grant CODE_WRITE_EXTERNAL_STORAGE&, Toast.LENGTH_SHORT).show(); default: } } }; /** * Callback received when a permissions request has been completed. */ @Override public void onRequestPermissionsResult(final int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { PermissionUtils.requestPermissionsResult(this, requestCode, permissions, grantResults, mPermissionGrant); }}
xml布局 android:layout_width=&match_parent& android:layout_height=&match_parent& android:paddingLeft=&@dimen/horizontal_page_margin& android:paddingRight=&@dimen/horizontal_page_margin& android:paddingTop=&@dimen/vertical_page_margin& android:paddingBottom=&@dimen/vertical_page_margin& android:orientation=&vertical& & android:id=&@+id/content_fragment& android:layout_width=&match_parent& android:layout_height=&0dp& android:layout_weight=&1&/& android:layout_width=&match_parent& android:layout_height=&0dp& android:layout_weight=&1&&android:layout_width=&match_parent& android:layout_height=&match_parent& android:orientation=&vertical&&android:layout_width=&match_parent& android:layout_height=&wrap_content& android:orientation=&horizontal&&android:layout_width=&wrap_content& android:layout_height=&wrap_content& android:text=&Camera& android:id=&@+id/button_camera& android:onClick=&showCamera&/&android:layout_width=&wrap_content& android:layout_height=&wrap_content& android:text=&RECORD_AUDIO& android:onClick=&recordAudio&/& android:layout_width=&match_parent& android:layout_height=&wrap_content& android:orientation=&horizontal&&android:layout_width=&wrap_content& android:layout_height=&wrap_content& android:text=&GET_ACCOUNTS& android:onClick=&getAccounts&/& android:layout_width=&wrap_content& android:layout_height=&wrap_content& android:text=&CALL_PHONE& android:onClick=&callPhone&/& android:layout_width=&wrap_content& android:layout_height=&wrap_content& android:text=&PERMISSION_READ_PHONE_STATE& android:onClick=&readPhoneState&/&android:layout_width=&wrap_content& android:layout_height=&wrap_content& android:text=&ACCESS_FINE_LOCATION& android:onClick=&accessFineLocation&/&android:layout_width=&wrap_content& android:layout_height=&wrap_content& android:text=&ACCESS_COARSE_LOCATION& android:onClick=&accessCoarseLocation&/&android:layout_width=&wrap_content& android:layout_height=&wrap_content& android:text=&READ_EXTERNAL_STORAGE& android:onClick=&readExternalStorage&/&android:layout_width=&wrap_content& android:layout_height=&wrap_content& android:text=&WRITE_EXTERNAL_STORAGE& android:onClick=&writeExternalStorage&/&
清单文件申请的权限
部分资源文件 @string/permission_recode_audio_hint @string/permission_get_accounts_hint @string/permission_read_phone_hint @string/permission_call_phone_hint @string/permission_camera_hint @string/permission_access_fine_location_hint @string/permission_access_coarse_location_hint @string/permission_read_external_hint @string/permission_white_external_hint 没有此权限,无法开启这个功能,请开启权限。PERMISSION_GET_ACCOUNTS 没有此权限,无法开启这个功能,请开启权限。PERMISSION_READ_PHONE_STATE 没有此权限,无法开启这个功能,请开启权限。PERMISSION_CALL_PHONE 没有此权限,无法开启这个功能,请开启权限。PERMISSION_CAMERA 没有此权限,无法开启这个功能,请开启权限。PERMISSION_ACCESS_FINE_LOCATION 没有此权限,无法开启这个功能,请开启权限。PERMISSION_ACCESS_COARSE_LOCATION 没有此权限,无法开启这个功能,请开启权限。PERMISSION_READ_EXTERNAL_STORAGE 没有此权限,无法开启这个功能,请开启权限。PERMISSION_WRITE_EXTERNAL_STORAGE 没有此权限,无法开启这个功能,请开启权限。PERMISSION_RE
关于自定义权限申请弹框 避免用户不再申请的问题
Android6.0版本(Api 23)推出了很多新的特性, 大幅提升了用户体验, 同时也为程序员带来新的负担.动态权限管理就是这样, 一方面让用户更加容易的控制自己的隐私, 一方面需要重新适配应用权限. 时代总是不断发展, 程序总是以人为本, 让我们为应用添加动态权限管理吧! 这里提供了一个非常不错的解决方案, 提供, 项目可以直接使用.
Android系统包含默认的授权提示框, 但是我们仍需要设置自己的页面. 原因是系统提供的授权框, 会有不再提示的选项. 如果用户选择, 则无法触发授权提示. 使用自定义的提示页面, 可以给予用户手动修改授权的指导.
本文示例GitHub下载地址.
在Api 23中, 权限需要动态获取, 核心权限必须满足. 标准流程:
如果用户点击,不再提示, 则系统授权弹窗将不会弹出. 流程变为:
流程就这些, 让我们看看代码吧.
在AndroidManifest中, 添加两个权限,录音和修改音量.
危险权限必须要授权, 一般权限不需要.
检测权限类
* 检查权限的工具类
* Created by wangchenlong on 16/1/26. */public class PermissionsChecker {private final Context mC public PermissionsChecker(Context context) { mContext = context.getApplicationContext(); } // 判断权限集合public boolean lacksPermissions(String... permissions) { for (String permission : permissions) { if (lacksPermission(permission)) { } } } // 判断是否缺少权限private boolean lacksPermission(String permission) { return ContextCompat.checkSelfPermission(mContext, permission) == PackageManager.PERMISSION_DENIED; } }
假设首页需要使用权限, 在页面显示前, 即onResume时, 检测权限,
如果缺少, 则进入权限获取页面; 接收返回值, 拒绝权限时, 直接关闭.
public class MainActivity extends AppCompatActivity {private static final int REQUEST_CODE = 0; // 请求码// 所需的全部权限static final String[] PERMISSIONS = new String[]{
Manifest.permission.RECORD_AUDIO,
Manifest.permission.MODIFY_AUDIO_SETTINGS
@Bind(R.id.main_t_toolbar) Toolbar mTT
private PermissionsChecker mPermissionsC // 权限检测器@Overrideprotected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
setSupportActionBar(mTToolbar);
mPermissionsChecker = new PermissionsChecker(this);
@Override protected void onResume() {
super.onResume();
// 缺少权限时, 进入权限配置页面if (mPermissionsChecker.lacksPermissions(PERMISSIONS)) {
startPermissionsActivity();
private void startPermissionsActivity() {
PermissionsActivity.startActivityForResult(this, REQUEST_CODE, PERMISSIONS);
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// 拒绝时, 关闭页面, 缺少主要权限, 无法运行if (requestCode == REQUEST_CODE && resultCode == PermissionsActivity.PERMISSIONS_DENIED) {
核心权限必须满足, 如摄像应用, 摄像头权限就是必须的, 如果用户不予授权, 则直接关闭.
授权页, 首先使用系统默认的授权页, 当用户拒绝时, 指导用户手动设置, 当用户再次操作失败后, 返回继续提示. 用户手动退出授权页时, 给使用页发送授权失败的通知.
* 权限获取页面
* Created by wangchenlong on 16/1/26. */public class PermissionsActivity extends AppCompatActivity {public static final int PERMISSIONS_GRANTED = 0; // 权限授权public static final int PERMISSIONS_DENIED = 1; // 权限拒绝private static final int PERMISSION_REQUEST_CODE = 0; // 系统权限管理页面的参数private static final String EXTRA_PERMISSIONS = &me.chunyu.clwang.permission.extra_permission&; // 权限参数private static final String PACKAGE_URL_SCHEME = &package:&; // 方案private PermissionsChecker mC // 权限检测器private boolean isRequireC // 是否需要系统权限检测// 启动当前权限页面的公开接口public static void startActivityForResult(Activity activity, int requestCode, String... permissions) { Intent intent = new Intent(activity, PermissionsActivity.class); intent.putExtra(EXTRA_PERMISSIONS, permissions); ActivityCompat.startActivityForResult(activity, intent, requestCode, null); } @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (getIntent() == null || !getIntent().hasExtra(EXTRA_PERMISSIONS)) { throw new RuntimeException(&PermissionsActivity需要使用静态startActivityForResult方法启动!&); } setContentView(R.layout.activity_permissions); mChecker = new PermissionsChecker(this); isRequireCheck = } @Override protected void onResume() { super.onResume(); if (isRequireCheck) { String[] permissions = getPermissions(); if (mChecker.lacksPermissions(permissions)) { requestPermissions(permissions); // 请求权限 } else { allPermissionsGranted(); // 全部权限都已获取 } } else { isRequireCheck = } } // 返回传递的权限参数private String[] getPermissions() { return getIntent().getStringArrayExtra(EXTRA_PERMISSIONS); } // 请求权限兼容低版本private void requestPermissions(String... permissions) { ActivityCompat.requestPermissions(this, permissions, PERMISSION_REQUEST_CODE); } // 全部权限均已获取private void allPermissionsGranted() { setResult(PERMISSIONS_GRANTED); finish(); } /** * 用户权限处理, * 如果全部获取, 则直接过. * 如果权限缺失, 则提示Dialog. * * @param requestCode 请求码 * @param permissions 权限 * @param grantResults 结果 */@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { if (requestCode == PERMISSION_REQUEST_CODE && hasAllPermissionsGranted(grantResults)) { isRequireCheck = allPermissionsGranted(); } else { isRequireCheck = showMissingPermissionDialog(); } } // 含有全部的权限private boolean hasAllPermissionsGranted(@NonNull int[] grantResults) { for (int grantResult : grantResults) { if (grantResult == PackageManager.PERMISSION_DENIED) { } } } // 显示缺失权限提示private void showMissingPermissionDialog() { AlertDialog.Builder builder = new AlertDialog.Builder(PermissionsActivity.this); builder.setTitle(R.string.help); builder.setMessage(R.string.string_help_text); // 拒绝, 退出应用 builder.setNegativeButton(R.string.quit, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { setResult(PERMISSIONS_DENIED); finish(); } }); builder.setPositiveButton(R.string.settings, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { startAppSettings(); } }); builder.show(); } // 启动应用的设置private void startAppSettings() { Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); intent.setData(Uri.parse(PACKAGE_URL_SCHEME + getPackageName())); startActivity(intent); } }
注意isRequireCheck参数的使用, 防止和系统提示框重叠.
系统授权提示: ActivityCompat.requestPermissions, ActivityCompat兼容低版本.
关键部分就这些了, 动态权限授权虽然给程序员带来了一些麻烦, 但是对用户还是很有必要的, 我们也应该欢迎, 毕竟每个程序员都是半个产品经理.

我要回帖

更多关于 儿童五子棋基础入门 的文章

 

随机推荐