将十六进制 颜色代码 转换为int类型数值
Color.parseColor("#FF00FF")
getColor在6.0中过时
MainActivity.this.getResources().getColor(R.color.colorTest)
用以下替换
ContextCompat.getColor(context, R.color.my_color)
//源码
public static final int getColor(Context context, int id)
{
final int version = Build.VERSION.SDK_INT;
if (version >= 23) {
return ContextCompatApi23.getColor(context, id);
} else {
return context.getResources().getColor(id);
}
}
SparseArray
SparseArray是android里为<Interger,Object>这样的Hashmap而专门写的class,目的是提高效率,其核心是折半查找函数(binarySearch)
Listview的Adapter的转换
如果ListView没有headerView或者footerView的时候,与listView相关联的Adapter就是传进来的参数Adapter,如果有,就将原来的Adapter包装成HeaderViewListAdapter,HeaderViewListAdapter有个方法getWrappedAdapter,该方法能返回被包装的HeaderViewListAdapter的ListAdapter。
HeaderViewListAdapter headerViewListAdapter = (HeaderViewListAdapter) listView.getAdapter();
ContactAdapter contactAdapter = (ContactAdapter) headerViewListAdapter.getWrappedAdapter();
使用View做虚线分割线
drawable/line_dash.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="line">
<stroke android:color="@color/colorBlack"
android:dashGap="2dp"
android:dashWidth="5dp"
android:width="1dp" />
<size android:width="1dp" />
</shape>
布局文件中:(需要设置 layerType为software)
<View
android:layout_width="match_parent"
android:layout_height="2dp"
android:background="@drawable/line_dash"
android:layerType="software"
/>
Android api23 删除HttpClient 相关类
在Module的gradle.build文件添加依赖,和 packagingOptions,和 useLibrary 'org.apache.http.legacy'
android {
compileSdkVersion 23
buildToolsVersion "23.0.2"
defaultConfig {
applicationId "com.egrid.webdemo"
minSdkVersion 16
targetSdkVersion 23
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
packagingOptions {
exclude 'META-INF/DEPENDENCIES'
exclude 'META-INF/NOTICE'
exclude 'META-INF/LICENSE'
exclude 'META-INF/LICENSE.txt'
exclude 'META-INF/NOTICE.txt'
}
//会加载Andrdoid自带的jar包 org.apache.http.legacy.jar
useLibrary 'org.apache.http.legacy'
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.1.1'
//下面这些不会起作用
compile 'org.apache.httpcomponents:httpclient:4.3.6'
compile 'org.apache.httpcomponents:httpcore:4.3.2'
}
在xml中使用系统的actionBarSize
- 在attrs.xml文件中定义
<resources>
<declare-styleable name="app">
<attr name="toolbarHeight" format="dimension" />
</declare-styleable>
</resources>
- 在styles.xml中自定义toolbarHeight为actionBarSize
<style name="BaseTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="colorButtonNormal">@color/blueLight</item>
<item name="colorControlHighlight">@color/background</item>
<item name="toolbarHeight">?android:attr/actionBarSize</item>
</style>
- 在布局xml中使用
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/toolbarHeight"
app:contentInsetStart="0dp"
app:layout_collapseMode="pin" />
Splash 的最佳实践
此方法是给主界面设置闪屏页主题,在主界面中再用代码换回主界面主题,实现无闪屏Activity达到闪屏页的效果。
- 闪屏主题
<resources>
<!-- 主界面主题 -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
<!-- 闪屏主题 -->
<style name="AppTheme.Launcher">
<item name="android:windowBackground">@drawable/launch_screen</item>
</style>
<resources>
- 闪屏界面背景drawable/launch_screen.xml
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
android:opacity="opaque">
<item android:drawable="@color/white" />
<bitmap
android:gravity="center"
android:src="@drawable/img_splash" />
</layer-list>
- 主界面设置主题
<activity
android:name=".ui.activity.MainActivity"
android:theme="@style/AppTheme.Launcher">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
- 主界面super.onCreate() 之前调用 onCall() 方法设置回应用主题
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceStated) {
setTheme(R.style.AppTheme);
super.onCreate(savedInstanceStated);
// ...
}
}
注:若有闪屏Activity可以直接使用主题设置闪屏背景,无需在布局设置背景,所以没有背景显示时的切换问题
链接:https://blog.youkuaiyun.com/zujack/article/details/69499350
TextView 设置和取消删除线的两种方法
设置删除线
- (推荐)通过按位或运算符|,将 TextView 原本的 Flags 属性和删除线一块设置。setPaintFlags内会对 TextView 进行重绘。
tv.setPaintFlags(tv.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
- 获取画笔后设置属性,重绘 TextView 。此方式有个问题,会把 TextView 原本的 Flags 属性替代,例如抗锯齿等。仔细查看,你会发现通过这种方式,文字有了锯齿。
tv.getPaint().setFlags(Paint.STRIKE_THRU_TEXT_FLAG);
tv.invalidate();
取消删除线
- (推荐)先对 Paint.STRIKE_THRU_TEXT_FLAG 属性取反,再用按位与运算符&,除去了删除线属性并保留了 TextView 原本的 Flags 属性。setPaintFlags内会对 TextView 进行重绘。
tv.setPaintFlags(tv.getPaintFlags() & (~Paint.STRIKE_THRU_TEXT_FLAG));
- 获取画笔后,清空 Flags 属性,再重绘 TextView 。此方式有个问题,会把 TextView 原本的所有 Flags 属性清空,例如抗锯齿等。仔细查看,你会发现通过这种方式,文字有了锯齿;
tv.getPaint().setFlags(0);
tv.invalidate();
参考:https://www.jb51.net/article/136661.htm
RecyclerView滚动到指定位置并置顶
// 自定义类
public class TopSmoothScroller extends LinearSmoothScroller {
public TopSmoothScroller(Context context) {
super(context);
}
@Override
protected int getHorizontalSnapPreference() {
return SNAP_TO_START;//具体见源码注释
}
@Override
protected int getVerticalSnapPreference() {
return SNAP_TO_START;//具体见源码注释
}
}
// 使用
LinearSmoothScroller scroller = new TopSmoothScroller(CourseActivity.this);
scroller.setTargetPosition(position);
linearLayoutManager.startSmoothScroll(scroller);
用shape画的虚线在真机上无法显示
在布局View添加属性 android:layerType="software"
安装debug包时手机(OPPO VIVO)显示INSTALL_FAILED_TEST_ONLY无法安装
Android Studio 3.0以后会在debug apk的manifest文件中加android:testOnly=”true” 属性,此属性无法在非开发者模式的手机上安装,VIVO OPPO即使在开发者模式也不能安装。
解决: 在gradle.properties文件中添加android.injected.testOnly=false
沉浸式模式
Android关于沉浸式状态栏总结
https://juejin.im/post/5989ded56fb9a03c3b6c8bde
Android状态栏微技巧,带你真正理解沉浸式模式
https://blog.youkuaiyun.com/guolin_blog/article/details/51763825
Android 沉浸式状态栏必知必会
https://juejin.im/entry/58cb481744d9040069f57266
刘海屏适配cutout
刘海屏适配 与WindowInsets,DisplayCutout使用
https://blog.youkuaiyun.com/yi_master/article/details/80309757
Android Studio配置文件路径修改
.AndroidStudio文件夹修改
修改文件C:\Program Files\Android\Android Studio\bin\idea.properties中的
idea.config.path=D:/Android/.AndroidStudio/config
idea.system.path=D:/Android/.AndroidStudio/system
.gradle文件夹的修改
设置Android Studio中的 Settings->Build,Execution,Deployment->Gradle 中的Service directory path为D:/Android/.gradle
.android文件夹的修改 添加一个系统的环境变量ANDROID_SDK_HOME为D:/Android/avd
https://www.jianshu.com/p/7a58c5f154c5
Android 常用尺寸
密度 | ldpi | mdpi | hdpi | xhdpi | xxhdpi | xxxhdpi |
---|---|---|---|---|---|---|
比例 | 0.75 | 1 | 1.5 | 2 | 3 | 4 |
密度数 | 120dpi | 160dpi | 240dpi | 320dpi | 480dpi | 640dpi |
代表分辨率 | 240*320 | 320*480 | 480*800 | 720*1280 | 1080*1920 | 1440*2560 |
Launcher And Home | 36*36 | 48*48 | 72*72 | 96*96 | 144*144 | 192*192 |
Action Bar And Tab | 24*24 | 32*32 | 48*48 | 64*64 | 96*96 | 128*128 |
Notification | 18*18 | 24*24 | 36*36 | 48*48 | 72*72 | 96*96 |
Background | 320*426 | 320*470 | 480*640 | 720*1280 | 1080*1920 | 1440*2560 |
Android Studio一直 Fetching Documentation...
修改“C:\Users\Administrator\.AndroidStudio2.3\config\options\jdk.table.xml”文件
<javadocPath>
<root type="composite">
<root type="simple" url="file://D:/Android/sdk/platforms/reference/" />
</root>
</javadocPath>
Android 颜色透明度换算
100% — FF
95% — F2
90% — E6
85% — D9
80% — CC
75% — BF
70% — B3
65% — A6
60% — 99
55% — 8C
50% — 80
45% — 73
40% — 66
35% — 59
30% — 4D
25% — 40
20% — 33
15% — 26
10% — 1A
5% — 0D
0% — 00
TabLayout添加 tab分割线
LinearLayout linearLayout = (LinearLayout) tabContent.getChildAt(0);
linearLayout.setShowDividers(LinearLayout.SHOW_DIVIDER_MIDDLE);
linearLayout.setDividerPadding(CommonUtils.dp2px(this, 8));
linearLayout.setDividerDrawable(ContextCompat.getDrawable(this,
R.drawable.layout_divider_vertical));
layout_divider_vertical.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/grayDark"/>
<size android:width="1dp"/>
</shape>
将十六进制 颜色代码 转换为int类型数值
Color.parseColor("#FF00FF")
getColor在6.0中过时
MainActivity.this.getResources().getColor(R.color.colorTest) 用一下替换
ContextCompat.getColor(context, R.color.my_color)
//源码 public static final int getColor(Context context, int id) {
final int version = Build.VERSION.SDK_INT;
if (version >= 23) {
return ContextCompatApi23.getColor(context, id);
} else {
return context.getResources().getColor(id);
}
}
SparseArray
SparseArray是android里为<Interger,Object>这样的Hashmap而专门写的class,目的是提高效率,其核心是折半查找函数(binarySearch)
Listview的Adapter的转换
如果ListView没有headerView或者footerView的时候,与listView相关联的Adapter就是传进来的参数Adapter,如果有,就将原来的Adapter包装成HeaderViewListAdapter,HeaderViewListAdapter有个方法getWrappedAdapter,该方法能返回被包装的HeaderViewListAdapter的ListAdapter。
HeaderViewListAdapter headerViewListAdapter = (HeaderViewListAdapter) listView.getAdapter(); ContactAdapter contactAdapter = (ContactAdapter) headerViewListAdapter.getWrappedAdapter();
使用View做虚线分割线
drawable/line_dash.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="line"
>
<stroke android:color="@color/colorBlack"
android:dashGap="2dp"
android:dashWidth="5dp"
android:width="1dp"
/>
<size android:width="1dp" />
</shape>
布局文件中:(需要设置 layerType为software)
<View
android:layout_width="match_parent"
android:layout_height="2dp"
android:background="@drawable/line_dash"
android:layerType="software"
/>
Android api23 删除HttpClient 相关类
在Module的gradle.build文件添加依赖,和 packagingOptions,和 useLibrary 'org.apache.http.legacy'
android {
compileSdkVersion 23
buildToolsVersion "23.0.2"
defaultConfig {
applicationId "com.egrid.webdemo"
minSdkVersion 16
targetSdkVersion 23
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
packagingOptions {
exclude 'META-INF/DEPENDENCIES'
exclude 'META-INF/NOTICE'
exclude 'META-INF/LICENSE'
exclude 'META-INF/LICENSE.txt'
exclude 'META-INF/NOTICE.txt'
}
//会加载Andrdoid自带的jar包 org.apache.http.legacy.jar
useLibrary 'org.apache.http.legacy'
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.1.1'
//下面这些不会起作用
compile 'org.apache.httpcomponents:httpclient:4.3.6'
compile 'org.apache.httpcomponents:httpcore:4.3.2'
}
横竖屏切换
android:configChanges="orientation|keyboardHidden|screenSize"
移动Android Studio默认的AVD目录(.android)
Move .android folder to E:\Android\
Create environment variable called ANDROID_SDK_HOME and set its value to E:\Android
Setting environment variable in Windows XP:
Right-click on My Computer and choose "Properties")
Click the "Advanced" tab
Click the button "Environment Variables".
Add New variable
https://stackoverflow.com/questions/3109473/moving-default-avd-configuration-folder-android
获取当前Activity的根视图
View rootView = getWindow().getDecorView().findViewById(android.R.id.content);
或者:
View rootView = findViewById(android.R.id.content);
或者:
View rootView = findViewById(android.R.id.content).getRootView();
关于android.R.id.content,开发者文档中并没有给予说明,但经过测试它应该是用来获取setContentView()中设置的View。
http://www.cnblogs.com/littlepanpc/p/4506294.html
Activity启动模式
https://inthecheesefactory.com/blog/understand-android-activity-launchmode/en
语言的复数形式
getQuantityString()
<resources>
<plurals
name="plural_name">
<item
quantity=["zero" | "one" | "two" | "few" | "many" | "other"]
>text_string</item>
</plurals>
</resources>
https://developer.android.com/guide/topics/resources/string-resource.html#Plurals
http://blog.youkuaiyun.com/a78270528/article/details/46791533
应用运行检测
/**
* 检测应用是否在后台运行
* [@param](https://my.oschina.net/u/2303379) context context
* [@return](https://my.oschina.net/u/556800) true 后台运行
*/
public static boolean isBackgroundRunning(final Context context) {
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> tasks = am.getRunningTasks(am.getRunningAppProcesses().size());
for (ActivityManager.RunningTaskInfo runningTaskInfo : tasks) {
if (runningTaskInfo.topActivity.getPackageName().equals(context.getPackageName())) {
Log.d(TAG, "packageName:" + runningTaskInfo.topActivity.getPackageName());
Log.d(TAG, "className:" + runningTaskInfo.topActivity.getClassName());
return true;
}
}
return false;
}
/**
* 检测应用是否在后台运行
* [@param](https://my.oschina.net/u/2303379) context context
* [@return](https://my.oschina.net/u/556800) true 前台运行
*/
public static boolean isFrontRunning(Context context) {
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningAppProcessInfo> runningProcesses = am.getRunningAppProcesses();
for (ActivityManager.RunningAppProcessInfo processInfo : runningProcesses) {
if (processInfo.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
for (String activeProcess : processInfo.pkgList) {
if (activeProcess.equals(context.getPackageName())) {
Log.d(TAG, "packageName:" + activeProcess);
Log.d(TAG, "className:" + processInfo.processName);
return true;
}
}
}
}
return false;
}
app过大错误
问题:
Error:Execution failed for task ':app:transformClassesWithDexForDevDebug'.
> com.android.build.api.transform.TransformException: com.android.ide.common.process.ProcessException: java.util.concurrent.ExecutionException: com.android.dex.DexIndexOverflowException: method ID not in [0, 0xffff]: 65536
修改文件:
build.gradle 文件
android {
compileSdkVersion 21
buildToolsVersion "21.1.0"
defaultConfig {
...
minSdkVersion 14
targetSdkVersion 21
...
// Enabling multidex support.
multiDexEnabled true
}
...
}
dependencies {
compile 'com.android.support:multidex:1.0.0'
}
Application类
<application
...
android:name="com.test.TestApplication">
...
</application>
public class TestApplication extends Application {
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
MultiDex.install(this);
}
}
详情:
https://developer.android.com/studio/build/multidex.html
http://stackoverflow.com/questions/26609734/how-to-enable-multidexing-with-the-new-android-multidex-support-library/38473900#38473900
Android 应用图标
m 1 48*48px
h 1.5 72*72px
xh 2 96*96px
xxh 3 144*144px
xxxh 4 192*192px
1.CTRL+A 再选择编辑中的“描边”就行。(选择自己喜欢的颜色、设置自己需要的宽度)
2.新建图层--矩形选框--反选--填充--快速蒙板--滤镜(多用几个)--退出蒙板--图层效果
3.矩形选区--快速蒙板--滤镜(各种滤镜有不同的效果,可以同时用多个滤镜)--退出蒙板--反选--删除--描边
ios和安卓切图换算比例
1dp(Android)=1pt(iOS)
以48dp@160dpi计算的话
mdpi 48px (160dpi, 1x) 基础尺寸
hdpi 72px (240dpi, 1.5x)
xhdpi 96px (320dpi, 2x) 同iOS @2x
xxdpi 144px (480dpi, 3x) 同iOS @3x
xxxdpi 192px (640dpi, 4x)
链接:http://www.zhihu.com/question/27038815/answer/34992846
android网络请求与页面切换
在android开发中会遇到使用fragment切换页面,并且切换的页面都会有网络请求,网络请求成功后会更新相应的fragment页面。如果使用异步网络请求组件android-async-http,会出现这样的情况,当你快速的切换fragment时,每个fragment都会发出新的请求。例如:fragmentA发了网络请求,又切换到了fragmentB,fragmentB又发了网络请求,然后快速的切换两个fragment,切换多次后可能会出现,fragmentA发出的请求返回成功并且使用handler发出消息请求改变fragmentA中的UI时,这时当前的页面正是fragmentB。此时会报空指针错误。
解决此类问题,可以通过第一次加载时缓存,再次切换到此页面时,只有下拉才能请求新数据。另一种方法是,设置一个public static volatile int flag;变量,如果flag为1时则表示当前页面在fragmentA中,当flag为2时表示当前页面在fragmentB中,只当handler收到消息并且flag=1时才能更新fragmentA中的数据。第二种方法实现起来比较繁锁,推荐使用第一种方法。其中1、2、3这些最好存放在一个枚举类型中。
[转]http://blog.youkuaiyun.com/wode_dream/article/details/41480271
访问UI线程
1)Activity.runOnUiThread(Runnable)
2)View.post(Runnable)
public void onClick(View v) {
new Thread(new Runnable() {
public void run() {
final Bitmap b = loadImageFromNetwork();
mImageView.post(new Runnable() {
public void run() {
mImageView.setImageBitmap(b);
}
});
}
}).start();
}
3)View.postDelayed(Runnable, long)
4)Handler
final Handler myHandler = new Handler();
(new Thread(new Runnable() {
@Override
public void run() {
final Bitmap b = loadImageFromNetwork();
myHandler.post(new Runnable() {
@Override
public void run() {
mImageView.setImageBitmap(b);
}
});
}
})).start();
}
ListView嵌套 父ListView高度设置
/**
* 调整ListView嵌套后,根据子ListView的高度重设父ListView的高度
* @param listView
*/
public static void setListViewHeightBasedOnChildren(ListView listView) {
ListAdapter listAdapter = listView.getAdapter();
if (listAdapter == null) {
return;
}
int totalHeight = 0;
for (int i = 0; i < listAdapter.getCount(); i++) {
View listItem = listAdapter.getView(i, null, listView);
listItem.measure(0, 0);
totalHeight += listItem.getMeasuredHeight();
}
ViewGroup.LayoutParams params = listView.getLayoutParams();
params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
listView.setLayoutParams(params);
}
代码创建控件
ImageView imageView = new ImageView(getActivity());
//父控件是LinearLayout
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
//相当于android:layout_gravity属性
params.gravity = Gravity.CENTER_VERTICAL;
imageView.setLayoutParams(params);
imageView.setScaleType(ImageView.ScaleType.FIT_XY);
Button button = new Button(getActivity());
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
button.setLayoutParams(params);
//相当于android:gravity属性
button.setGravity(Gravity.CENTER_VERTICAL);
linearLayout.addView(imageView);
linearLayout.addView(button);
文本拼接
%1表示第一个位置,$d表示数字,$s表示文本
<string name="sale_comment_text1">【%1$d】</string>
<string name="sale_comment_text2">%1$s评价%2$s</string>
getString(R.string.sale_comment_text1,pojo.getCommentType())
getString(R.string.sale_comment_text2,pojo.getCustomerName(),pojo.getSalesName())
拼接文本为:【2】,张三评价李四
textAppearance
textAppearanceInverse/
textAppearanceLarge/
textAppearanceLargeInverse/
textAppearanceMedium/
textAppearanceSmallInverse/
textAppearanceMediumInverse/
textAppearanceSmall/
代码中加下划线 textView.getPaint().setFlags(Paint. UNDERLINE_TEXT_FLAG ); //下划线 textView.getPaint().setAntiAlias(true);//抗锯齿
转:http://www.cnblogs.com/-cyb/archive/2011/08/02/Android_textAppearance.html
gradle dependencies 设置 版本号
ext{
compileLibVersion = '23.3.0'
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile "com.android.support:appcompat-v7:[$compileLibVersion]"
}
隐藏/移除ActionBar
//隐藏掉整个ActionBar,包括下面的Tabs
getSupportActionBar().hide();
//或
requestWindowFeature(Window.FEATURE_NO_TITLE);
//会保留tab标签
//高版本可以换成 ActionBar actionBar = getActionBar();
ActionBar actionBar = getSupportActionBar();
actionBar.setDisplayShowTitleEnabled(false);
actionBar.setDisplayShowHomeEnabled(false);
判断SDK版本
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
Window window = getWindow();
// Translucent status bar
window.setFlags(
WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS,
WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
Android M运行权限问题
一行代码解决Android M新的运行时权限问题: http://www.jianshu.com/p/d3a998ec04ad
Android Build.VERSION.SDK_INT兼容介绍
http://aijiawang-126-com.iteye.com/blog/1481572