diff --git a/.idea/caches/build_file_checksums.ser b/.idea/caches/build_file_checksums.ser index 61f8648..7373d53 100644 Binary files a/.idea/caches/build_file_checksums.ser and b/.idea/caches/build_file_checksums.ser differ diff --git a/.idea/caches/gradle_models.ser b/.idea/caches/gradle_models.ser index 2b28c59..cbb1c1c 100644 Binary files a/.idea/caches/gradle_models.ser and b/.idea/caches/gradle_models.ser differ diff --git a/Changelog.md b/Changelog.md index 50602e0..eda9f5f 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,10 +1,11 @@ Version 3.0 +* Feature: Search icons inside iconpacks * Feature: Posidon Launcher support * Bug: App Icon size issue on main list * Bug: Exclude other icon managers on main list * Bug: Masked icon preview always shows as empty (whitecons etc.,) -* +* Crash report Fixes and various performance improvements Version 1.3 diff --git a/app/build.gradle b/app/build.gradle index 1f4627a..11aa1c7 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -9,7 +9,7 @@ android { defaultConfig { applicationId "dev.ukanth.iconmanager" minSdkVersion 19 - targetSdkVersion 28 + targetSdkVersion 27 versionCode 3000 versionName "3.0.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" diff --git a/app/src/main/java/dev/ukanth/iconmgr/IconPackManager.java b/app/src/main/java/dev/ukanth/iconmgr/IconPackManager.java index 89ee077..d0a5786 100644 --- a/app/src/main/java/dev/ukanth/iconmgr/IconPackManager.java +++ b/app/src/main/java/dev/ukanth/iconmgr/IconPackManager.java @@ -62,10 +62,10 @@ public List updateIconPacks(IPObjDao ipObjDao, boolean forceReload, Mater packageList.add(info.packageName); } } - List rinfo = pm.queryIntentActivities(new Intent("com.gau.go.launcherex.theme"), PackageManager.GET_META_DATA); - rinfo.addAll(pm.queryIntentActivities(new Intent("com.novalauncher.THEME"), PackageManager.GET_META_DATA)); - rinfo.addAll(pm.queryIntentActivities(new Intent("org.adw.launcher.THEMES"), PackageManager.GET_META_DATA)); - + List rinfo = new ArrayList<>(); + for (String intent : IconPackUtil.ICON_INTENTS) { + rinfo.addAll(pm.queryIntentActivities(new Intent(intent), PackageManager.GET_META_DATA)); + } loadIconPack(rinfo, ipObjDao, installedIconPacks); return installedIconPacks; } @@ -75,12 +75,16 @@ public void insertIconPack(final IPObjDao ipObjDao, final String packageName) { final PackageManager pm = mContext.getPackageManager(); final IconPackUtil ip = new IconPackUtil(); //detect if it's iconpack or not - List rinfo = pm.queryIntentActivities(new Intent("com.gau.go.launcherex.theme"), PackageManager.GET_META_DATA); + List rinfo = new ArrayList<>(); + for (String intent : IconPackUtil.ICON_INTENTS) { + rinfo.addAll(pm.queryIntentActivities(new Intent(intent), PackageManager.GET_META_DATA)); + } + /*List rinfo = pm.queryIntentActivities(new Intent("com.gau.go.launcherex.theme"), PackageManager.GET_META_DATA); rinfo.addAll(pm.queryIntentActivities(new Intent("com.novalauncher.THEME"), PackageManager.GET_META_DATA)); rinfo.addAll(pm.queryIntentActivities(new Intent("org.adw.launcher.THEMES"), PackageManager.GET_META_DATA)); rinfo.addAll(pm.queryIntentActivities(new Intent("com.teslacoilsw.launcher.THEME"), PackageManager.GET_META_DATA)); rinfo.addAll(pm.queryIntentActivities(new Intent("com.anddoes.launcher.THEME"), PackageManager.GET_META_DATA)); - rinfo.addAll(pm.queryIntentActivities(new Intent("com.fede.launcher.THEME_ICONPACK"), PackageManager.GET_META_DATA)); + rinfo.addAll(pm.queryIntentActivities(new Intent("com.fede.launcher.THEME_ICONPACK"), PackageManager.GET_META_DATA));*/ List excludedPackage = Util.getExcludedPackages(); for (ResolveInfo ri : rinfo) { if (ri.activityInfo.packageName.equals(packageName) && !excludePackages.contains(packageName)) { @@ -108,53 +112,6 @@ public void insertIconPack(final IPObjDao ipObjDao, final String packageName) { } } - class ProcessPack implements Callable { - String pkgName; - IPObjDao ipObjDao; - boolean onlyMissed = false; - - public ProcessPack(String pkgName, IPObjDao ipObjDao, boolean onlyMissed) { - this.pkgName = pkgName; - this.ipObjDao = ipObjDao; - this.onlyMissed = onlyMissed; - } - - @Override - public IPObj call() throws Exception { - IPObj obj = new IPObj(); - IconPackUtil ip = new IconPackUtil(); - IconAttr attr = new IconAttr(); - if (!onlyMissed) { - obj.setIconPkg(pkgName); - PackageManager pm = mContext.getPackageManager(); - ApplicationInfo ai = pm.getApplicationInfo(obj.getIconPkg(), PackageManager.GET_META_DATA); - obj.setIconType("GO"); - obj.setInstallTime(pm.getPackageInfo(obj.getIconPkg(), 0).lastUpdateTime); - obj.setIconName(mContext.getPackageManager().getApplicationLabel(ai).toString()); - obj.setTotal(ip.calcTotal(obj.getIconPkg())); - attr.setDeleted(false); - obj.setMissed(ip.getMissingApps(obj.getIconPkg(), Util.getInstalledApps()).size()); - attr.setSize(Util.getApkSize(obj.getIconPkg())); - obj.setAdditional(attr.toString()); - ipObjDao.insert(obj); - sendIntent(pkgName); - } else { - IPObj obj2 = ipObjDao.queryBuilder().where(IPObjDao.Properties.IconPkg.eq(pkgName)).unique(); - if (obj2.getMissed() == 0 || obj2.getAdditional() == null) { - attr.setDeleted(false); - obj2.setMissed(ip.getMissingApps(obj2.getIconPkg(), Util.getInstalledApps()).size()); - attr.setSize(Util.getApkSize(obj2.getIconPkg())); - obj2.setAdditional(attr.toString()); - ipObjDao.update(obj2); - } - sendIntent(pkgName); - obj = obj2; - } - return obj; - } - - } - private void sendIntent(String pkgName) { Intent intentNotify = new Intent(); intentNotify.setAction("insertlist"); @@ -162,7 +119,6 @@ private void sendIntent(String pkgName) { mContext.sendBroadcast(intentNotify); } - private void loadIconPack(List rinfo, final IPObjDao ipObjDao, final List installedIconPacks) { ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(2); @@ -202,4 +158,51 @@ private void loadIconPack(List rinfo, final IPObjDao ipObjDao, fina Thread.currentThread().interrupt(); } } + + class ProcessPack implements Callable { + String pkgName; + IPObjDao ipObjDao; + boolean onlyMissed = false; + + public ProcessPack(String pkgName, IPObjDao ipObjDao, boolean onlyMissed) { + this.pkgName = pkgName; + this.ipObjDao = ipObjDao; + this.onlyMissed = onlyMissed; + } + + @Override + public IPObj call() throws Exception { + IPObj obj = new IPObj(); + IconPackUtil ip = new IconPackUtil(); + IconAttr attr = new IconAttr(); + if (!onlyMissed) { + obj.setIconPkg(pkgName); + PackageManager pm = mContext.getPackageManager(); + ApplicationInfo ai = pm.getApplicationInfo(obj.getIconPkg(), PackageManager.GET_META_DATA); + obj.setIconType("GO"); + obj.setInstallTime(pm.getPackageInfo(obj.getIconPkg(), 0).lastUpdateTime); + obj.setIconName(mContext.getPackageManager().getApplicationLabel(ai).toString()); + obj.setTotal(ip.calcTotal(obj.getIconPkg())); + attr.setDeleted(false); + obj.setMissed(ip.getMissingApps(obj.getIconPkg(), Util.getInstalledApps()).size()); + attr.setSize(Util.getApkSize(obj.getIconPkg())); + obj.setAdditional(attr.toString()); + ipObjDao.insert(obj); + sendIntent(pkgName); + } else { + IPObj obj2 = ipObjDao.queryBuilder().where(IPObjDao.Properties.IconPkg.eq(pkgName)).unique(); + if (obj2.getMissed() == 0 || obj2.getAdditional() == null) { + attr.setDeleted(false); + obj2.setMissed(ip.getMissingApps(obj2.getIconPkg(), Util.getInstalledApps()).size()); + attr.setSize(Util.getApkSize(obj2.getIconPkg())); + obj2.setAdditional(attr.toString()); + ipObjDao.update(obj2); + } + sendIntent(pkgName); + obj = obj2; + } + return obj; + } + + } } diff --git a/app/src/main/java/dev/ukanth/iconmgr/IconPackUtil.java b/app/src/main/java/dev/ukanth/iconmgr/IconPackUtil.java index 724f7d3..05dd697 100644 --- a/app/src/main/java/dev/ukanth/iconmgr/IconPackUtil.java +++ b/app/src/main/java/dev/ukanth/iconmgr/IconPackUtil.java @@ -42,6 +42,7 @@ import java.util.concurrent.Executors; import java.util.concurrent.Future; +import dev.ukanth.iconmgr.dao.IPObj; import dev.ukanth.iconmgr.util.Util; /** @@ -52,6 +53,17 @@ public class IconPackUtil { private static final String TAG = "MicoPacks"; private Resources iconPackres = null; + + public final static String[] ICON_INTENTS = new String[] { + "com.fede.launcher.THEME_ICONPACK", + "com.anddoes.launcher.THEME", + "com.novalauncher.THEME", + "com.teslacoilsw.launcher.THEME", + "com.gau.go.launcherex.theme", + "org.adw.launcher.THEMES", + "org.adw.launcher.icons.ACTION_PICK_ICON" + }; + public static @ColorInt int getPaletteColorFromApp(Icon app) { return getPaletteColorFromBitmap(app.getIconBitmap()); @@ -140,7 +152,6 @@ private Bitmap loadBitmap(String drawableName, String packageName) { ByteArrayOutputStream stream = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream); byte[] byteArray = stream.toByteArray(); - new Thread(() -> { Intent broadcastIntent = new Intent(); broadcastIntent.putExtra("image",byteArray); @@ -426,6 +437,27 @@ private Bitmap getMostAppropriateBackImage(Bitmap defaultBitmap, List mB } + /*public List lookUpSearch(final String searchQuery, List objList) { + try { + ExecutorService service = Executors.newFixedThreadPool(3); + List>> futures = new ArrayList>>(); + for (final IPObj attr : objList) { + Callable> callable = () -> getFilterIcons(attr.getIconPkg(), searchQuery); + futures.add(service.submit(callable)); + } + service.shutdown(); + + List outputs = new ArrayList<>(); + for (Future> future : futures) { + outputs.addAll(future.get()); + } + return outputs; + } catch (Exception e) { + e.printStackTrace(); + } + return new ArrayList(); + }*/ + public Set processXpp(final String packageName, List input) { try { ExecutorService service = Executors.newFixedThreadPool(5); @@ -436,7 +468,7 @@ public Set processXpp(final String packageName, List input) { if (isSupported(listPackages, attr.key)) { Bitmap iconBitmap = loadBitmap(attr.value, packageName); if (iconBitmap != null) { - return new Icon(attr.value, iconBitmap); + return new Icon(attr.value, packageName, iconBitmap); } } return new Icon(""); diff --git a/app/src/main/java/dev/ukanth/iconmgr/IconPreviewActivity.java b/app/src/main/java/dev/ukanth/iconmgr/IconPreviewActivity.java index 64e63de..6e426a0 100644 --- a/app/src/main/java/dev/ukanth/iconmgr/IconPreviewActivity.java +++ b/app/src/main/java/dev/ukanth/iconmgr/IconPreviewActivity.java @@ -24,6 +24,7 @@ import android.widget.GridLayout; import android.widget.ImageView; import android.widget.LinearLayout; +import android.widget.RelativeLayout; import android.widget.TextView; import android.widget.Toast; @@ -33,6 +34,8 @@ import com.afollestad.materialdialogs.StackingBehavior; import com.glidebitmappool.GlideBitmapPool; +import org.w3c.dom.Text; + import java.io.File; import java.io.FileOutputStream; import java.util.ArrayList; @@ -160,9 +163,6 @@ protected void onPause() { @Override protected void onDestroy() { super.onDestroy(); - /*if (iconViewReceiver != null) { - unregisterReceiver(iconViewReceiver); - }*/ } private void saveImage(Icon icon, String packageName) { @@ -279,6 +279,7 @@ protected void onPostExecute(Boolean aBoolean) { gridLayout.removeAllViews(); + if (themed_icons != null) { List list = new ArrayList(themed_icons); if (Prefs.isNonPreview() && nonthemed_icons != null) { @@ -290,34 +291,37 @@ protected void onPostExecute(Boolean aBoolean) { for (final Icon icon : list) { if (icon.getIconBitmap() != null) { + /*RelativeLayout relativeLayout=new RelativeLayout(mContext); + RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT); + params.addRule(RelativeLayout.ALIGN_PARENT_LEFT, RelativeLayout.TRUE); + relativeLayout.setLayoutParams(params); + TextView textView = new TextView(mContext); + textView.setText(icon.getPackageName());*/ ImageView image = new ImageView(mContext); image.setLayoutParams(params); image.setPadding(15, 15, 15, 15); image.setScaleType(ImageView.ScaleType.FIT_CENTER); image.setImageDrawable(new BitmapDrawable(getResources(), icon.getIconBitmap())); - image.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - new MaterialDialog.Builder(mContext) - .title(icon.getTitle()) - .positiveText(R.string.save) - .onPositive((dialog, which) -> { - if (isStoragePermissionGranted()) { - saveImage(icon, packageName); - dialog.dismiss(); - } - }) - .negativeText(R.string.close) - .icon(new BitmapDrawable(getResources(), icon.getIconBitmap())) - .show(); - } - }); + image.setOnClickListener(v -> new MaterialDialog.Builder(mContext) + .title(icon.getTitle()) + .positiveText(R.string.save) + .onPositive((dialog, which) -> { + if (isStoragePermissionGranted()) { + saveImage(icon, icon.getPackageName()); + dialog.dismiss(); + } + }) + .negativeText(R.string.close) + .icon(new BitmapDrawable(getResources(), icon.getIconBitmap())) + .show()); image.setOnLongClickListener(view -> { if (isStoragePermissionGranted()) { saveImage(icon, packageName); } return true; }); + //relativeLayout.addView(image); + //relativeLayout.addView(textView); gridLayout.addView(image); } } diff --git a/app/src/main/java/dev/ukanth/iconmgr/IconSearchActivity.java b/app/src/main/java/dev/ukanth/iconmgr/IconSearchActivity.java index 673faa8..ec92947 100644 --- a/app/src/main/java/dev/ukanth/iconmgr/IconSearchActivity.java +++ b/app/src/main/java/dev/ukanth/iconmgr/IconSearchActivity.java @@ -1,11 +1,24 @@ package dev.ukanth.iconmgr; +import android.Manifest; +import android.content.BroadcastReceiver; import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; import android.graphics.drawable.BitmapDrawable; import android.os.AsyncTask; +import android.os.Build; import android.os.Bundle; +import android.os.Environment; +import android.support.v13.app.ActivityCompat; +import android.support.v4.content.LocalBroadcastManager; import android.support.v7.app.AppCompatActivity; import android.util.DisplayMetrics; +import android.util.Log; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; @@ -13,11 +26,16 @@ import android.widget.GridLayout; import android.widget.ImageView; import android.widget.LinearLayout; +import android.widget.RelativeLayout; import android.widget.SearchView; +import android.widget.TextView; +import android.widget.Toast; import com.afollestad.materialdialogs.MaterialDialog; import com.glidebitmappool.GlideBitmapPool; +import java.io.File; +import java.io.FileOutputStream; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -32,6 +50,8 @@ public class IconSearchActivity extends AppCompatActivity { + private static final int WRITE_EXTERNAL_STORAGE = 12; + private MaterialDialog plsWait; private LinearLayout.LayoutParams params; @@ -41,6 +61,9 @@ public class IconSearchActivity extends AppCompatActivity { private SearchView mSearchView; + private BroadcastReceiver uiProgressReceiver; + private IntentFilter uiFilter; + @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); @@ -54,6 +77,24 @@ public boolean onCreateOptionsMenu(Menu menu) { return true; } + private void registerUIbroadcast() { + uiFilter = new IntentFilter("UPDATEUI"); + + uiProgressReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + byte[] byteArray = intent.getByteArrayExtra("image"); + Bitmap bitmap = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length); + ImageView image = new ImageView(getApplicationContext()); + image.setLayoutParams(params); + image.setPadding(15, 15, 15, 15); + image.setScaleType(ImageView.ScaleType.FIT_CENTER); + image.setImageDrawable(new BitmapDrawable(getResources(), bitmap)); + gridLayout.addView(image); + } + }; + } + private void setupSearchView(MenuItem searchItem) { mSearchView.setIconifiedByDefault(false); mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { @@ -108,7 +149,7 @@ protected void onCreate(Bundle savedInstanceState) { objList = ipObjDao.loadAll(); - + registerUIbroadcast(); } private void searchIcons(String query) { @@ -125,11 +166,13 @@ private void searchIcons(String query) { @Override public void onResume() { super.onResume(); + LocalBroadcastManager.getInstance(getApplicationContext()).registerReceiver(uiProgressReceiver, uiFilter); } @Override protected void onPause() { super.onPause(); + LocalBroadcastManager.getInstance(getApplicationContext()).unregisterReceiver(uiProgressReceiver); } @Override @@ -137,6 +180,25 @@ protected void onDestroy() { super.onDestroy(); } + private void saveImage(Icon icon, String packageName) { + String root = Environment.getExternalStorageDirectory().toString(); + File myDir = new File(root + "/micopacks/" + packageName); + myDir.mkdirs(); + String fname = icon.getTitle() + ".png"; + File file = new File(myDir, fname); + if (file.exists()) + file.delete(); + try { + FileOutputStream out = new FileOutputStream(file); + icon.getIconBitmap().compress(Bitmap.CompressFormat.PNG, 85, out); + out.flush(); + out.close(); + Toast.makeText(getApplicationContext(), "Saved successfully: " + file.getAbsolutePath(), Toast.LENGTH_SHORT).show(); + } catch (Exception e) { + Log.e("MICO", e.getMessage(), e); + } + } + private class IconsPreviewLoader extends AsyncTask { @@ -159,8 +221,12 @@ protected Boolean doInBackground(Void... voids) { while (!isCancelled()) { try { IconPackUtil packUtil = new IconPackUtil(); - for (IPObj obj : objList) { - themed_icons.addAll(packUtil.getFilterIcons(obj.getIconPkg(), query)); + for (int i = 0; i < objList.size(); i++) { + final int pos = i; + runOnUiThread(() -> { + plsWait.setTitle(mContext.getString(R.string.searching) + (" " + pos + "/" + objList.size())); + }); + themed_icons.addAll(packUtil.getFilterIcons(objList.get(i).getIconPkg(), query)); } return true; } catch (Exception e) { @@ -170,6 +236,7 @@ protected Boolean doInBackground(Void... voids) { return false; } + @Override protected void onPostExecute(Boolean aBoolean) { super.onPostExecute(aBoolean); @@ -189,6 +256,7 @@ protected void onPostExecute(Boolean aBoolean) { gridLayout.removeAllViews(); + if (themed_icons != null) { List list = new ArrayList(themed_icons); if (list != null && list.size() > 0) { @@ -196,29 +264,36 @@ protected void onPostExecute(Boolean aBoolean) { for (final Icon icon : list) { if (icon.getIconBitmap() != null) { + /* RelativeLayout relativeLayout=new RelativeLayout(mContext); + relativeLayout.setLayoutParams(params); + TextView textView = new TextView(mContext); + textView.setText(icon.getPackageName());*/ ImageView image = new ImageView(mContext); image.setLayoutParams(params); image.setPadding(15, 15, 15, 15); image.setScaleType(ImageView.ScaleType.FIT_CENTER); image.setImageDrawable(new BitmapDrawable(getResources(), icon.getIconBitmap())); - image.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - new MaterialDialog.Builder(mContext) - .title(icon.getTitle()) - .positiveText(R.string.save) - .onPositive((dialog, which) -> { - - }) - .negativeText(R.string.close) - .icon(new BitmapDrawable(getResources(), icon.getIconBitmap())) - .show(); - } - }); + image.setOnClickListener(v -> new MaterialDialog.Builder(mContext) + .title(icon.getTitle() + "\n" +" " + getAppNameByPackage(icon.getPackageName()) + " ") + .positiveText(R.string.save) + .onPositive((dialog, which) -> { + if (isStoragePermissionGranted()) { + saveImage(icon, icon.getPackageName()); + dialog.dismiss(); + } + }) + .negativeText(R.string.close) + .icon(new BitmapDrawable(getResources(), icon.getIconBitmap())) + .show()); image.setOnLongClickListener(view -> { + if (isStoragePermissionGranted()) { + saveImage(icon, icon.getPackageName()); + } return true; }); + //relativeLayout.addView(image); + //relativeLayout.addView(textView); gridLayout.addView(image); } } @@ -229,4 +304,57 @@ public void onClick(View v) { } } } + + private boolean isStoragePermissionGranted() { + if (Build.VERSION.SDK_INT >= 23) { + if (checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE) + == PackageManager.PERMISSION_GRANTED) { + Log.v("MICO", "Permission is granted"); + return true; + } else { + + Log.v("MICO", "Permission is revoked"); + ActivityCompat.requestPermissions(IconSearchActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, WRITE_EXTERNAL_STORAGE); + return false; + } + } else { //permission is automatically granted on sdk<23 upon installation + Log.v("MICO", "Permission is granted"); + return true; + } + } + + + private String getAppNameByPackage(String packageName){ + + final PackageManager pm = getApplicationContext().getPackageManager(); + ApplicationInfo ai; + try { + ai = pm.getApplicationInfo(packageName, 0); + } catch (final PackageManager.NameNotFoundException e) { + ai = null; + } + return (String) (ai != null ? pm.getApplicationLabel(ai) : packageName); + } + @Override + public void onRequestPermissionsResult(int requestCode, + String permissions[], int[] grantResults) { + switch (requestCode) { + case WRITE_EXTERNAL_STORAGE: { + // If request is cancelled, the result arrays are empty. + if (grantResults.length > 0 + && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + // permission was granted, yay! Do the + // contacts-related task you need to do. + Toast.makeText(getApplicationContext(), "Permission granted", Toast.LENGTH_SHORT).show(); + } else { + + // permission denied, boo! Disable the + // functionality that depends on this permission. + Toast.makeText(getApplicationContext(), "Permission denied", Toast.LENGTH_SHORT).show(); + } + return; + } + } + } + } diff --git a/app/src/main/java/dev/ukanth/iconmgr/util/LauncherHelper.java b/app/src/main/java/dev/ukanth/iconmgr/util/LauncherHelper.java index ac4e1e0..c6694b3 100644 --- a/app/src/main/java/dev/ukanth/iconmgr/util/LauncherHelper.java +++ b/app/src/main/java/dev/ukanth/iconmgr/util/LauncherHelper.java @@ -78,7 +78,7 @@ public class LauncherHelper { public static final int POSIDON = 28; public static final int TOTAL = 29; - + public static final int ROOTLESS = 30; @@ -156,6 +156,8 @@ public static int getLauncherId(String packageName) { return POSIDON; case "com.ss.launcher2": return TOTAL; + case "amirz.rootless.nexuslauncher": + return ROOTLESS; default: return UNKNOWN; }