使用限定符来控制布局
在之前学习碎片的时候我们知道,碎片主要是给平板这样的大屏幕设备使用的。但是我们在编写程序时一般是不会专门编写一个为平板而设计的应用,因为以后维护起来就需要同时维护手机和平板两个版本的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>