使用限定符來控制布局
在之前學(xué)習(xí)碎片的時(shí)候我們知道徒蟆,碎片主要是給平板這樣的大屏幕設(shè)備使用的杉辙。但是我們?cè)诰帉懗绦驎r(shí)一般是不會(huì)專門編寫一個(gè)為平板而設(shè)計(jì)的應(yīng)用薛匪,因?yàn)橐院缶S護(hù)起來就需要同時(shí)維護(hù)手機(jī)和平板兩個(gè)版本的APP移必。所以為了解決這樣的問題Android中是提供了一種使用限定符的方法來讓程序更具使用設(shè)備自動(dòng)的加載不同的布局啄踊。
例如我們先將在手機(jī)里面使用的程序的布局代碼編寫完(activity_main.xml)掖蛤,我們接著在res的目錄下新建一個(gè)layout-large的文件夾杀捻,在這里文件夾里面編寫為平板的布局。然后分別在手機(jī)和平板上運(yùn)行這個(gè)程序蚓庭,會(huì)發(fā)現(xiàn)運(yùn)行時(shí)的布局是不同的致讥。這是因?yàn)閘arge是Android中的一種限定符,而Android中還有許多的限定符:
所以以后編寫程序時(shí)器赞,就可以使用限定符來為不同的設(shè)備提供不同的程序服務(wù)了拄踪。
隨時(shí)退出程序
當(dāng)我們編寫程序時(shí)候,有時(shí)會(huì)遇到這種情況拳魁,即我們想要退出程序時(shí)惶桐,點(diǎn)擊back鍵,卻發(fā)現(xiàn)必須要回到上一個(gè)活動(dòng)潘懊,只有當(dāng)所有的活動(dòng)都“回歸”完畢姚糊,才能夠順利的退出程序。當(dāng)然直接使用home鍵確實(shí)可以返回到桌面授舟,但是程序是仍然在后臺(tái)掛起運(yùn)行的救恨,所以我們就需要編寫一段能夠讓我們隨時(shí)隨地退出程序的代碼。
首先是創(chuàng)建一個(gè)新類用來管理所有的活動(dòng):
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){ //添加活動(dòng)
activities.add(activity);
}
public static void removeActivity(Activity activity){ //移除活動(dòng)
activities.remove(activity);
}
public static void finishAll(){ //銷毀所有活動(dòng)
for(Activity activity : activities){
activity.finish();
}
activities.clear();
}
}
我們創(chuàng)建了一個(gè)ActivityCollector新類释树,并為它添加了管理活動(dòng)的方法肠槽,包括添加活動(dòng),移除活動(dòng)和銷毀活動(dòng)奢啥。
接著我們來創(chuàng)建一個(gè)所有活動(dòng)的父類:
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秸仙,以后所有的活動(dòng)就都可以繼承自BaseActivity,并且當(dāng)所有活動(dòng)創(chuàng)建時(shí)候就都會(huì)被添加進(jìn)ActivityCollector來進(jìn)行統(tǒng)一的管理桩盲,讓我們要銷毀所有的活動(dòng)時(shí)寂纪,只需要調(diào)用finishAll()即可。
為程序申請(qǐng)權(quán)限
在Android系統(tǒng)中有很多的權(quán)限赌结,我們可以將它們大致分為普通權(quán)限和危險(xiǎn)權(quán)限捞蛋。普通權(quán)限指的是那些不會(huì)對(duì)用戶的安全和隱私造成威脅的權(quán)限,這一部分權(quán)限系統(tǒng)為自動(dòng)的幫我們申請(qǐng)柬姚,我們不管是作為用戶還是開發(fā)者都不用手動(dòng)的去管理這些權(quán)限拟杉;而危險(xiǎn)權(quán)限則是需要我們手動(dòng)申請(qǐng)才能夠使用的,例如獲取聯(lián)系人的信息量承、撥打電話等等搬设,如果不給程序權(quán)限穴店,則有關(guān)程序的這部分功能就不能使用。
危險(xiǎn)權(quán)限的的個(gè)數(shù)很少焕梅,可以用一張圖來概括迹鹅,而張圖以外的所有權(quán)限就是普通權(quán)限了:
為了更好的理解申請(qǐng)危險(xiǎn)權(quán)限的步驟,我們可以來寫一個(gè)demo來親身體驗(yàn)一下贞言,首先是創(chuàng)建一個(gè)空項(xiàng)目斜棚,然后為布局設(shè)置一個(gè)按鈕,之后修改主代碼:
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{
//獲得權(quán)限之后你想做的事情
}
}
});
}
@Override
public void onRequestPermissionsResult(int requestCode,String[] permission,int[] grantResult){
switch(requestCode){
case 1:
if(grantResult.length>0 && grantResult[0] ==PackageManager.PERMISSION_GRANTED){
//獲得權(quán)限之后你想做的事情
}
else{
Toast.makeText(this, "申請(qǐng)權(quán)限失敗", Toast.LENGTH_SHORT).show();
}
break;
default:
}
}
}
讓我們來分析一下代碼的主要意義该窗。首先是在點(diǎn)擊的方法中判斷權(quán)限是否已經(jīng)申請(qǐng)成功弟蚀,這里面使用的是ContextCompat.checkSelfPermission()方法,該方法需要傳入2個(gè)參數(shù)酗失,第一個(gè)參數(shù)是就是Context义钉,第二個(gè)參數(shù)是需要申請(qǐng)的權(quán)限名。然后是使用PackageManager.PERMISSION_GRANTED來進(jìn)行判斷规肴,相等則是申請(qǐng)成功捶闸,不相等則是沒有申請(qǐng)。如果沒有申請(qǐng)拖刃,我們就可以使用ActivityCompat.requestPermissions()方法來進(jìn)行申請(qǐng)删壮,該方法需要傳入
三個(gè)參數(shù):第一個(gè)參數(shù)就是Activity;第二個(gè)參數(shù)是需要申請(qǐng)的權(quán)限名兑牡,一般是傳入一個(gè)字符串進(jìn)去央碟;第三個(gè)參數(shù)是一個(gè)唯一的請(qǐng)求碼。如果申請(qǐng)成功均函,則直接寫我們想要做的活動(dòng)即可亿虽。
接著來看onRequestPermissionsResult()方法,當(dāng)調(diào)用完requestPermissions()方法之后苞也,系統(tǒng)會(huì)調(diào)出一個(gè)提示框來提醒用戶是否同意授權(quán)洛勉,但是不論是哪一種結(jié)果它都會(huì)回調(diào)onRequestPermissionsResult()方。在該方法中我們就來判斷用戶是做了哪種選擇即可墩朦。
最后要注冊(cè)權(quán)限:
<?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>