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() { } }
参考链接:
NFC之PN532使用
1.唤醒PN532:
PC->PN532: 55 55 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ff 03 fd d4 14 01 17 00 PN532->PC: 00 00 FF 00 FF 00 00 00 FF 02 FE D5 15 16 00
2.获取卡UID,也就是卡的唯一ID号,全球就这一个(理论上)
PC->PN532: 00 00 FF 04 FC D4 4A 02 00 E0 00
协程
Android USB开发
用原生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-Refresh、TwinklingRefreshLayout 。 还集成了各种炫酷的 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 用户已经清楚一个包的数据,包括包名(清除包程序不能接收到这个广播)
Calendar 设置每周从周一开始
Calendar calendar = Calendar.getInstance(); calendar.setFirstDayOfWeek(Calendar.MONDAY);