|
2 | 2 |
|
3 | 3 | import com.genymobile.scrcpy.AndroidVersions;
|
4 | 4 | import com.genymobile.scrcpy.FakeContext;
|
| 5 | +import com.genymobile.scrcpy.util.AppListProcessor; |
5 | 6 | import com.genymobile.scrcpy.util.Ln;
|
6 | 7 | import com.genymobile.scrcpy.wrappers.ActivityManager;
|
7 | 8 | import com.genymobile.scrcpy.wrappers.ClipboardManager;
|
|
12 | 13 | import com.genymobile.scrcpy.wrappers.WindowManager;
|
13 | 14 |
|
14 | 15 | import android.annotation.SuppressLint;
|
| 16 | +import android.app.UiModeManager; |
| 17 | +import android.content.ComponentName; |
| 18 | +import android.content.Context; |
15 | 19 | import android.content.Intent;
|
16 | 20 | import android.app.ActivityOptions;
|
17 | 21 | import android.content.pm.ApplicationInfo;
|
18 | 22 | import android.content.pm.PackageManager;
|
| 23 | +import android.content.pm.ResolveInfo; |
| 24 | +import android.content.res.Configuration; |
19 | 25 | import android.os.Build;
|
20 | 26 | import android.os.Bundle;
|
21 | 27 | import android.os.IBinder;
|
|
25 | 31 | import android.view.KeyCharacterMap;
|
26 | 32 | import android.view.KeyEvent;
|
27 | 33 |
|
28 |
| -import java.util.ArrayList; |
29 | 34 | import java.util.List;
|
30 | 35 | import java.util.Locale;
|
31 | 36 |
|
@@ -221,95 +226,123 @@ private static int getCurrentRotation(int displayId) {
|
221 | 226 | return displayInfo.getRotation();
|
222 | 227 | }
|
223 | 228 |
|
224 |
| - public static List<DeviceApp> listApps() { |
225 |
| - List<DeviceApp> apps = new ArrayList<>(); |
226 |
| - PackageManager pm = FakeContext.get().getPackageManager(); |
227 |
| - for (ApplicationInfo appInfo : getLaunchableApps(pm)) { |
228 |
| - apps.add(toApp(pm, appInfo)); |
| 229 | + public static void startApp(Intent launchIntent, int displayId, boolean forceStop) { |
| 230 | + Bundle options = null; |
| 231 | + if (Build.VERSION.SDK_INT >= AndroidVersions.API_26_ANDROID_8_0) { |
| 232 | + ActivityOptions launchOptions = ActivityOptions.makeBasic(); |
| 233 | + launchOptions.setLaunchDisplayId(displayId); |
| 234 | + options = launchOptions.toBundle(); |
229 | 235 | }
|
230 | 236 |
|
231 |
| - return apps; |
232 |
| - } |
233 |
| - |
234 |
| - @SuppressLint("QueryPermissionsNeeded") |
235 |
| - private static List<ApplicationInfo> getLaunchableApps(PackageManager pm) { |
236 |
| - List<ApplicationInfo> result = new ArrayList<>(); |
237 |
| - for (ApplicationInfo appInfo : pm.getInstalledApplications(PackageManager.GET_META_DATA)) { |
238 |
| - if (appInfo.enabled && getLaunchIntent(pm, appInfo.packageName) != null) { |
239 |
| - result.add(appInfo); |
240 |
| - } |
| 237 | + ActivityManager am = ServiceManager.getActivityManager(); |
| 238 | + if (forceStop) { |
| 239 | + am.forceStopPackage(launchIntent.getComponent().getPackageName()); |
241 | 240 | }
|
242 |
| - |
243 |
| - return result; |
| 241 | + am.startActivity(launchIntent, options); |
244 | 242 | }
|
245 | 243 |
|
246 |
| - public static Intent getLaunchIntent(PackageManager pm, String packageName) { |
247 |
| - Intent launchIntent = pm.getLaunchIntentForPackage(packageName); |
248 |
| - if (launchIntent != null) { |
249 |
| - return launchIntent; |
250 |
| - } |
| 244 | + @SuppressLint("QueryPermissionsNeeded") |
| 245 | + public static List<ResolveInfo> getDrawerApps() { |
| 246 | + Context context = FakeContext.get(); |
| 247 | + PackageManager pm = context.getPackageManager(); |
| 248 | + Intent intent = new Intent(Intent.ACTION_MAIN, null); |
251 | 249 |
|
252 |
| - return pm.getLeanbackLaunchIntentForPackage(packageName); |
253 |
| - } |
| 250 | + UiModeManager uiModeManager = (UiModeManager) context.getSystemService(Context.UI_MODE_SERVICE); |
| 251 | + intent.addCategory(uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION? |
| 252 | + Intent.CATEGORY_LEANBACK_LAUNCHER : Intent.CATEGORY_LAUNCHER); |
254 | 253 |
|
255 |
| - private static DeviceApp toApp(PackageManager pm, ApplicationInfo appInfo) { |
256 |
| - String name = pm.getApplicationLabel(appInfo).toString(); |
257 |
| - boolean system = (appInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0; |
258 |
| - return new DeviceApp(appInfo.packageName, name, system); |
| 254 | + return pm.queryIntentActivities(intent, 0); |
259 | 255 | }
|
260 | 256 |
|
261 |
| - @SuppressLint("QueryPermissionsNeeded") |
262 |
| - public static DeviceApp findByPackageName(String packageName) { |
263 |
| - PackageManager pm = FakeContext.get().getPackageManager(); |
264 |
| - // No need to filter by "launchable" apps, an error will be reported on start if the app is not launchable |
265 |
| - for (ApplicationInfo appInfo : pm.getInstalledApplications(PackageManager.GET_META_DATA)) { |
266 |
| - if (packageName.equals(appInfo.packageName)) { |
267 |
| - return toApp(pm, appInfo); |
| 257 | + public static Intent getIntentFromAppDrawer(String query, boolean isPackageName){ |
| 258 | + AppListProcessor appListProcessor = new AppListProcessor(isPackageName, true, query); |
| 259 | + query = query.toLowerCase(Locale.getDefault()); |
| 260 | + Context context = FakeContext.get(); |
| 261 | + PackageManager pm = context.getPackageManager(); |
| 262 | + |
| 263 | + for (ResolveInfo drawerApp : getDrawerApps()) { |
| 264 | + String packageName = drawerApp.activityInfo.packageName; |
| 265 | + String label = drawerApp.loadLabel(pm).toString().toLowerCase(Locale.getDefault()); |
| 266 | + |
| 267 | + if (isPackageName){ |
| 268 | + if (packageName.equals(query)) { |
| 269 | + ComponentName componentName = new ComponentName(packageName, drawerApp.activityInfo.name); |
| 270 | + return new Intent().setComponent(componentName) |
| 271 | + .putExtra("APP_LABEL", drawerApp.loadLabel(pm).toString()); |
| 272 | + } else if (packageName.contains(query)){ |
| 273 | + appListProcessor.addPotentialMatchesPkgName(drawerApp); |
| 274 | + } |
| 275 | + } else { |
| 276 | + if (label.equals(query)) { |
| 277 | + appListProcessor.addExactMatchesLabel(drawerApp); |
| 278 | + } else if (label.contains(query)){ |
| 279 | + appListProcessor.addPotentialMatchesAppName(drawerApp); |
| 280 | + } |
268 | 281 | }
|
269 | 282 | }
|
270 | 283 |
|
271 |
| - return null; |
272 |
| - } |
273 |
| - |
274 |
| - @SuppressLint("QueryPermissionsNeeded") |
275 |
| - public static List<DeviceApp> findByName(String searchName) { |
276 |
| - List<DeviceApp> result = new ArrayList<>(); |
277 |
| - searchName = searchName.toLowerCase(Locale.getDefault()); |
278 |
| - |
279 |
| - PackageManager pm = FakeContext.get().getPackageManager(); |
280 |
| - for (ApplicationInfo appInfo : getLaunchableApps(pm)) { |
281 |
| - String name = pm.getApplicationLabel(appInfo).toString(); |
282 |
| - if (name.toLowerCase(Locale.getDefault()).startsWith(searchName)) { |
283 |
| - boolean system = (appInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0; |
284 |
| - result.add(new DeviceApp(appInfo.packageName, name, system)); |
285 |
| - } |
| 284 | + //Suggestions will show regardless if MULTIPLE_EXACT_LABELS |
| 285 | + Intent launchIntent = appListProcessor.getIntent(pm,false); |
| 286 | + if (launchIntent == null){ |
| 287 | + Ln.w("Trying to find from list of all apps"); |
| 288 | + return getIntentFromListOfAllApps(appListProcessor.getOrgQuery(), isPackageName); |
286 | 289 | }
|
287 |
| - |
288 |
| - return result; |
| 290 | + else if (launchIntent.getBooleanExtra("MULTIPLE_EXACT_LABELS", false)) { |
| 291 | + //Let processResolvedLists() return a "garbage" intent if there are multiple exact labels. |
| 292 | + // We want to avoid redundant check. This happens if first check "launchIntent == null" |
| 293 | + // becomes true since getIntentFromListOfAllApps() also calls processResolvedLists(). |
| 294 | + // This limitation can be removed to instead list possible exact label matches |
| 295 | + // from list of all apps also. |
| 296 | + return null; |
| 297 | + } |
| 298 | + return launchIntent; |
289 | 299 | }
|
290 | 300 |
|
291 |
| - public static void startApp(String packageName, int displayId, boolean forceStop) { |
292 |
| - PackageManager pm = FakeContext.get().getPackageManager(); |
293 |
| - |
294 |
| - Intent launchIntent = getLaunchIntent(pm, packageName); |
295 |
| - if (launchIntent == null) { |
296 |
| - Ln.w("Cannot create launch intent for app " + packageName); |
297 |
| - return; |
| 301 | + @SuppressLint("QueryPermissionsNeeded") |
| 302 | + public static Intent getIntentFromListOfAllApps(String query, boolean isPackageName){ |
| 303 | + AppListProcessor appListProcessor = new AppListProcessor(isPackageName, false, query); |
| 304 | + query = query.toLowerCase(Locale.getDefault()); |
| 305 | + Context context = FakeContext.get(); |
| 306 | + PackageManager pm = context.getPackageManager(); |
| 307 | + |
| 308 | + boolean isTV = false; |
| 309 | + UiModeManager uiModeManager = (UiModeManager) context.getSystemService(Context.UI_MODE_SERVICE); |
| 310 | + if (uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION) { |
| 311 | + isTV = true; |
298 | 312 | }
|
299 | 313 |
|
300 |
| - launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); |
301 |
| - |
302 |
| - Bundle options = null; |
303 |
| - if (Build.VERSION.SDK_INT >= AndroidVersions.API_26_ANDROID_8_0) { |
304 |
| - ActivityOptions launchOptions = ActivityOptions.makeBasic(); |
305 |
| - launchOptions.setLaunchDisplayId(displayId); |
306 |
| - options = launchOptions.toBundle(); |
| 314 | + for (ApplicationInfo appInfo : pm.getInstalledApplications(PackageManager.GET_META_DATA)) { |
| 315 | + String packageName = appInfo.packageName; |
| 316 | + String label = appInfo.loadLabel(pm).toString().toLowerCase(Locale.getDefault()); |
| 317 | + Intent launchIntent = isTV ? |
| 318 | + pm.getLeanbackLaunchIntentForPackage(packageName) : |
| 319 | + pm.getLaunchIntentForPackage(packageName); |
| 320 | + |
| 321 | + if (isPackageName){ |
| 322 | + if (packageName.equals(query) && launchIntent == null) { |
| 323 | + Ln.e("No launch intent for " + appInfo.loadLabel(pm) + " ["+packageName+"]"); |
| 324 | + return null; |
| 325 | + } else if (packageName.equals(query)) { |
| 326 | + return launchIntent.putExtra("APP_LABEL", label); |
| 327 | + }else if (packageName.contains(query) && launchIntent != null){ |
| 328 | + appListProcessor.addPotentialMatchesPkgName(pm.resolveActivity(launchIntent, 0)); |
| 329 | + } |
| 330 | + } else { |
| 331 | + if (launchIntent == null) { |
| 332 | + if (label.equals(query)){ |
| 333 | + Ln.w("Ignoring "+ appInfo.loadLabel(pm) + " ["+packageName+"] which has no launch intent"); |
| 334 | + } |
| 335 | + continue; |
| 336 | + } |
| 337 | + ResolveInfo resolveInfo = pm.resolveActivity(launchIntent, 0); |
| 338 | + if (label.equals(query)) { |
| 339 | + appListProcessor.addExactMatchesLabel(resolveInfo); |
| 340 | + } else if (label.contains(query)){ |
| 341 | + appListProcessor.addPotentialMatchesAppName(resolveInfo); |
| 342 | + } |
| 343 | + } |
307 | 344 | }
|
308 | 345 |
|
309 |
| - ActivityManager am = ServiceManager.getActivityManager(); |
310 |
| - if (forceStop) { |
311 |
| - am.forceStopPackage(packageName); |
312 |
| - } |
313 |
| - am.startActivity(launchIntent, options); |
| 346 | + return appListProcessor.getIntent(pm,true); |
314 | 347 | }
|
315 | 348 | }
|
0 commit comments