《安卓开垦框架》体系文章,Activity将会压入栈中

《安卓开垦框架》类别小说>>>

本人的博客
自己的博客:Android6.0动态权限申请手续以及要求注意的1部分坑

一、什么是Activity?

   
简来讲之:Activity便是遍布整个窗口恐怕悬浮于其余窗口上的竞相分界面。在1个应用程序中无独有偶由八个Activity构成,都会在Manifest.xml中钦点一个主的Activity,如下设置

<actionandroid:name=”android.intent.action.MAIN”
/>

当程序第壹遍运维时用户就能够看这么些Activity,这一个Activity能够经过运行其余的Activity举行连锁操作。当运行其余的Activity时这几个当前的这几个Activity将会告一段落,新的
Activity将会压入栈中,同时取得用户主题,那时就可在那么些Activity上操作了。都知情栈是先进后出的尺度,那么当用户按Back键时,当前
的那个Activity销毁,前一个Activity重新苏醒。

前言

差不离各样体系都会有两种四种的工具类,在付出中通过它们可更间接惠及地促功能益。上边将介绍demo中逐条工具类的使用,而实际的贯彻请下载demo查看代码。


因为职业急需,轻便研究了一下Android6.0权力申请,在谷歌提供的sample的功底上,写了1个差不多的demo。算是自个儿的笔记吧,也许会相比较混乱,重假若有益以后翻看。早先时期有其他难点,随时更新~

二、Activity生命周期

先看下图:

图片 1

本条图不再多说什么样,上边我们通过二个实例来注解难题。新建筑工程程,编写如下代码:

[java] view
plain

copy
print?

  1. <span style=”font-size:18px;”>package com.android.ttx.actiitylifedemo;  
  2. import android.app.Activity;  
  3. import android.os.Bundle;  
  4. import android.util.Log;  
  5. import android.view.KeyEvent;  
  6. public class ActivityLifeDemo extends Activity {  
  7.     private final static String TAG=”ActivityLifeDemo”;  
  8.       
  9.     @Override  
  10.     public void onCreate(Bundle savedInstanceState) {  
  11.         super.onCreate(savedInstanceState);  
  12.         setContentView(R.layout.main);  
  13.           
  14.         Log.i(TAG, “onCreate”);  
  15.     }  
  16.     @Override  
  17.     protected void onStart() {  
  18.         Log.i(TAG, “onStart”);  
  19.         super.onStart();  
  20.     }  
  21.     @Override  
  22.     protected void onRestart() {  
  23.         Log.i(TAG, “onRestart”);  
  24.         super.onRestart();  
  25.     }  
  26.     @Override  
  27.     protected void onResume() {  
  28.         Log.i(TAG, “onResume”);  
  29.         super.onResume();  
  30.     }  
  31.     @Override  
  32.     protected void onPause() {  
  33.         Log.i(TAG, “onPause”);  
  34.         super.onPause();  
  35.     }  
  36.     @Override  
  37.     protected void onStop() {  
  38.         Log.i(TAG, “onStop”);  
  39.         super.onStop();  
  40.     }  
  41.     @Override  
  42.     protected void onDestroy() {  
  43.         Log.i(TAG, “onDestroy”);  
  44.         super.onDestroy();  
  45.     }  
  46. }  
  47. </span>  

代码很简短,只关乎到3个Activity,一些用户的操作,我们透过记录操作和打字与印刷日志的办法来看看Activity的生命周期进度。

1、  运行
来看如下打字与印刷日志:
08-31 08:46:53.916: INFO/ActivityLifeDemo(312): onCreate
08-31 08:46:53.916: INFO/ActivityLifeDemo(312): onStart
08-31 08:46:53.916: INFO/ActivityLifeDemo(312): onResume
二、按下回到按钮:
08-31 09:29:57.396: INFO/ActivityLifeDemo(354): onPause
08-31 09:29:58.216: INFO/ActivityLifeDemo(354): onStop
08-31 09:29:58.216: INFO/ActivityLifeDemo(354): onDestroy
三、长按Home键,弹出近期开垦过的应用程序,点击ActivityLife德姆o
08-31 08:51:46.916: INFO/ActivityLifeDemo(312): onCreate
08-31 08:51:46.916: INFO/ActivityLifeDemo(312): onStart
08-31 08:51:46.936: INFO/ActivityLifeDemo(312): onResume
4、按Home键
08-31 08:53:32.676: INFO/ActivityLifeDemo(312): onPause
08-31 08:53:33.796: INFO/ActivityLifeDemo(312): onStop
5、在AllList中式点心击张开
08-31 08:54:14.286: INFO/ActivityLifeDemo(312): onRestart
08-31 08:54:14.286: INFO/ActivityLifeDemo(312): onStart
08-31 08:54:14.296: INFO/ActivityLifeDemo(312): onResume

经过日记信息,大家能够看出。Activity的运转进度:onCreate—onStart—onResume;下重返键时:onPause—onStop—onDestroy
正如上边正是,当按下再次来到键时,此Activity弹出栈,程序销毁。确实如此,我们再次张开时的起步进度又回到onCreate—onStart—onResume。OK,运行未来按下Home键,回到Launcher,查看打字与印刷新闻:onPause—onStop,再度展开的运维进度:onRestart—onStart—onResume。

俺们透过对Activity的各个操作,构成了Activity的生命周期,大家看看无论对Activity做什么样的操作,都会吸收到相关的回调方法,那么大家在付出的进度中通过这么些回调方法就能够写职业,比如说释放部分重量级的对象,互联网连接,数据库连接,文件读等等。

以下是各样艺术的详细表明:

onCreate():当 activity 第一遍创建时会被调用。在那么些办法中你供给做到有着的常规静态设置 ,比方创立一个视图( view )、绑定列表的多少等等。借使能捕获到 activity 状
态的话,那几个措施传递进入的 Bundle 对象将存放了 activity 当前的意况。调用该格局后一般会调用 onStart() 方法。

onRestart():在 activity 被甘休后再行运转时会调用该办法。其后续会调用 onStart 方法。

onStart()à当 activity 对于用户可知前即调用那几个法子。倘使 activity回到前台则随之调用 onResume() ,固然 activity 隐藏则调用onStop()

onResume():在 activity 开端与用户交互前调用该格局。在那儿该activity 处于 activity 栈的最上端,并且接受用户的输入。其一连会调用 onPause() 方法。

onPause():在系统一筹算算起初重操旧业其它 activity 时会调用该方法。那几个法子中司空眼惯用来交给一些还没封存的改造到漫长数据 中,停止部分动画或任何一些耗 CPU 的操作等等。无论
在该方法里面举行别的操作,都亟需较便捷到位,因为要是它不回来的话,下1个 activity 将不大概苏醒出来。假使 activity 重回到前台将
会调用 onResume() ,借使 activity 变得对用户不可知了将会调用onStop() 。

onStop():在 activity 对用户不可见时
将调用该办法。大概会因为方今 activity 正在被灭绝,或另八个 activity (已经存在的activity 或新
的 activity )已经回复了正筹算覆盖它,而调用该方法。如若 activity 正计划赶回与用户交互时继续会调用onRestart ,要是 activity 正在被释放则会调用 onDestroy 。

onDestroy():在 activity 被灭绝前
会调用该办法。那是 activity 能接到到的最终3个调用。可能会因为有人调用了 finish 方法使妥帖前activity 正在关闭,或系统
为了维护内部存款和储蓄器有时释放这些 activity的实例,而调用该办法。你能够用 isFinishing 方法来分别那三种差别的动静。

介绍

  • 本demo
    github下载地址!!!

  • 谷歌提供的demo的下载地址

  • 6.0权力的基本知识,以下是索要单独申请的权位,共分为九组,每组只要有二个权力申请成功了,就暗中认可整组权限都足以行使了。

      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
    
  • 以下是见惯司空权限,只须要在AndroidManifest.xml中申请就可以。

      android.permission.ACCESS_LOCATION_EXTRA_COMMANDS
      android.permission.ACCESS_NETWORK_STATE
      android.permission.ACCESS_NOTIFICATION_POLICY
      android.permission.ACCESS_WIFI_STATE
      android.permission.ACCESS_WIMAX_STATE
      android.permission.BLUETOOTH
      android.permission.BLUETOOTH_ADMIN
      android.permission.BROADCAST_STICKY
      android.permission.CHANGE_NETWORK_STATE
      android.permission.CHANGE_WIFI_MULTICAST_STATE
      android.permission.CHANGE_WIFI_STATE
      android.permission.CHANGE_WIMAX_STATE
      android.permission.DISABLE_KEYGUARD
      android.permission.EXPAND_STATUS_BAR
      android.permission.FLASHLIGHT
      android.permission.GET_ACCOUNTS
      android.permission.GET_PACKAGE_SIZE
      android.permission.INTERNET
      android.permission.KILL_BACKGROUND_PROCESSES
      android.permission.MODIFY_AUDIO_SETTINGS
      android.permission.NFC
      android.permission.READ_SYNC_SETTINGS
      android.permission.READ_SYNC_STATS
      android.permission.RECEIVE_BOOT_COMPLETED
      android.permission.REORDER_TASKS
      android.permission.REQUEST_INSTALL_PACKAGES
      android.permission.SET_TIME_ZONE
      android.permission.SET_WALLPAPER
      android.permission.SET_WALLPAPER_HINTS
      android.permission.SUBSCRIBED_FEEDS_READ
      android.permission.TRANSMIT_IR
      android.permission.USE_FINGERPRINT
      android.permission.VIBRATE
      android.permission.WAKE_LOCK
      android.permission.WRITE_SYNC_SETTINGS
      com.android.alarm.permission.SET_ALARM
      com.android.launcher.permission.INSTALL_SHORTCUT
      com.android.launcher.permission.UNINSTALL_SHORTCUT
    

叁、怎样运行三个新的Activity?

要开动一个新的Activity,大家得以由此调用Context中的startActivity来运营。像那样:

[java] view
plain

copy
print?

  1. <span style=”font-size:18px;”>Intent intent = new Intent(this, ActivityDemo.class);  
  2. startActivity(intent);  // Activity德姆o是亟需运营的Activity类  
  3. </span>  

透过下面的章程能够运转新的Activity了,但假若小编要从近些日子的Activity中传递数据到新的Activity呢?很简短:

[java] view
plain

copy
print?

  1. <span style=”font-size:18px;”>Intent intent = new Intent(this,ActivityDemo.class);  
  2. Bundle bundle = new Bundle();  
  3. bundle.putBoolean(“bool_key”, true);  
  4. intent.putExtras(bundle);  
  5. startActivity(intent);  
  6. </span>  

还有,一时候大家须求运转带重返值的Activity,简单的讲就是急需新开发银行的Activity重返时将值传递给运维它的Activity,像这么:

[java] view
plain

copy
print?

  1. <span style=”font-size:18px;”>Intent intent = new Intent(ActivityLifeDemo.this,RevalueActivity.class);  
  2. startActivityForResult(intent, 0x1001);  
  3. </span>  

ActivityLife德姆o是目前的Activity,运维RevalueActivity,我们在ActivityLife德姆o中供给得到RevalueActivity传回到的值。那么在RevalueActivity中就亟须这么写:

[java] view
plain

copy
print?

  1. <span style=”font-size:18px;”>Intent intent  = new Intent();  
  2. intent.putExtra(“revalue_key”,”haha-revalueActivity”);  
  3. setResult(0x1001, intent);</span>  

那么“revalue_key”值在哪儿获得呢?必须重写onActivityResult方法,通过决断requestCode,来分明

[java] view
plain

copy
print?

  1. <span style=”font-size:18px;”>if(requestCode==0x1001){  
  2.             String str = data.getStringExtra(“revalue_key”);  
  3.             Log.i(TAG, “再次来到的值为:”+str);  
  4.         }  
  5. </span>  

好了,详细的请看代码吧。下载地址:http://download.csdn.net/detail/tangcheng_ok/3580700

 

1. Log打印

demo中提供了LogUtil工具类(出自ZhaoKaiQiang),和一般性的Log一样包括Verbose、Debug、Info、Warn、Error、Assert几个级次,还协理将json或xml文本格式化后输出。
使用:
一)调整是不是打字与印刷。正式打包上线时可设为false:

LogUtil.init(true);

2)打印

//比如打印Error级日志
LogUtil.e(TAG, message);

//将jsonString格式化后打印出来
LogUtil.json(TAG, jsonString);

//将xmlString格式化后打印出来
LogUtil.xml(TAG, xmlString);

其壹Log工具类多少个相当的大的好处是,你能够便捷地跟踪到调用打字与印刷的具体地点。如图:

图片 2

Log跟踪1

点击MoviePresenter就可以定位到输出打字与印刷的地方

图片 3

Log跟踪2

报名手续

    1. 将targetSdkVersion设置为二三,注意,借使您将targetSdkVersion设置为>=二三,则必须依据Android谷歌的需求,动态的提请权限,如若您一时半刻不盘算辅助动态权限申请,则targetSdkVersion最大不得不设置为2二.
  • 二在AndroidManifest.xml中申请你供给的权杖,包涵常见权限和内需提请的特种权限。

  • 三.起来申请权限,此处分为三部。

  • (壹)检查是不是因而权限checkSelfPermission(),假如已经展开,则一贯做你想做的。

  • (二)倘若未打开,则决断是或不是供给向用户解释为什么申请权限shouldShowRequestPermissionRationale。

  • (三)倘使急需(即重回true),则能够弹出对话框提醒用户申请权限原因,用户确认后申请权限requestPermissions(),假设没有须要(即重回false),则直接申请权限requestPermissions()。
    (这里是壹单位代码,尾部有相比较完善的代码,整个demo能够在github中下载)。

图片 4

单个权限申请.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) {
                return;
            }

            Log.i(TAG, "requestPermission requestCode:" + requestCode);
            if (requestCode < 0 || requestCode >= requestPermissions.length) {
                Log.w(TAG, "requestPermission illegal requestCode:" + requestCode);
                return;
            }

            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);
//            return;
//        }

            int checkSelfPermission;
            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());
                return;
            }

            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);
            }
        }

图片 5

6.0之下系统的应用程序安装分界面.png

4、保存Activity运营状态

因而重写onSaveInstanceState()方法来促成Activity的运营状态,请留意以下几点:

1)由于activity 对象被中止或终止时,它依然保留在内部存款和储蓄器里面,关于它的积极分子音信和日前场地都以移动的,所以那时候能够保存Activity的情状,从而使用户所作的Activity的转移保存在内部存款和储蓄器中

二) 
当系统回收内部存款和储蓄器而将Activity销毁时,就不可能保存其情景,所以供给调用onSaveInstanceState()方法来促成意况的保存

叁) 
大多状态并无需保持状态音讯,比如按下再次来到键间接关闭程序,所以并不可能保险会调用onSaveInstanceState。借使调用了该办法,一般是在
onStop 方法在此以前且大概在 onPause 之后调用。固然如此,纵然你没做任何操作或尚未落到实处 onSaveInstanceState() 方
法,你的 activity 状态也能通过Activity 类里面暗中认可完毕的 onSaveInstanceState 方法恢复生机出来。特别是会为布局
中的视图( View )暗许调用onSaveInstanceState 方法,并在这么些点子中允许每三个视图提供它须要苏醒的任何音讯。大致每2个 Android框架中的 widget 都视意况实现了这几个艺术。

注:因为 onSaveInstanceState 方法
不自然会被调用,所以你应有只是用它来保存一些 activity 的转移进度气象(即 UI 的场馆),而不能够用来保存永远性数据。但你可以用 onPause 方法在用户距离 activity 时来保存永远性数据,比方须要保留到数据库的多寡。

有3个很好的方法能够用来视察应用程序保存景况的力量,就是轻易地打转你的设备来改动显示器的矛头。因为当显示屏方向更动时,系统为了给新的取向提供2个可能适度的替代能源,会销毁 activity 并新建三个新
的。由于那几个缘故,你的 activity 是不是能在其再一次制造时产生保存意况就显得愈加关键,因为用户时时会在选择应用程序时旋转显示屏的。

上文部分剧情参谋了:http://blog.csdn.net/sam_zhang1984/article/details/6430817,在此间感谢那位博主了。

2. 倾家荡产打字与印刷

demo中提供了CrashLogUtil工具类,用于在先后崩溃时,输出卓殊日志到手提式无线电话机本守田件中,方便在没连接计算机时翻看万分音信。
采取方法:
一.Application中初阶化

CrashLogUtil.getInstance().init(this);//初始化崩溃打印

2.可内定特别音信所出口的文件(地方)

File dirTemp = FileUtil.generateDirectory(FileUtil.getExternalCacheDir(), "temp");
File fileOutput = FileUtil.generateFile(dirTemp, fileName);
//指定输出文件
CrashLogUtil.getInstance().setFileOutput(fileOutput);

不点名的话,文件暗中同意就保存在/storage/emulated/0/Android/data/com.xxx.xxx/cache/temp下。
程序崩溃时,就能够到相应的岗位下查看万分消息,如图:

图片 6

查阅崩溃日志1

图片 7

翻开崩溃日志二

备注!!!

(一)checkSelfPermission:检查是否具备那个权力
(二)requestPermissions:请求权限,一般会弹出一个系统对话框,询问用户是不是展开这些权力。
(三)shouldShowRequestPermissionRationale:Android原生系统中,假设第3遍弹出权力申请的对话框,会产出“以往不再弹出”的提醒框,若是用户勾选了,你再申请权限,则shouldShowRequestPermissionRationale再次回到true,意思是说要给用户三个解释,告诉用户为啥要那一个权力。但是,在实际上费用中,须求专注的是,大多手机对原生系统做了修改,比方索爱,HUAWEI4的6.0的shouldShowRequestPermissionRationale
就一直重回false,而且在申请权限期,假如用户挑选了拒绝,则不会再弹出对话框了。。。。
所以说这几个地方有坑,笔者的缓和方法是,在回调里面管理,如若用户拒绝了那几个权力,则展开本金和利息用新闻分界面,由用户自个儿手动开启这么些权力。
(④)每个应用都有和好的权力管理分界面,里面有本利用申请的权柄以及各个意况,纵然用户已经允许了你申请的权能,他也随时可以关闭

图片 8

权限管理分界面.png

5、完全退出程序

经过地点的牵线,大家清楚当点击back键时,程序调用了
onDestroy方法,程序退出了,不过我们查阅其进度,开采调用了onDestroy方法之后那一个Activity还在运行。以至调用了
finish()方法之后先后还是可以够在过程中看看。通过下边这种办法得以兑现程序的完全脱离:

[java] view
plain

copy
print?

  1. <span style=”font-size:18px;”>Intent intent = new Intent();  
  2. Intent.setClass(context,MainActivity.class);  
  3. intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);  
  4. intent.putExtra(“flag”,EXIT_APPLICATION);  
  5. context.startActivity(intnet);   
  6. </span> 

三. 手提式有线电话机系统项目

demo中提供了SystemTypeUtil工具类,用于拍卖与手提式无线电话机系统项目相关的风浪。
局地部手提式无线话机的种类是基于原生Android系统改变的(如魅族,红米),所以在稍微功用的兑现上急需做合作处理,如设置情况栏中图像和文字的水彩情势、跳转到权限管理页面。

  • 剖断手提式无线电话机项目

boolean flag;
flag = SystemTypeUtil.isEMUI();//是否为华为手机
flag = SystemTypeUtil.isMIUI();//是否为小米手机
flag = SystemTypeUtil.isFlyme();//是否为魅族手机
  • 跳转到权限管理页面

//跳转,兼容不同手机系统类型
SystemTypeUtil.goToPermissionManager(context);
  • 设置意况栏中图像和文字的颜料方式(深色情势或亮色方式)

boolean isDark = true;//true表示深色模式,false表示亮色模式
Window window = getWindow();
boolean flag = SystemTypeUtil.setStatusBarLightMode(window, isDark);//返回true表示设置成功

深色方式功效图:

图片 9

深色形式

亮色情势功能图:

图片 10

亮色情势

三回申请八个权力

实则和报名2个权力是千篇壹律的,只是requestPermissions(final @NonNull
Activity activity,
final @NonNull String[] permissions, final int
requestCode),里面包车型地铁permissions给的参数多些而已。

图片 11

申请五个权限.png

 /**
     * 一次申请多个权限
     */
    public static void requestMultiPermissions(final Activity activity, PermissionGrant grant) {

        final List<String> permissionsList = getNoGrantedPermission(activity, false);
        final List<String> shouldRationalePermissionsList = getNoGrantedPermission(activity, true);

        //TODO checkSelfPermission
        if (permissionsList == null || shouldRationalePermissionsList == null) {
            return;
        }
        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);
        }

    }
  • 至于权限请求结果的回调。Activity实现ActivityCompat.OnRequestPermissionsResultCallback接口,重写onRequestPermissionsResult方法。

     @Override
      public void onRequestPermissionsResult(final int requestCode, @NonNull String[] permissions,
                                             @NonNull int[] grantResults) {
          PermissionUtils.requestPermissionsResult(this, requestCode, permissions, grantResults, mPermissionGrant);
    
      }
    

4. android 陆.0权力申请

android六.0后(targetSdkVersion>=2三)对于敏感权限,app须求向用户建议授权申请。
demo中提供了贰个比较轻松PermissionUtil工具类,用于陆.0本子的权杖申请。github上有不少高star的陆.0权力开源库,我们能够自动查阅。

此处说下一般的报名流程:
一)在 AndroidManifest.xml 加多权限申明。
2)使用 checkSelfPermission 检查某些权限是或不是早已申请。
3)权限未申请,使用 requestPermissions
申请权限,然后会回调onRequestPermissionsResult。
四)在 onRequestPermissionsResult 回调中推断权限是不是申请成功。
伍)假若申请倒闭,则动用 shouldShowRequestPermissionRationale
判定用户是不是勾选了 “不再晋升”。勾选了的话,则弹出叁个 Dialog
指导用户到安装界当面讲解予权限。没勾选的话,能够怎么都不做,也足以弹出弹出一个Dialog 引导用户到安装分界面授予权限。

任何申请权限工具类代码

package com.example.android.system.runtimepermissions;

import android.Manifest;
import android.app.Activity;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.provider.Settings;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AlertDialog;
import android.util.Log;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by qianxiaoai on 2016/7/7.
 */
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) {
            return;
        }

        Log.i(TAG, "requestPermission requestCode:" + requestCode);
        if (requestCode < 0 || requestCode >= requestPermissions.length) {
            Log.w(TAG, "requestPermission illegal requestCode:" + requestCode);
            return;
        }

        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) {
//            return;
//        }

        int checkSelfPermission;
        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());
            return;
        }

        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) {
            return;
        }

        //TODO
        Log.d(TAG, "onRequestPermissionsResult permissions length:" + permissions.length);
        Map<String, Integer> perms = new HashMap<>();

        ArrayList<String> notGranted = new ArrayList<>();
        for (int i = 0; i < permissions.length; 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<String> permissionsList = getNoGrantedPermission(activity, false);
        final List<String> shouldRationalePermissionsList = getNoGrantedPermission(activity, true);

        //TODO checkSelfPermission
        if (permissionsList == null || shouldRationalePermissionsList == null) {
            return;
        }
        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) {
            return;
        }
        Log.d(TAG, "requestPermissionsResult requestCode:" + requestCode);

        if (requestCode == CODE_MULTI_PERMISSION) {
            requestMultiResult(activity, permissions, grantResults, permissionGrant);
            return;
        }

        if (requestCode < 0 || requestCode >= requestPermissions.length) {
            Log.w(TAG, "requestPermissionsResult illegal requestCode:" + requestCode);
            Toast.makeText(activity, "illegal requestCode:" + requestCode, Toast.LENGTH_SHORT).show();
            return;
        }

        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<String> getNoGrantedPermission(Activity activity, boolean isShouldRationale) {

        ArrayList<String> permissions = new ArrayList<>();

        for (int i = 0; i < requestPermissions.length; 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());
                return null;
            }

            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");
                }

            }
        }

        return permissions;
    }

}

五. 互连网状态

demo中提供了NetworkUtil工具类,用于查询网络状态

//当前网络是否可用,返回true表示可用,false表示不可以用
NetworkUtil.isNetWorkAvailable(context);

//当前网络是否为wifi网络,返回true表示是,false表示不是
NetworkUtil.isWifiConnected(context);

//当前网络是否为手机移动网络,返回true表示是,false表示不是
NetworkUtil.isMobileConnected(context);

...

分界面调用代码

package com.example.android.system.runtimepermissions;

import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentTransaction;
import android.view.View;
import android.widget.Toast;

import com.example.android.common.logger.Log;

/**
 * Created by qianxiaoai on 2016/7/8.
 */
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();
                    break;
                case PermissionUtils.CODE_GET_ACCOUNTS:
                    Toast.makeText(PermissionActivity.this, "Result Permission Grant CODE_GET_ACCOUNTS", Toast.LENGTH_SHORT).show();
                    break;
                case PermissionUtils.CODE_READ_PHONE_STATE:
                    Toast.makeText(PermissionActivity.this, "Result Permission Grant CODE_READ_PHONE_STATE", Toast.LENGTH_SHORT).show();
                    break;
                case PermissionUtils.CODE_CALL_PHONE:
                    Toast.makeText(PermissionActivity.this, "Result Permission Grant CODE_CALL_PHONE", Toast.LENGTH_SHORT).show();
                    break;
                case PermissionUtils.CODE_CAMERA:
                    Toast.makeText(PermissionActivity.this, "Result Permission Grant CODE_CAMERA", Toast.LENGTH_SHORT).show();
                    break;
                case PermissionUtils.CODE_ACCESS_FINE_LOCATION:
                    Toast.makeText(PermissionActivity.this, "Result Permission Grant CODE_ACCESS_FINE_LOCATION", Toast.LENGTH_SHORT).show();
                    break;
                case PermissionUtils.CODE_ACCESS_COARSE_LOCATION:
                    Toast.makeText(PermissionActivity.this, "Result Permission Grant CODE_ACCESS_COARSE_LOCATION", Toast.LENGTH_SHORT).show();
                    break;
                case PermissionUtils.CODE_READ_EXTERNAL_STORAGE:
                    Toast.makeText(PermissionActivity.this, "Result Permission Grant CODE_READ_EXTERNAL_STORAGE", Toast.LENGTH_SHORT).show();
                    break;
                case PermissionUtils.CODE_WRITE_EXTERNAL_STORAGE:
                    Toast.makeText(PermissionActivity.this, "Result Permission Grant CODE_WRITE_EXTERNAL_STORAGE", Toast.LENGTH_SHORT).show();
                    break;
                default:
                    break;
            }
        }
    };

    /**
     * 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);
    }
}

6. File相关

demo中提供了FileUtil工具类,用于拍卖File相关的操作

  • CF闪存卡是不是能用

FileUtil.isSDCardAvailable();
  • 始建文件夹

/**
* 创建一个文件夹, 存在则返回, 不存在则新建
*
* @param String parentDirectory 父目录路径
* @param String directory  目录名
* @return 文件,null代表失败
*/
FileUtil.generateDirectory(parentDirectory, directory);

/**
 * 创建一个文件夹, 存在则返回, 不存在则新建
 *
 * @param File parentDirectory 父目录
 * @param String directory  目录名
 * @return 文件,null代表失败
 */
 FileUtil.generateDirectory(parentDirectory, directory)
  • 成立文件

/**
 * 创建一个文件, 存在则返回, 不存在则新建
 *
 * @param File catalog 父目录
 * @param String name    文件名
 * @return 文件,null代表失败
 */
 FileUtil.generateFile(catalog, name);

/**
* 根据全路径创建一个文件
*
* @param filePath 文件全路径
* @return 文件,null代表失败
*/
FileUtil.generateFile(filePath);
  • 去除文件

/**
* 删除文件/文件夹
* 如果是文件夹,则会删除其下的文件以及它本身
* @param file file
* @return true代表成功删除
*/
FileUtil.deleteFile(file);
  • 计量文件大小

/**
 * 计算文件/文件夹的大小
 * @param file 文件或文件夹
 * @return long 文件大小
 */
FileUtil.calculateFileSize(file);
  • 获得系统提供的公文夹路线

//返回"/data"目录
FileUtil.getDataDirectory();

//返回"/storage/emulated/0"目录
FileUtil.getExternalStorageDirectory();

//返回"/system"目录
FileUtil.getRootDirectory();

//返回"/cache"目录
FileUtil.getDownloadCacheDirectory();

//返回"/data/user/0/com.xxx.xxx/cache"目录
FileUtil.getCacheDir();

//返回"/data/user/0/com.xxx.xxx/files"目录
FileUtil.getFilesDir();

//返回"/storage/emulated/0/Android/data/com.xxx.xxx/cache"目录
FileUtil.getExternalCacheDir();

/**
 * @param String type 所放的文件的类型,传入的参数是Environment类中的DIRECTORY_XXX静态变量
 * @return 返回"/storage/emulated/0/xxx"目录
 *         例如传入Environment.DIRECTORY_ALARMS则返回"/storage/emulated/0/Alarms"
 */
FileUtil.getExternalStoragePublicDirectory(type);

/**
 * @param String type 所放的文件的类型,传入的参数是Environment类中的DIRECTORY_XXX静态变量
 * @return  返回"/storage/emulated/0/Android/data/com.xxx.xxx/files/Alarms"目录
 *          例如传入Environment.DIRECTORY_ALARMS则返回"/storage/emulated/0/Android/data/com.xxx.xxx/files/Alarms"
 */
FileUtil.getExternalFilesDir(type);

xml布局

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              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"
    >

    <FrameLayout
        android:id="@+id/content_fragment"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"/>

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="horizontal">

                <Button
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="Camera"
                    android:id="@+id/button_camera"
                    android:onClick="showCamera"/>

                <Button
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="RECORD_AUDIO"
                    android:onClick="recordAudio"/>
            </LinearLayout>

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="horizontal">

                <Button
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="GET_ACCOUNTS"
                    android:onClick="getAccounts"/>

                <Button
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="CALL_PHONE"
                    android:onClick="callPhone"/>
            </LinearLayout>

            <Button
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="PERMISSION_READ_PHONE_STATE"
                android:onClick="readPhoneState"/>

            <Button
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="ACCESS_FINE_LOCATION"
                android:onClick="accessFineLocation"/>

            <Button
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="ACCESS_COARSE_LOCATION"
                android:onClick="accessCoarseLocation"/>

            <Button
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="READ_EXTERNAL_STORAGE"
                android:onClick="readExternalStorage"/>

            <Button
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="WRITE_EXTERNAL_STORAGE"
                android:onClick="writeExternalStorage"/>

        </LinearLayout>
    </ScrollView>

</LinearLayout>

7. Activity栈管理

demo中提供了ActivityStackManager工具类,用于存放管理Activity栈。
运用流程:
一.在activity创设时调用pushOneActivity(Activity
activity)推入栈,可放于Activity基类中

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    mStackManager = ActivityStackManager.getInstance();
    mStackManager.pushOneActivity(this);
}

二.在activity销毁时调用popOneActivity(Activity
activity)弹出栈,可放于Activity基类中

@Override
protected void onDestroy() {
    mStackManager.popOneActivity(this);
    super.onDestroy();
}

3.当您想要退出某些Activity时,可调用exitActivity(Class cls)

mStackManager.exitActivity(CollectActivity.class);

四.当你想要退出整个应用(全部Activity)时,可调用exitApplication()

mStackManager.exitApplication();

还提供了别样方法,具体请查看demo代码

清单文件申请的权力

  <uses-permission android:name="android.permission.CAMERA"/>
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    <uses-permission android:name="android.permission.CALL_PHONE"/>
    <uses-permission android:name="android.permission.SEND_SMS"/>
    <uses-permission android:name="android.permission.READ_SMS"/>

    <uses-permission android:name="android.permission.GET_ACCOUNTS"/>
    <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.RECORD_AUDIO"/>

8. SharedPreferences

demo中提供了PreferenceUtil工具类,用于SharedPreferences的数额插入、读取等操作。

  • 获取SharedPreferences

SharedPreferences sp = PreferenceUtil.getPreference(context, spName);
  • 安顿数据

//int类型
PreferenceUtil.putInt(sp, key, value);
//String类型
PreferenceUtil.putString(sp, key, value);
//boolean类型
PreferenceUtil.putBoolean(sp, key, value);
//float类型
PreferenceUtil.putFloat(sp, key, value);
//long类型
PreferenceUtil.putLong(sp, key, value);
  • 读取数据

//int类型
PreferenceUtil.getInt(sp, key, defaultValue);
//String类型
PreferenceUtil.getString(sp, key, defaultValue);
//boolean类型
PreferenceUtil.getBoolean(sp, key, defaultValue);
//float类型
PreferenceUtil.getFloat(sp, key, defaultValue);
//long类型
PreferenceUtil.getLong(sp, key, defaultValue);

//读取所有数据,返回Map
PreferenceUtil.getAll(sp);
  • 清空数据

PreferenceUtil.clearAll(sp);

有的 财富文件

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string-array name="permissions">
        <item>@string/permission_recode_audio_hint</item>
        <item>@string/permission_get_accounts_hint</item>
        <item>@string/permission_read_phone_hint</item>
        <item>@string/permission_call_phone_hint</item>
        <item>@string/permission_camera_hint</item>
        <item>@string/permission_access_fine_location_hint</item>
        <item>@string/permission_access_coarse_location_hint</item>
        <item>@string/permission_read_external_hint</item>
        <item>@string/permission_white_external_hint</item>
    </string-array>
</resources>

 <string name="permission_get_accounts_hint">没有此权限,无法开启这个功能,请开启权限。PERMISSION_GET_ACCOUNTS</string>
    <string name="permission_read_phone_hint">没有此权限,无法开启这个功能,请开启权限。PERMISSION_READ_PHONE_STATE</string>
    <string name="permission_call_phone_hint">没有此权限,无法开启这个功能,请开启权限。PERMISSION_CALL_PHONE</string>
    <string name="permission_camera_hint">没有此权限,无法开启这个功能,请开启权限。PERMISSION_CAMERA</string>
    <string name="permission_access_fine_location_hint">没有此权限,无法开启这个功能,请开启权限。PERMISSION_ACCESS_FINE_LOCATION</string>
    <string name="permission_access_coarse_location_hint">没有此权限,无法开启这个功能,请开启权限。PERMISSION_ACCESS_COARSE_LOCATION</string>
    <string name="permission_read_external_hint">没有此权限,无法开启这个功能,请开启权限。PERMISSION_READ_EXTERNAL_STORAGE</string>
    <string name="permission_white_external_hint">没有此权限,无法开启这个功能,请开启权限。PERMISSION_WRITE_EXTERNAL_STORAGE</string>
    <string name="permission_recode_audio_hint">没有此权限,无法开启这个功能,请开启权限。PERMISSION_RECORD_AUDIO</string>

9. Toast

demo中提供了ToastUtil工具类,方便吐司。
运用流程
一.Application中初叶化

ToastUtil.init(this);//初始化吐司

二.在要吐司的地点调用show

ToastUtil.show("hello world");

ToastUtil.show(R.string.appName);

10. 密度单位转变

demo提供了DensityUtil工具类,用于密度单位的改造

  • px转dp

int dp = DensityUtil.px2dp(context, px);
  • dp转px

int px = DensityUtil.dp2px(context, dp);
  • sp转px

int px = DensityUtil.sp2px(context, sp);
  • px转sp

int sp = DensityUtil.px2sp(context, px);

1壹. 高斯模糊

demo中提供了BlurUtil工具类,用于对Bitmap做高斯模糊管理,能够接纳Java原生格局和RenderScript方式。

  • Java原生格局

//使用Java实现的高斯模糊效果(性能较低,模糊半径0-100,越大越模糊)
Bitmap bitmapAfter = BlurUtil.javaBlur(bitmapBefore, 15, true);
  • RenderScript方式

/**
* 使用RenderScript实现的高斯模糊效果(性能较高,模糊半径0-25,越大越模糊)
* 需在module下的build.gradle中加入
* renderscriptTargetApi 19
* renderscriptSupportModeEnabled true
*/
Bitmap bitmapAfter = BlurUtil.rsBlur(MyApplication.getInstance(), bitmapBefore, 15);

图片 12

高斯模糊效果

12. 加密

demo中提供了HashCoderUtil工具类,用于md5加密和sha1加密。

  • md5加密

String encrpt = HashCoderUtil.md5Crypt(password.getBytes());
//加盐值
String encrpt = HashCoderUtil.md5Crypt(password.getBytes(),salt);
  • sha1加密

String encrpt = HashCoderUtil.sha1Crypt(password.getBytes());
//加盐值
String encrpt = HashCoderUtil.sha1Crypt(password.getBytes(),salt);

13. 其他

demo中还提供了一个CommonUtil,负担一些相比较杂碎的职能,举个例子

  • 获取道具唯壹ID号

String deviceId = CommonUtil.getDeviceUniqueId(context);
  • 创建/删除桌面连忙形式

//创建
CommonUtil.creatShortcut(context);
//删除
CommonUtil.delShortcut(context);
  • 扩展View的触摸范围

//扩大view上下左右10个单位触摸的范围
CommonUtil.expandViewTouchDelegate(view,10,10,10,10);

其余,BlankJ提供了三个种种工具类的开源项目,大家各取所需呢。
https://github.com/Blankj/AndroidUtilCode/blob/master/README-CN.md


详见代码请看demo,地址https://github.com/LJYcoder/DevBase
demo的剧情流程,请看《安卓开拓框架(MVP+主流框架+基类+工具类)—
开篇》

相关文章