Broadcast组件——收发广播应用——捕获屏幕的变更事件——回到桌面与切到任务列表
按下主页键会回到桌面,按下任务键会打开任务列表,这两个操作并未提供相应的按键处理方法,而是通过广播发出事件信息。
若想知晓是否回到桌面,以及是否打开任务列表,均需收听系统广播Intent.ACTION_CLOSE_SYSTEM_DIALOGS。
从收到的广播意图中获取原因reason字段,该字段值为homekey时表示回到桌面,值为recentapps时表示打开任务列表。
======================================================================================
布局:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="5dp"> <TextView android:id="@+id/tv_monitor" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="请按下主页键或者任务键,然后回到该页面观察结果" android:textColor="@color/black" android:textSize="17sp" /> </LinearLayout>
代码:
package com.example.myapplication; import androidx.appcompat.app.AppCompatActivity; import android.app.PictureInPictureParams; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.res.Configuration; import android.os.Build; import android.os.Bundle; import android.text.TextUtils; import android.util.Log; import android.util.Rational; import android.widget.TextView; public class MainActivity extends AppCompatActivity { private final static String TAG = "ReturnDesktopActivity"; private TextView tv_monitor; private String mDesc = ""; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv_monitor = findViewById(R.id.tv_monitor); initDesktopRecevier(); // 初始化桌面广播 } // 显示变更的状态 private void showChangeStatus(String reason) { mDesc = String.format("%s%s 按下了%s键\n", mDesc, DateUtil.getNowTime(), reason); tv_monitor.setText(mDesc); // 当前未开启画中画,则开启画中画模式 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && !isInPictureInPictureMode()) { // 创建画中画模式的参数构建器 PictureInPictureParams.Builder builder = new PictureInPictureParams.Builder(); // 设置宽高比例值,第一个参数表示分子,第二个参数表示分母 // 下面的10/5=2,表示画中画窗口的宽度是高度的两倍 Rational aspectRatio = new Rational(20,10); builder.setAspectRatio(aspectRatio); // 设置画中画窗口的宽高比例 // 进入画中画模式,注意enterPictureInPictureMode是Android8.0之后新增的方法 enterPictureInPictureMode(builder.build()); } } // 在进入画中画模式或退出画中画模式时触发 @Override public void onPictureInPictureModeChanged(boolean isInPicInPicMode, Configuration newConfig) { Log.d(TAG, "onPictureInPictureModeChanged isInPicInPicMode="+isInPicInPicMode); super.onPictureInPictureModeChanged(isInPicInPicMode, newConfig); if (isInPicInPicMode) // 进入画中画模式 { } else // 退出画中画模式 { } } // 初始化桌面广播 private void initDesktopRecevier() { desktopRecevier = new DesktopRecevier(); // 创建一个返回桌面的广播接收器 // 创建一个意图过滤器,只接收关闭系统对话框(即返回桌面)的广播 IntentFilter intentFilter = new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); registerReceiver(desktopRecevier, intentFilter); // 注册接收器,注册之后才能正常接收广播 } @Override protected void onDestroy() { super.onDestroy(); unregisterReceiver(desktopRecevier); // 注销接收器,注销之后就不再接收广播 } private DesktopRecevier desktopRecevier; // 声明一个返回桌面的广播接收器对象 // 定义一个返回到桌面的广播接收器 private class DesktopRecevier extends BroadcastReceiver { // 在收到返回桌面广播时触发 @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)) { String reason = intent.getStringExtra("reason"); // 获取变更原因 // 按下了主页键或者任务键 if (!TextUtils.isEmpty(reason) && (reason.equals("homekey") || reason.equals("recentapps"))) { showChangeStatus(reason); // 显示变更的状态 } } } } }
DateUtil:
package com.example.myapplication; import android.annotation.SuppressLint; import android.text.TextUtils; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; @SuppressLint("SimpleDateFormat") public class DateUtil { // 获取当前的日期时间 public static String getNowDateTime(String formatStr) { String format = formatStr; if (TextUtils.isEmpty(format)) { format = "yyyyMMddHHmmss"; } SimpleDateFormat sdf = new SimpleDateFormat(format); return sdf.format(new Date()); } // 获取当前的时间 public static String getNowTime() { SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss"); return sdf.format(new Date()); } // 获取当前的时间(精确到毫秒) public static String getNowTimeDetail() { SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss.SSS"); return sdf.format(new Date()); } public static String getNowDate() { SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd"); return sdf.format(new Date()); } public static String getDate(Calendar calendar) { Date date = calendar.getTime(); // 创建一个日期格式化的工具 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); // 将当前日期时间按照指定格式输出格式化后的日期时间字符串 return sdf.format(date); } public static String getMonth(Calendar calendar) { Date date = calendar.getTime(); // 创建一个日期格式化的工具 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM"); // 将当前日期时间按照指定格式输出格式化后的日期时间字符串 return sdf.format(date); } public static Date formatString(String strTime) { Date date = new Date(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); try { date = sdf.parse(strTime); } catch (Exception e) { e.printStackTrace(); } return date; } }
manifest
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.myapplication"> <uses-permission android:name="android.permission.VIBRATE" /> <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/Theme.MyApplication"> <activity android:name=".MainActivity" android:supportsPictureInPicture="true" android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>