Android运行时权限

import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    // 申请权限
    private final int REQUEST_PERMISSION = 666;
    private boolean gotoAppDetail = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 判断系统版本
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            // 申请权限
            requestPermission();
        } else {
            // 初始化
            onInit();
        }
    }

    /**
     * 申请权限
     */
    private void requestPermission() {
        // 检查权限
        String[] permissions = {Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO, Manifest.permission.READ_PHONE_STATE, Manifest.permission.READ_EXTERNAL_STORAGE};
        List<String> checkPermissions = new ArrayList<>();

        for (String permission : permissions) {
            if (ActivityCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
                checkPermissions.add(permission);
            }
        }

        if (checkPermissions.size() > 0) {
            // 申请权限
            ActivityCompat.requestPermissions(this, checkPermissions.toArray(new String[0]), REQUEST_PERMISSION);
        } else {
            // 初始化
            onInit();
        }
    }

    /**
     * 申请权限回调
     *
     * @param requestCode
     * @param permissions
     * @param grantResults
     */
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        if (requestCode == REQUEST_PERMISSION) {
            int flag = 0;
            for (int i = 0; i < grantResults.length; i++) {
                if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {
                    flag = 1;
                    if (!ActivityCompat.shouldShowRequestPermissionRationale(this, permissions[i])) {
                        flag = 2;
                    }
                    break;
                }
            }

            if (flag == 0) {
                // 初始化
                onInit();
            } else if (flag == 1) {
                new AlertDialog.Builder(this).setTitle("提示").setMessage("请允许所有权限!").setPositiveButton("确定", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        // 申请权限
                        requestPermission();
                    }
                }).show();
            } else {
                new AlertDialog.Builder(this).setTitle("提示").setMessage("请手动允许所有权限!").setPositiveButton("确定", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        gotoAppDetail = true;
                        // 跳转到应用详情界面
                        gotoAppDetailIntent(MainActivity.this);
                    }
                }).show();
            }
        } else {
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        }
    }

    /**
     * 跳转到应用详情界面
     */
    private void gotoAppDetailIntent(Activity activity) {
        Intent intent = new Intent();
        intent.setAction(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
        intent.setData(Uri.parse("package:" + activity.getPackageName()));
        activity.startActivity(intent);
    }

    @Override
    protected void onRestart() {
        super.onRestart();
        // 跳转到应用详情界面返回
        if (gotoAppDetail) {
            gotoAppDetail = false;
            // 申请权限
            requestPermission();
        }
    }

    /**
     * 初始化
     */
    private void onInit() {
        
    }
}

参考链接:

安卓跳转到应用信息界面(用于方便用户打开权限)

Android 6.0运行时权限勾选不再询问后该如何处理?

用原生VideoView进行全屏播放时的问题

节选自:用原生VideoView进行全屏播放时的问题


import android.content.Context;
import android.util.AttributeSet;
import android.widget.VideoView;

public class MyVideoView extends VideoView {
    public MyVideoView(Context context) {
        super(context);
    }

    public MyVideoView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public MyVideoView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int width = getDefaultSize(0, widthMeasureSpec);
        int height = getDefaultSize(0, heightMeasureSpec);

        setMeasuredDimension(width, height);
    }
}

很好用的下拉刷新组件SmartRefreshLayout

节选自:Android智能下拉刷新框架-SmartRefreshLayout


SmartRefreshLayout以打造一个强大,稳定,成熟的下拉刷新框架为目标,并集成各种的炫酷、多样、实用、美观的Header和Footer。 正如名字所说,SmartRefreshLayout是一个“聪明”或者“智能”的下拉刷新布局,由于它的“智能”,它不只是支持所有的View,还支持多层嵌套的视图结构。 它继承自ViewGroup 而不是FrameLayout或LinearLayout,提高了性能。 也吸取了现在流行的各种刷新布局的优点,包括谷歌官方的 SwipeRefreshLayout, 其他第三方的 Ultra-Pull-To-RefreshTwinklingRefreshLayout 。 还集成了各种炫酷的 Header 和 Footer。

【Android】Android 监听apk安装替换卸载广播

节选自:【Android】Android 监听apk安装替换卸载广播


首先是要获取应用的安装状态,通过广播的形式

以下是和应用程序相关的Broadcast Action

ACTION_PACKAGE_ADDED 一个新应用包已经安装在设备上,数据包括包名(最新安装的包程序不能接收到这个广播)
ACTION_PACKAGE_REPLACED 一个新版本的应用安装到设备,替换之前已经存在的版本
ACTION_PACKAGE_CHANGED 一个已存在的应用程序包已经改变,包括包名
ACTION_PACKAGE_REMOVED 一个已存在的应用程序包已经从设备上移除,包括包名(正在被安装的包程序不能接收到这个广播)
ACTION_PACKAGE_RESTARTED 用户重新开始一个包,包的所有进程将被杀死,所有与其联系的运行时间状态应该被移除,包括包名(重新开始包程序不能接收到这个广播)
ACTION_PACKAGE_DATA_CLEARED 用户已经清楚一个包的数据,包括包名(清除包程序不能接收到这个广播)