Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

List and launch apps faster, add option to launch new instance, show app suggestions #5572

Draft
wants to merge 1 commit into
base: dev
Choose a base branch
from

Conversation

4nric
Copy link

@4nric 4nric commented Nov 30, 2024

Show exact matches + other app labels with the keyword

scrcpy --start-app="?Camera"    
[server] ERROR: No unique launchable app named "Camera" found from app drawer
Found 2 exact matches:
 - Camera                         com.samsung.android.scan3d
 - Camera                         com.sec.android.app.camera
Found 2 other potential matches:
 - IP Camera                      com.shenyaocn.android.WebCam
 - Open Camera                    net.sourceforge.opencamera

Look for the app from pm.getInstalledApplications() (may take time) if not found in drawer. Also if string provided are with spaces, "?" may be dropped. If without spaces, "?" is still required to differentiate with package names. Package names can never have spaces.

scrcpy --start-app="?Device Care"
scrcpy --start-app="Device Care" 
[server] ERROR: No unique launchable app named "Device Care" found from app drawer
[server] WARN: Trying to find from list of all apps
[server] INFO: Starting app "Device care" [com.samsung.android.lool] on display 0...

Recognize system apps but ignore if they don't have a launch intent.

scrcpy --start-app=?Shell
...
[server] ERROR: No unique launchable app named "Shell" found from app drawer
[server] WARN: Trying to find from list of all apps
[server] WARN: Ignoring Shell [com.android.shell] which has no launch intent
[server] ERROR: No unique launchable app named "Shell" found from list of all apps
Found 1 other potential match:
 - Remote ADB Shell               com.cgutman.androidremotedebugger
scrcpy --start-app=com.android.shell
...
[server] ERROR: No launchable app with package name "com.android.shell" found from app drawer
[server] WARN: Trying to find from list of all apps
[server] ERROR: No launch intent for Shell [com.android.shell]

Try launch a new instance. App must support like Chrome, Samsung Gallery & Calculator, etc

scrcpy --start-app=+com.sec.android.app.popupcalculator --new-display
scrcpy --start-app=+?Gallery --new-display

image

Force stopping an app changed to - to accommodate + for new instance feature.

scrcpy --start-app=-com.android.chrome

--list-apps list drawer apps and does so almost twice as fast than previous. Also launching apps in main display or new display are faster, as long as the apps are found from app drawer.

Edit: document changes instead

@rom1v
Copy link
Collaborator

rom1v commented Dec 1, 2024

Thank you for the PR.

I didn't read the details, but could you explain a bit why this new method would be preferable (benefits/drawbacks)?

Here are some differences I observed between current scrcpy and the current version of this PR.

System apps are not listed separately.

Some items do not appear with this PR. For example:

 * Google Play Store              com.android.vending

Some items have a different name. With current scrcpy:

- Breezy Weather                 org.breezyweather
- VLC                            org.videolan.vlc

With this PR:

  VLC reporter                   org.videolan.vlc
  Weather                        org.breezyweather

The packages having the same label appear only once. With current scrcpy:

 * Calculator                     com.google.android.calculator
 - Calculator                     com.darkempire78.opencalculator
 - Gamepad Tester                 com.dylan.gamepad.tester.pro
 - Gamepad Tester                 ru.elron.gamepadtester

With this PR:

 Calculator                     com.darkempire78.opencalculator
 Gamepad Tester                 ru.elron.gamepadtester

@4nric
Copy link
Author

4nric commented Dec 1, 2024

Hello😊 This will instead list the apps available to launchers alphabetically.

public static List<ResolveInfo> getDrawerApps() {
Context context = FakeContext.get();
PackageManager packageManager = context.getPackageManager();
Intent intent = new Intent(Intent.ACTION_MAIN, null);
UiModeManager uiModeManager = (UiModeManager) context.getSystemService(Context.UI_MODE_SERVICE);
if (uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION){
intent.addCategory(Intent.CATEGORY_LEANBACK_LAUNCHER);
} else {
intent.addCategory(Intent.CATEGORY_LAUNCHER);
}
return packageManager.queryIntentActivities(intent, 0);
}

The missing labels if there are duplicates are now fixed in this commit: f8c32cf

In my device, the label for com.android.vending is Play Store. In my installed launcher, I removed all folders and sorted alphabetically. The list produced in this PR is exactly the same as in my launcher.

The benefit with this approach is that time can be shaved off because every time trying to launch an app or just build list, we no longer need to go through every installed application (which some system apps are not launchable), and filter it ourselves:

public static DeviceApp findByPackageName(String packageName) {
PackageManager pm = FakeContext.get().getPackageManager();
// No need to filter by "launchable" apps, an error will be reported on start if the app is not launchable
for (ApplicationInfo appInfo : pm.getInstalledApplications(PackageManager.GET_META_DATA)) {
if (packageName.equals(appInfo.packageName)) {
return toApp(pm, appInfo);
}
}
return null;
}

This mainly is for user-convenience (for me at least). I am planning on adding an option to specifically launch a specific activity, some activities of apps are exported. Even system ones that can't normally be launched from main default launcher. For this, I propose another list type, maybe "expert?" --list-apps=expert (unimplemented). This will instead go through all installed apps, check every activity if exported or not, then add to list. This one may take a long time to build the list.

I have been using Activity Launcher myself to directly launch to specific activities.

--start-app can then be modified easily to launch if for example, given this format:

--start-app='com.android.settings/com.android.settings.Settings$DevelopmentSettingsDashboardActivity'

Must be surrounded with single quote to escape $ if there is. Here's a proof of concept implemented in this commit: 574c425

Edit: Playstore typo, format, clarification

@4nric
Copy link
Author

4nric commented Dec 2, 2024

Hello @rom1v, I have made possible to show suggestions if there's no exact match for labels/package names, exact names and alike. The list refers to the same apps that are listed in launcher app drawers. For example, if there are multiple apps installed with "Camera" in its label, it will show this:

[server] ERROR: No unique app found named "Camera"
Found 2 exact matches:
 - Camera                         com.samsung.android.scan3d
 - Camera                         com.sec.android.app.camera
Found 2 potential matches:
 - IP Camera                      com.shenyaocn.android.WebCam
 - Open Camera                    net.sourceforge.opencamera

Same goes for packages names:

[server] ERROR: No app found with package name "com.android"
Found 3 potential matches:
 - Chrome                         com.android.chrome
 - Play Store                     com.android.vending
 - Settings                       com.android.settings

Package names can never contain spaces. This PR now also allows treating string passed to --start-app as app name or label instead as a package name if it contains a space.

For example, scrcpy --start-app="Play Store" is allowed, treated as label instead as package name though "?" was not indicated.

Previously, even if full app label is not entered, app with the closest label and is unique will still launch. I don't know if that is by design, but this PR requires full unique label/package name (no ambiguity).

In the original version, several queries need to be made before the app gets launched.

Mainly, this method gets called for all installed packages

public static Intent getLaunchIntent(PackageManager pm, String packageName) {
Intent launchIntent = pm.getLaunchIntentForPackage(packageName);
if (launchIntent != null) {
return launchIntent;
}
return pm.getLeanbackLaunchIntentForPackage(packageName);
}

And when finally launching the app, because only package name is provided to Device.startApp,
launch intent needs to be queried again, which i think is redundant.

Intent launchIntent = getLaunchIntent(pm, packageName);

Approach in this PR instead gets the already filtered intents. The system does it for us. And since this only limit to the list of apps that are visible in default launcher, there'd be no need to get the launch intent for all packages in the system.

@4nric
Copy link
Author

4nric commented Dec 2, 2024

PR5572_v3.0.mp4
original_v3.0.mp4

@4nric
Copy link
Author

4nric commented Dec 2, 2024

I have noticed that some apps are missing from each other, even have different label as mentioned (Play Store vs Google Play Store). Current scrcpy drops also some items that are normally listed in app drawer. Drive, Facebook, and Maps for example.

Screen recording above includes the approximate duration at the bottom. Current scrcpy takes almost twice as long, if not more, compared to this PR. The difference can also be felt when launching apps in main display and virtual display.

@4nric 4nric changed the title Replace how list of apps are obtained List and launch apps faster, add option to launch new instance, show app suggestions Dec 3, 2024
@4nric 4nric marked this pull request as draft December 4, 2024 01:37
@rom1v
Copy link
Collaborator

rom1v commented Dec 6, 2024

I just tested, it's not faster for me.

In the current scrcpy version, what takes time in is to call getApplicationLabel() for all apps:

String name = pm.getApplicationLabel(appInfo).toString();

In your PR, it's the same (app is a ResolveInfo):

app.loadLabel(context.getPackageManager());

Or did I miss something?

@4nric
Copy link
Author

4nric commented Dec 8, 2024

Hello @rom1v ignore this mess 😅 If resolving apps available to "launchers," label may differ ResolveInfo.activityInfo. Have a branch not pushed yet that also take into account that + the label from ApplicationInfo (current implentation)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants