編輯:關於Android編程
引言:去年Android 6.0發布後,其新引入的(Requesting Permissions at Run Time)運行時權限就備受開發者關注,隨著今年國內手機廠商對6.0系統的普及,覺得大家有必要了解下這個新特性,因為在TargetSDK23+進行開發不注意這些會造成APP運行在6.0+手機上崩潰,這篇博文將對這個新特性進行探索。
在之前的SDK開發中,如果需要用到一些權限例如打電話,發短信只在AndroidManifest中配置一下就可以了,但是SDK23+以上用到一些危險敏感(Dangerous Permissions)權限就不僅僅是在AndroidManifest配置一下就可以了,需要在操作發生前需要讓用戶進行授予權限才能進行下一步的操作,跟iOS的權限處理很像,如果沒讓用戶授予權限或用戶拒絕了此權限再進行操作例如打電話就會造成軟件崩潰。
*如果你的app TargetSDK設置在了23以下那麼在6.0+系統中運行是不會崩潰的,當然你也可以TargetSDK一直設置在23以下,那麼這篇文章你就沒必要繼續看了:)
那麼到底哪些權限需要進行在運行時進行授權呢?看下官方的說明
Dangerous permissions
以上這些權限不僅僅需要在AndroidManifest配置,還需要在運行時讓用戶進行授予權限才能使用這些功能。<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxwPr/J0tS/tLW9tPK157uwysfQ6NKqvfjQ0NTL0NDKscrayKi1xKOsztLDx77N1/a49rXju/ewtMWltPK157uwtcTQoWRlbW+jrL+0v7TV4rj21MvQ0MqxyKjP3rW9tdfU9cO0u9jKwqGjPC9wPg0KPHA+PHN0cm9uZz4xo7rQ6NKqvatBUFC1xHRhcmdldFNka1ZlcnNpb27J6NbDtb0yM9LUyc+yosfS1NpBbmRyb2lkNi4w0tTJz8+1zbPUy9DQPC9zdHJvbmc+PC9wPg0KPHA+PGltZyBhbHQ9"這裡寫圖片描述" data-pin-nopin="true" src="/uploadfile/2016/0527/20160527031726750.png" title="\" />
2:在AndroidManifest中配置撥打電話的權限
3:在布局layout中我們就簡簡單單放個按鈕,點擊進行撥打電話(略)
4.1:如果不做運行時權限處理會怎麼樣呢?我們直接進行點擊按鈕撥打電話
public void CallPhone(View v) {
Intent intent = new Intent(Intent.ACTION_CALL);
Uri data = Uri.parse("tel:" + "10010");
intent.setData(data);
startActivity(intent);
}
運行效果:
可以看到在android 6.0系統上運行會崩潰
4.2:我們加上運行時權限的處理再運行
private static final int REQUESTCODE = 8;
public void CallPhone(View v) {
//檢查權限
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.CALL_PHONE)
!= PackageManager.PERMISSION_GRANTED) {
//沒有權限,申請權限
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.CALL_PHONE},
REQUESTCODE);
} else {
//已經擁有權限進行撥打
call();
}
}
API:
REQUESTCODE的作用是為了進行回調處理,因為申請權限是有回調結果的後面會說到。
ContextCompat.checkSelfPermission 主要用於檢測某個權限是否已經被授予,方法參數為(context,需要檢測的權限)方法返回值為PackageManager.PERMISSION_DENIED或者PackageManager.PERMISSION_GRANTED,當返回PackageManager.PERMISSION_DENIED時需要調用API進行權限申請。
ActivityCompat.requestPermissions 用於權限的申請,方法參數為(context,需要申請的權限數組,自定義的請求碼),系統會彈出一個申請權限的對話框。
運行效果:
可以看到程序已經成功進行了電話的撥打。
4.3 但是如果用戶拒絕了此權限並且設置了不再提醒怎麼辦呢?點擊按鈕就會沒響應了,是非常不友好的,如下。
稍稍改下代碼
public void CallPhone(View v) {
//檢查權限
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.CALL_PHONE)
!= PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.CALL_PHONE)) {
new AlertDialog.Builder(MainActivity.this)
.setMessage("app需要開啟權限才能使用此功能")
.setPositiveButton("設置", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.setData(Uri.parse("package:" + getPackageName()));
startActivity(intent);
}
})
.setNegativeButton("取消", null)
.create()
.show();
} else {
//申請權限
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.CALL_PHONE},
REQUESTCODE);
}
} else {
//已經擁有權限進行撥打
call();
}
}
這裡我們在申請權限前加了個判斷ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.CALL_PHONE)方法參數為(context,需要檢測的權限)如果返回true證明用戶上次點擊已經選了拒絕,所以我們進行一些友好的提示,這裡做的是進行進行提示並讓用戶跳轉到設置將權限打開。
運行效果:
5:OK 最後介紹下,申請權限的回調方法處理
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
switch (requestCode) {
case REQUESTCODE: {
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//用戶同意了授權
call();
} else {
//用戶拒絕了授權
// Toast.makeText(MainActivity.this, "Permission Denied", Toast.LENGTH_SHORT).show();
}
return;
}
}
}
這個方法跟onActivityResult比較類似,先判斷requestCode,之後在判斷用戶的授權狀態,grantResults數組代表了權限的結果數組,有點繞口,哈哈,之前申請權限是支持數組的,所以 onRequestPermissionsResult的返回結果也放到了一個數組裡面,數組grantResults[n] == PackageManager.PERMISSION_GRANTED代表這個權限已經被用戶授權了。
final:最後我們看下完整的代碼
/**
* blog:www.lijizhou.com
*/
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
private static final int REQUESTCODE = 8;
public void CallPhone(View v) {
//檢查權限
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.CALL_PHONE)
!= PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.CALL_PHONE)) {
new AlertDialog.Builder(MainActivity.this)
.setMessage("app需要開啟權限才能使用此功能")
.setPositiveButton("設置", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.setData(Uri.parse("package:" + getPackageName()));
startActivity(intent);
}
})
.setNegativeButton("取消", null)
.create()
.show();
} else {
//申請權限
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.CALL_PHONE},
REQUESTCODE);
}
} else {
//已經擁有權限進行撥打
call();
}
}
private void call() {
Intent intent = new Intent(Intent.ACTION_CALL);
Uri data = Uri.parse("tel:" + "10010");
intent.setData(data);
startActivity(intent);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
switch (requestCode) {
case REQUESTCODE: {
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//用戶同意了授權
call();
} else {
//用戶拒絕了授權
// Toast.makeText(MainActivity.this, "Permission Denied", Toast.LENGTH_SHORT).show();
}
return;
}
}
}
}
OK,一個利用android原始API進行的運行時權限處理就介紹完了,當然你也可以對此進行封裝方便使用
TextView與EditText詳解TextView 顧名思義:就是在界面上呈現文本信息,主要用於顯示,沒有特殊的事件響應。然而EditText與TexVi
現在新版360手機助手的界面都做得挺漂亮的,在切換底部導航時的波紋效果也很好看,剛好最近看了個開源項目才了解到原來Drawable做動畫效果也怎麼好用,所以就仿照360實
在Android中使用ImageView顯示圖片的時候發現圖片顯示不正,方向偏了或者倒過來了。 解決這個問題很自然想到的分兩步走: 1、自動識別圖像方向,計算旋轉角度;
1. Android Parcelable code generator顧名思義,這是個生成實現了Parcelable接口的代碼的插件。在你的類中