Launcher start App WINDOWING_MODE_FREEFORM

WINDOWING_MODE_FREEFORM start App

核心思路:
这个windowmode需要从FullScreen —> Freeform,
需要在startActivity时候携带相关相关参数,把windowmode和launchBounds进行设置。

Android T


+++ b/frameworks/base/core/java/android/app/Instrumentation.java
@@ -1798,6 +1798,7 @@ public class Instrumentation {
     public ActivityResult execStartActivity(
             Context who, IBinder contextThread, IBinder token, Activity target,
             Intent intent, int requestCode, Bundle options) {
+        android.util.Log.d("tag",Log.getStackTraceString(new Throwable()));
         IApplicationThread whoThread = (IApplicationThread) contextThread;
         Uri referrer = target != null ? target.onProvideReferrer() : null;
         if (referrer != null) {

//打印堆栈,查看一下堆栈,清晰看见整个startActivity的过程
//清楚知道在哪里启动的onClick且一步步到对应的startActivity...,这里寻找最贴近context的startActivity...

java.lang.Throwable
                    at android.app.Instrumentation.execStartActivity(Instrumentation.java:1801)
                    at android.app.Activity.startActivityForResult(Activity.java:5522)
                    at com.android.launcher3.Launcher.startActivityForResult(Launcher.java:1895)
                    at com.android.launcher3.uioverrides.QuickstepLauncher.startActivityForResult(QuickstepLauncher.java:833)
                    at android.app.Activity.startActivity(Activity.java:5974)
                    at com.android.launcher3.views.ActivityContext.startActivitySafely(ActivityContext.java:356)
                    at com.android.launcher3.Launcher.startActivitySafely(Launcher.java:2259)
                    at com.android.launcher3.uioverrides.QuickstepLauncher.startActivitySafely(QuickstepLauncher.java:348)
                    at com.android.launcher3.touch.ItemClickHandler.startAppShortcutOrInfoActivity(ItemClickHandler.java:351)
                    at com.android.launcher3.touch.ItemClickHandler.onClickAppShortcut(ItemClickHandler.java:309)
                    at com.android.launcher3.touch.ItemClickHandler.onClick(ItemClickHandler.java:94)
                    at com.android.launcher3.touch.ItemClickHandler.$r8$lambda$c3IcSovkrXGdCZtXy0f_A5Sz5VA(Unknown Source:0)
                    at com.android.launcher3.touch.ItemClickHandler$$ExternalSyntheticLambda6.onClick(Unknown Source:0)
                    at com.android.launcher3.uioverrides.QuickstepLauncher.onItemClicked(QuickstepLauncher.java:387)
                    at com.android.launcher3.uioverrides.QuickstepLauncher$$ExternalSyntheticLambda9.onClick(Unknown Source:2)
                    at android.view.View.performClick(View.java:7542)
                    at android.view.View.performClickInternal(View.java:7519)
                    at android.view.View.-$$Nest$mperformClickInternal(Unknown Source:0)
                    at android.view.View$PerformClick.run(View.java:29476)
                    at android.os.Handler.handleCallback(Handler.java:942)
                    at android.os.Handler.dispatchMessage(Handler.java:99)
                    at android.os.Looper.loopOnce(Looper.java:201)
                    at android.os.Looper.loop(Looper.java:288)
                    at android.app.ActivityThread.main(ActivityThread.java:7924)
                    at java.lang.reflect.Method.invoke(Native Method)
                    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
                    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)
                    


+++ b/packages/apps/Launcher3/src/com/android/launcher3/views/ActivityContext.java

default boolean startActivitySafely(
            View v, Intent intent, @Nullable ItemInfo item) {
        Preconditions.assertUIThread();
        Context context = (Context) this;
        ...
        try {
            boolean isShortcut = (item instanceof WorkspaceItemInfo)
                    && (item.itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT
                    || item.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT)
                    && !((WorkspaceItemInfo) item).isPromise();
            if (isShortcut) {
                // Shortcuts need some special checks due to legacy reasons.
                startShortcutIntentSafely(intent, optsBundle, item);
            } else if (user == null || user.equals(Process.myUserHandle())) {
                // Could be launching some bookkeeping activity
                //add text
                Log.e("tag", "WINDOWING_MODE_FREEFORM launcher");
                ActivityOptions activityOptions = ActivityOptions.makeBasic();
                activityOptions.setLaunchWindowingMode(WINDOWING_MODE_FREEFORM);
                final Rect rect = new Rect(0, 0, 480, (int) (480 * 0.5f));
                activityOptions.setLaunchBounds(rect);
                context.startActivity(intent, activityOptions.toBundle());
                //context.startActivity(intent, optsBundle);
                //add text
            } else {
                context.getSystemService(LauncherApps.class).startMainActivity(
                        intent.getComponent(), user, intent.getSourceBounds(), optsBundle);
            }
        ...
    
    } 
    

补充:
如果发现修改无效,检查是否打开系统的自由窗口模式

adb shell settings put global enable_freeform_support  1
adb shell settings put global force_resizable_activities  1

或者

开发者模式下开启小窗功能,开发者模式下打开如下两个开关,然后重启即可.

Android13深入了解 Android 小窗口模式和窗口类型
copy
参考

FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
public static final int FLAG_ACTIVITY_RESET_TASK_IF_NEEDED = 0x00200000;
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
//如果没有新的,就会new 一个新的TASK,如果存在旧的TASK,使用旧的TASK(正在启动的Activity的Task已经在运行的话,那么新的Activity将不会启动)
在Android中,可以通过检查应用程序的清单文件中的intent-filter来确定一个应用程序是否为启动器应用程序(LAUNCHER_APP)。一个具有以下清单文件的应用程序将被认为是启动器应用程序: ``` <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.launcherapp"> <application> <activity android:name=".LauncherActivity" android:label="@string/app_name"> <!-- This intent filter identifies this activity as the main entry point --> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest> ``` 这里,我们使用了`android.intent.category.LAUNCHER`意图过滤器来标识此应用程序作为启动器应用程序,因为该过滤器指示此活动为该应用程序的主要入口点。 如果您想在代码中编程检查一个应用程序是否为启动器应用程序,您可以使用PackageManager的getLaunchIntentForPackage()方法。如果返回的Intent对象包含`CATEGORY_LAUNCHER`类别,则该应用程序被认为是启动器应用程序。以下是一个示例: ``` PackageManager pm = getPackageManager(); Intent launchIntent = pm.getLaunchIntentForPackage("com.example.launcherapp"); Set<String> categories = launchIntent.getCategories(); if (categories != null && categories.contains(Intent.CATEGORY_LAUNCHER)) { // The app is a launcher app } else { // The app is not a launcher app } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值