使用限定符來控制布局
在之前學習碎片的時候我們知道,碎片主要是給平板這樣的大屏幕設備使用的。但是我們在編寫程序時一般是不會專門編寫一個為平板而設計的應用,因為以后維護起來就需要同時維護手機和平板兩個版本的APP。所以為了解決這樣的問題Android中是提供了一種使用限定符的方法來讓程序更具使用設備自動的加載不同的布局。
例如我們先將在手機里面使用的程序的布局代碼編寫完(activity_main.xml),我們接著在res的目錄下新建一個layout-large的文件夾,在這里文件夾里面編寫為平板的布局。然后分別在手機和平板上運行這個程序,會發現運行時的布局是不同的。這是因為large是Android中的一種限定符,而Android中還有許多的限定符:
所以以后編寫程序時,就可以使用限定符來為不同的設備提供不同的程序服務了。
隨時退出程序
當我們編寫程序時候,有時會遇到這種情況,即我們想要退出程序時,點擊back鍵,卻發現必須要回到上一個活動,只有當所有的活動都“回歸”完畢,才能夠順利的退出程序。當然直接使用home鍵確實可以返回到桌面,但是程序是仍然在后臺掛起運行的,所以我們就需要編寫一段能夠讓我們隨時隨地退出程序的代碼。
首先是創建一個新類用來管理所有的活動:
package com.example.yzbkaka.broadcastbestpractice;
import android.app.Activity;
import java.util.ArrayList;
import java.util.List;
public class ActivityCollector {
static List<Activity> activities = new ArrayList<>();
public static void addActivity(Activity activity){ //添加活動
activities.add(activity);
}
public static void removeActivity(Activity activity){ //移除活動
activities.remove(activity);
}
public static void finishAll(){ //銷毀所有活動
for(Activity activity : activities){
activity.finish();
}
activities.clear();
}
}
我們創建了一個ActivityCollector新類,并為它添加了管理活動的方法,包括添加活動,移除活動和銷毀活動。
接著我們來創建一個所有活動的父類:
package com.example.yzbkaka.broadcastbestpractice;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
public class BaseActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
ActivityCollector.addActivity(this);
}
protected void onDestroy(){
super.onDestroy();
ActivityCollector.removeActivity(this);
}
}
我們讓BaseActivity繼承自AppCoompatActivity,以后所有的活動就都可以繼承自BaseActivity,并且當所有活動創建時候就都會被添加進ActivityCollector來進行統一的管理,讓我們要銷毀所有的活動時,只需要調用finishAll()即可。
為程序申請權限
在Android系統中有很多的權限,我們可以將它們大致分為普通權限和危險權限。普通權限指的是那些不會對用戶的安全和隱私造成威脅的權限,這一部分權限系統為自動的幫我們申請,我們不管是作為用戶還是開發者都不用手動的去管理這些權限;而危險權限則是需要我們手動申請才能夠使用的,例如獲取聯系人的信息、撥打電話等等,如果不給程序權限,則有關程序的這部分功能就不能使用。
危險權限的的個數很少,可以用一張圖來概括,而張圖以外的所有權限就是普通權限了:
為了更好的理解申請危險權限的步驟,我們可以來寫一個demo來親身體驗一下,首先是創建一個空項目,然后為布局設置一個按鈕,之后修改主代碼:
package com.example.yzbkaka.requesttest;
import android.Manifest;
import android.content.pm.PackageManager;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button send = (Button)findViewById(R.id.start);
send.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(MainActivity.this,new String[]{Manifest.permission.CALL_PHONE},1);
}
else{
//獲得權限之后你想做的事情
}
}
});
}
@Override
public void onRequestPermissionsResult(int requestCode,String[] permission,int[] grantResult){
switch(requestCode){
case 1:
if(grantResult.length>0 && grantResult[0] ==PackageManager.PERMISSION_GRANTED){
//獲得權限之后你想做的事情
}
else{
Toast.makeText(this, "申請權限失敗", Toast.LENGTH_SHORT).show();
}
break;
default:
}
}
}
讓我們來分析一下代碼的主要意義。首先是在點擊的方法中判斷權限是否已經申請成功,這里面使用的是ContextCompat.checkSelfPermission()方法,該方法需要傳入2個參數,第一個參數是就是Context,第二個參數是需要申請的權限名。然后是使用PackageManager.PERMISSION_GRANTED來進行判斷,相等則是申請成功,不相等則是沒有申請。如果沒有申請,我們就可以使用ActivityCompat.requestPermissions()方法來進行申請,該方法需要傳入
三個參數:第一個參數就是Activity;第二個參數是需要申請的權限名,一般是傳入一個字符串進去;第三個參數是一個唯一的請求碼。如果申請成功,則直接寫我們想要做的活動即可。
接著來看onRequestPermissionsResult()方法,當調用完requestPermissions()方法之后,系統會調出一個提示框來提醒用戶是否同意授權,但是不論是哪一種結果它都會回調onRequestPermissionsResult()方。在該方法中我們就來判斷用戶是做了哪種選擇即可。
最后要注冊權限:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.yzbkaka.requesttest">
<uses-permission android:name="android.permission.CALL_PHONE"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>