diff --git a/app/build.gradle b/app/build.gradle index 5e6a64a..d8d1610 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -8,8 +8,8 @@ android { applicationId 'de.kaiserdragon.iconrequest' minSdkVersion 21 targetSdkVersion 31 - versionName "1.5.5" - versionCode 5 + versionName "1.7" + versionCode 6 } buildTypes { diff --git a/app/src/main/java/de/kaiserdragon/iconrequest/MainActivity.java b/app/src/main/java/de/kaiserdragon/iconrequest/MainActivity.java index 7e69b86..8ad68d8 100644 --- a/app/src/main/java/de/kaiserdragon/iconrequest/MainActivity.java +++ b/app/src/main/java/de/kaiserdragon/iconrequest/MainActivity.java @@ -1,6 +1,7 @@ package de.kaiserdragon.iconrequest; import android.content.ComponentName; +import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.os.Bundle; @@ -12,8 +13,15 @@ import androidx.appcompat.app.AppCompatDelegate; import androidx.appcompat.widget.Toolbar; +import java.util.ArrayList; + public class MainActivity extends AppCompatActivity { + private static final String TAG = "MainActivity"; + private static final boolean DEBUG = true; + + private static ArrayList appListFilter = new ArrayList<>(); + private Context context; @Override protected void onCreate(Bundle savedInstanceState) { @@ -40,6 +48,9 @@ public boolean onCreateOptionsMenu(Menu menu) { public void start(boolean update) { Intent intent = new Intent(Intent.ACTION_MAIN); + //if (DEBUG) Log.v(TAG, String.valueOf(getAvailableIconPacks(true))); + //populateView(appListFilter); + intent.putExtra("update", update); intent.setComponent(new ComponentName(getPackageName(), getPackageName() + ".RequestActivity")); startActivity(intent); @@ -59,4 +70,6 @@ public int loadData() { SharedPreferences sharedPreferences = getSharedPreferences("SharedPrefs", MODE_PRIVATE); return sharedPreferences.getInt("DarkModeState", -1); } + + } \ No newline at end of file diff --git a/app/src/main/java/de/kaiserdragon/iconrequest/RequestActivity.java b/app/src/main/java/de/kaiserdragon/iconrequest/RequestActivity.java index 7758a1e..4ab6514 100644 --- a/app/src/main/java/de/kaiserdragon/iconrequest/RequestActivity.java +++ b/app/src/main/java/de/kaiserdragon/iconrequest/RequestActivity.java @@ -9,7 +9,6 @@ import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; -import android.content.res.AssetManager; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.Canvas; @@ -85,12 +84,16 @@ public class RequestActivity extends AppCompatActivity { private static final ArrayList appListAll = new ArrayList<>(); private static String xmlString; private static boolean updateOnly; + private static boolean OnlyNew; + private static boolean SecondIcon; private static ArrayList appListFilter = new ArrayList<>(); + private static ArrayList IPackListFilter = new ArrayList<>(); private String ImgLocation; private String ZipLocation; private ViewSwitcher switcherLoad; private ActivityResultLauncher activityResultLauncher; private Context context; + private boolean IPackChoosen = false; public static void deleteDirectory(File path) { if (path.exists()) { @@ -209,6 +212,8 @@ public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); updateOnly = getIntent().getBooleanExtra("update", false); + OnlyNew = loadDataBool("SettingOnlyNew"); + SecondIcon = (loadDataBool("SettingRow") == true); setContentView(R.layout.activity_request); switcherLoad = findViewById(R.id.viewSwitcherLoadingMain); @@ -222,28 +227,36 @@ public void onCreate(Bundle savedInstanceState) { setSupportActionBar(toolbar); Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(true); - if (savedInstanceState == null) { + //if (savedInstanceState == null) { ExecutorService executors = Executors.newSingleThreadExecutor(); executors.execute(() -> { try { - // get included apps - parseXML(); - // compare list to installed apps - prepareData(); + if (OnlyNew | SecondIcon) { + prepareDataIPack(); //show only apps that arent in the selectable Icon Pack + } else { + prepareData(); //show all apps + } + } catch (Exception e) { e.printStackTrace(); } new Handler(Looper.getMainLooper()).post(() -> { - populateView(appListFilter); + if (OnlyNew | SecondIcon) { + populateView_Ipack(IPackListFilter); + } else { + findViewById(R.id.text_ipack_chooser).setVisibility(View.GONE); + populateView(appListFilter); + } switcherLoad.showNext(); }); }); - } else { - populateView(appListFilter); - switcherLoad.showNext(); - } + //} else { + // populateView_Ipack(IPackListFilter); + //populateView(appListFilter); + // switcherLoad.showNext(); + // } activityResultLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), new ActivityResultCallback() { @Override public void onActivityResult(ActivityResult result) { @@ -253,14 +266,19 @@ public void onActivityResult(ActivityResult result) { } public boolean onCreateOptionsMenu(Menu menu) { - if (updateOnly) { - getMenuInflater().inflate(R.menu.menu_request_update, menu); + if (OnlyNew && !IPackChoosen) { + getMenuInflater().inflate(R.menu.menu_iconpack_chooser, menu); } else { - getMenuInflater().inflate(R.menu.menu_request_new, menu); + if (updateOnly) { + getMenuInflater().inflate(R.menu.menu_request_update, menu); + } else { + getMenuInflater().inflate(R.menu.menu_request_new, menu); + } } return true; } + @Override public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == R.id.action_share) { @@ -285,18 +303,6 @@ public boolean onOptionsItemSelected(MenuItem item) { } } - private boolean visible(Drawable one, Drawable two) { - Bitmap bmp1 = getBitmapFromDrawable(one); - Bitmap bmp2 = getBitmapFromDrawable(two); - - ByteBuffer buffer1 = ByteBuffer.allocate(bmp1.getHeight() * bmp1.getRowBytes()); - bmp1.copyPixelsToBuffer(buffer1); - - ByteBuffer buffer2 = ByteBuffer.allocate(bmp2.getHeight() * bmp2.getRowBytes()); - bmp2.copyPixelsToBuffer(buffer2); - - return Arrays.equals(buffer1.array(), buffer2.array()); - } public void makeToast(String text) { Toast.makeText(context, text, Toast.LENGTH_SHORT).show(); @@ -372,7 +378,6 @@ private void actionSendSave() { } - private String[] actionSave() { final File imgLocation = new File(ImgLocation); final File zipLocation = new File(ZipLocation); @@ -457,52 +462,80 @@ private Bitmap getBitmapFromDrawable(Drawable drawable) { return bmp; } - private void parseXML() { + private void parseXML(String packageName) { + // load appfilter.xml from the icon pack package + Resources iconPackres = null; + + PackageManager pm = getPackageManager(); + try { + iconPackres = pm.getResourcesForApplication(packageName); XmlPullParserFactory xmlFactoryObject = XmlPullParserFactory.newInstance(); - XmlPullParser myparser = xmlFactoryObject.newPullParser(); - - AssetManager am = context.getAssets(); - String xmlLocation = "empty.xml"; - InputStream inputStream = am.open(xmlLocation); - myparser.setInput(inputStream, null); - - int activity = myparser.getEventType(); - while (activity != XmlPullParser.END_DOCUMENT) { - String name = myparser.getName(); - switch (activity) { - case XmlPullParser.START_TAG: - break; - case XmlPullParser.END_TAG: - if (name.equals("item")) { - try { - String xmlLabel = myparser.getAttributeValue(null, "drawable"); - String xmlComponent = - myparser.getAttributeValue(null, "component"); - - String[] xmlCode = xmlComponent.split("/"); - if (xmlCode.length > 1) { - String xmlPackage = xmlCode[0].substring(14); - String xmlClass = xmlCode[1].substring(0, xmlCode[1].length() - 1); - appListAll.add(new AppInfo(null, null, - xmlLabel, xmlPackage, xmlClass, false)); - if (DEBUG) Log.v(TAG, "XML APP: " + xmlLabel); + XmlPullParser xpp = xmlFactoryObject.newPullParser(); + + try { + InputStream appfilterstream = iconPackres.getAssets().open("appfilter.xml"); + + XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); + factory.setNamespaceAware(true); + xpp = factory.newPullParser(); + xpp.setInput(appfilterstream, "utf-8"); + } catch (IOException e1) { + Log.v(TAG, "No appfilter.xml file"); + } + + if (xpp != null) { + int activity = xpp.getEventType(); + while (activity != XmlPullParser.END_DOCUMENT) { + String name = xpp.getName(); + switch (activity) { + case XmlPullParser.START_TAG: + break; + case XmlPullParser.END_TAG: + if (name.equals("item")) { + try { + String xmlLabel = xpp.getAttributeValue(null, "drawable"); + String xmlComponent = + xpp.getAttributeValue(null, "component"); + + String[] xmlCode = xmlComponent.split("/"); + if (xmlCode.length > 1) { + String xmlPackage = xmlCode[0].substring(14); + String xmlClass = xmlCode[1].substring(0, xmlCode[1].length() - 1); + //if (DEBUG) Log.v(TAG, "XML APP: "+ xmlLabel); + Drawable icon = null; + if (SecondIcon){ + if (xmlLabel != null) icon = loadDrawable(xmlLabel, iconPackres, packageName); + } + appListAll.add(new AppInfo(icon, null, + xmlLabel, xmlPackage, xmlClass, false)); + // if (DEBUG) Log.v(TAG, "XML APP: " + xmlLabel +" " + xmlPackage); + } + } catch (Exception e) { + e.printStackTrace(); } - } catch (Exception e) { - e.printStackTrace(); } - } - break; + break; + } + activity = xpp.next(); } - activity = myparser.next(); } - } catch (Exception e) { - makeToast(getString(R.string.appfilter_assets)); - e.printStackTrace(); + } catch(Exception e){ + makeToast(getString(R.string.appfilter_assets)); + e.printStackTrace(); + } } - } + private Drawable loadDrawable(String drawableName, Resources iconPackres, String packageName) { + int id = iconPackres.getIdentifier(drawableName, "drawable", packageName); + if (id > 0) { + Drawable bitmap = ResourcesCompat.getDrawable(iconPackres, id, null); + return bitmap; + } + return null; + } + private void prepareData() { // sort the apps ArrayList arrayList = new ArrayList<>(); @@ -512,24 +545,46 @@ private void prepareData() { List list = pm.queryIntentActivities(intent, 0); Iterator localIterator = list.iterator(); if (DEBUG) Log.v(TAG, "list size: " + list.size()); - boolean notVisible = loadDataBool("SettingOnlyNew"); + for (int i = 0; i < list.size(); i++) { ResolveInfo resolveInfo = localIterator.next(); Drawable icon1 = getHighResIcon(pm, resolveInfo); - Drawable icon2 = resolveInfo.loadIcon(pm); - if (DEBUG) Log.v(TAG, String.valueOf(icon2)); AppInfo appInfo = new AppInfo(icon1, - icon2, + null, resolveInfo.loadLabel(pm).toString(), resolveInfo.activityInfo.packageName, resolveInfo.activityInfo.name, false); - if (notVisible) { - if (DEBUG) Log.v(TAG, "Not Done"); - if (visible(icon1, icon2)) arrayList.add(appInfo); - } else arrayList.add(appInfo); - } + if (SecondIcon) { + Drawable icon2 = null; + if (appListAll.contains(appInfo)) {//check if the list contains the element + int o = appListAll.indexOf((appInfo)); + if (DEBUG) Log.v(TAG, String.valueOf(o)); + AppInfo geticon = appListAll.get(appListAll.indexOf(appInfo));//get the element by passing the index of the element + //if (DEBUG) Log.v(TAG, "label" + String.valueOf(geticon.label)); + icon2 = geticon.icon; + // if (DEBUG) Log.v(TAG,"iconwert" + String.valueOf(icon2)); + } + appInfo = new AppInfo(icon1, + icon2, + resolveInfo.loadLabel(pm).toString(), + resolveInfo.activityInfo.packageName, + resolveInfo.activityInfo.name, + false); + } + + if (OnlyNew) { + // filter out apps that are already included + if (!appListAll.contains(appInfo)) { + arrayList.add(appInfo); + if (DEBUG) Log.i(TAG, "Added app: " + resolveInfo.loadLabel(pm)); + } else { + if (DEBUG) Log.v(TAG, "Removed app: " + resolveInfo.loadLabel(pm)); + } + } else arrayList.add(appInfo); + + } //Custom comparator to ensure correct sorting for characters like and apps // starting with a small letter like iNex @@ -546,6 +601,51 @@ private void prepareData() { appListFilter = arrayList; } + private void prepareDataIPack() { + // sort the apps + ArrayList arrayList = new ArrayList<>(); + PackageManager pm = getPackageManager(); + Intent intent = new Intent("org.adw.launcher.THEMES", null); + // intent.addCategory("org.adw.launcher.THEMES"); + // List adwlauncherthemes = pm.queryIntentActivities(new Intent("org.adw.launcher.THEMES"), PackageManager.GET_META_DATA); + List golauncherthemes = pm.queryIntentActivities(new Intent("com.gau.go.launcherex.theme"), PackageManager.GET_META_DATA); + + // List rinfo = new ArrayList(adwlauncherthemes); + // rinfo.addAll(golauncherthemes); + + List list = pm.queryIntentActivities(intent, 0); + //list.addAll(golauncherthemes); + Iterator localIterator = list.iterator(); + if (DEBUG) Log.v(TAG, "list size: " + list.size()); + boolean notVisible = loadDataBool("SettingOnlyNew"); + for (int i = 0; i < list.size(); i++) { + ResolveInfo resolveInfo = localIterator.next(); + + iPackInfo ipackinfo = new iPackInfo(getHighResIcon(pm, resolveInfo), + //icon2, + resolveInfo.loadLabel(pm).toString(), + resolveInfo.activityInfo.packageName, + // resolveInfo.activityInfo.name, + false); + arrayList.add(ipackinfo); + + } + + //Custom comparator to ensure correct sorting for characters like and apps + // starting with a small letter like iNex + Collections.sort(arrayList, (object1, object2) -> { + Locale locale = Locale.getDefault(); + Collator collator = Collator.getInstance(locale); + collator.setStrength(Collator.TERTIARY); + + if (DEBUG) + Log.v(TAG, "Comparing \"" + object1.label + "\" to \"" + object2.label + "\""); + + return collator.compare(object1.label, object2.label); + }); + IPackListFilter = arrayList; + } + private Drawable getHighResIcon(PackageManager pm, ResolveInfo resolveInfo) { Drawable icon; @@ -558,19 +658,20 @@ private Drawable getHighResIcon(PackageManager pm, ResolveInfo resolveInfo) { int iconId = resolveInfo.getIconResource();//Get the resource Id for the activity icon if (iconId != 0) { - icon = ResourcesCompat.getDrawable(pm.getResourcesForActivity(componentName), iconId, null); - //icon = context.getPackageManager().getApplicationIcon(resolveInfo.activityInfo.packageName); - //icon =pm.getDrawable(resolveInfo.activityInfo.packageName, iconId, null); - //Drawable adaptiveDrawable = resolveInfo.loadIcon(pm); + //Resources.Theme theme = context.getTheme(); + icon = ResourcesCompat.getDrawable(pm.getResourcesForActivity(componentName), iconId, null); //loads unthemed + //icon = context.getPackageManager().getApplicationIcon(resolveInfo.activityInfo.packageName); //loads themed OnePlus + //icon =pm.getDrawable(resolveInfo.activityInfo.packageName, iconId, null); //loads unthemed + //Drawable adaptiveDrawable = resolveInfo.loadIcon(pm); //loads themed OnePlus //PackageManager packageManager = getPackageManager(); - //icon = resolveInfo.loadIcon(packageManager); - //icon = context.getDrawable(pm.getResourcesForActivity(componentName),iconId,null); + //icon = resolveInfo.loadIcon(packageManager); //loads themed OnePlus + return icon; } return resolveInfo.loadIcon(pm); } catch (PackageManager.NameNotFoundException e) { //fails return the normal icon - return resolveInfo.loadIcon(pm); + return resolveInfo.loadIcon(pm); } catch (Resources.NotFoundException e) { return resolveInfo.loadIcon(pm); } @@ -582,7 +683,7 @@ private void populateView(ArrayList arrayListFinal) { ListView grid = findViewById(R.id.app_list); grid.setFastScrollEnabled(true); - grid.setFastScrollAlwaysVisible(true); + //grid.setFastScrollAlwaysVisible(true); grid.setAdapter(new AppAdapter(this, R.layout.item_request, local_arrayList)); grid.setOnItemClickListener((AdapterView, view, position, row) -> { AppInfo appInfo = (AppInfo) AdapterView.getItemAtPosition(position); @@ -619,6 +720,39 @@ public boolean loadDataBool(String setting) { return sharedPreferences.getBoolean(setting, false); } + private void populateView_Ipack(ArrayList arrayListFinal) { + ArrayList local_arrayList; + local_arrayList = arrayListFinal; + + ListView grid = findViewById(R.id.app_list); + grid.setFastScrollEnabled(true); + //grid.setFastScrollAlwaysVisible(true); + grid.setAdapter(new RequestActivity.IPackAppAdapter(this, R.layout.item_iconpack, local_arrayList)); + grid.setOnItemClickListener((AdapterView, view, position, row) -> { + iPackInfo ipackinfo = (iPackInfo) AdapterView.getItemAtPosition(position); + switcherLoad.showNext(); + ExecutorService executors = Executors.newSingleThreadExecutor(); + executors.execute(() -> { + try { + parseXML(ipackinfo.packageName); + if (DEBUG) Log.v(TAG, ipackinfo.packageName); + prepareData(); + } catch (Exception e) { + e.printStackTrace(); + } + new Handler(Looper.getMainLooper()).post(() -> { + findViewById(R.id.text_ipack_chooser).setVisibility(View.GONE); + populateView(appListFilter); + IPackChoosen = true; + invalidateOptionsMenu(); + //populateView(appListFilter); //Orginal fill view + switcherLoad.showNext(); + }); + }); + }); + } + + private class AppAdapter extends ArrayAdapter { private final ArrayList appList = new ArrayList<>(); @@ -688,4 +822,39 @@ private class ViewHolder { } } + + private class IPackAppAdapter extends ArrayAdapter { + private final ArrayList appList = new ArrayList<>(); + + public IPackAppAdapter(Context context, int position, ArrayList adapterArrayList) { + super(context, position, adapterArrayList); + appList.addAll(adapterArrayList); + } + + @NonNull + public View getView(int position, View convertView, @NonNull ViewGroup parent) { + RequestActivity.IPackAppAdapter.ViewHolder holder; + if (convertView == null) { + convertView = ((LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE)) + .inflate(R.layout.item_iconpack, null); + holder = new RequestActivity.IPackAppAdapter.ViewHolder(); + holder.apkIcon = convertView.findViewById(R.id.ipackicon); + holder.apkName = convertView.findViewById(R.id.ipacklabel); + convertView.setTag(holder); + } else { + holder = (RequestActivity.IPackAppAdapter.ViewHolder) convertView.getTag(); + } + + iPackInfo appInfo = appList.get(position); + holder.apkName.setText(appInfo.label); + holder.apkIcon.setImageDrawable(appInfo.icon); + return convertView; + } + + private class ViewHolder { + TextView apkName; + ImageView apkIcon; + } + } } + diff --git a/app/src/main/java/de/kaiserdragon/iconrequest/SettingActivity.java b/app/src/main/java/de/kaiserdragon/iconrequest/SettingActivity.java index 0277928..7f47678 100644 --- a/app/src/main/java/de/kaiserdragon/iconrequest/SettingActivity.java +++ b/app/src/main/java/de/kaiserdragon/iconrequest/SettingActivity.java @@ -62,13 +62,9 @@ public void start(View view, int update) { AppCompatDelegate.setDefaultNightMode(update); } else { if (view == (CheckBox) findViewById(R.id.checkBoxRows)) { - if (((CheckBox) view).isChecked()) { - saveDataBool("SettingRow", true); - } else saveDataBool("SettingRow", false); + saveDataBool("SettingRow", ((CheckBox) view).isChecked()); } else if (view == (CheckBox) findViewById(R.id.checkBoxOnly)) { - if (((CheckBox) view).isChecked()) { - saveDataBool("SettingOnlyNew", true); - } else saveDataBool("SettingOnlyNew", false); + saveDataBool("SettingOnlyNew", ((CheckBox) view).isChecked()); } } diff --git a/app/src/main/java/de/kaiserdragon/iconrequest/iPackInfo.java b/app/src/main/java/de/kaiserdragon/iconrequest/iPackInfo.java new file mode 100644 index 0000000..4d0bc4a --- /dev/null +++ b/app/src/main/java/de/kaiserdragon/iconrequest/iPackInfo.java @@ -0,0 +1,32 @@ +package de.kaiserdragon.iconrequest; + +import android.graphics.drawable.Drawable; + +public class iPackInfo { + public Drawable icon; + public String label; + public boolean selected; + String packageName; + String className; + + iPackInfo(Drawable icon, String label, String packageName, boolean selected) { + this.icon = icon; + this.label = label; + this.packageName = packageName; + this.selected = selected; + } + + public String getCode() { + return packageName + "/" + className; + } + + @Override + public boolean equals(Object object) { + if (object instanceof iPackInfo) { + iPackInfo ipackinfo = (iPackInfo) object; + return this.getCode().equals(ipackinfo.getCode()); + } + return false; + } +} + diff --git a/app/src/main/res/layout/activity_request.xml b/app/src/main/res/layout/activity_request.xml index 4edf5d4..671a427 100644 --- a/app/src/main/res/layout/activity_request.xml +++ b/app/src/main/res/layout/activity_request.xml @@ -1,5 +1,6 @@ + - + android:layout_height="match_parent"> + + + + + + diff --git a/app/src/main/res/layout/item_iconpack.xml b/app/src/main/res/layout/item_iconpack.xml new file mode 100644 index 0000000..8afa870 --- /dev/null +++ b/app/src/main/res/layout/item_iconpack.xml @@ -0,0 +1,31 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/menu_iconpack_chooser.xml b/app/src/main/res/menu/menu_iconpack_chooser.xml new file mode 100644 index 0000000..1fe7aa6 --- /dev/null +++ b/app/src/main/res/menu/menu_iconpack_chooser.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 8ae3f46..31681b0 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -15,12 +15,15 @@ Device Default Other - The following options might not work as intended. These options depend somewhat on the Launcher. - It works with the OnePlus-Launcher but not with KissLauncher. If it doesn\'t work please disable it. - Show second row with currently applied icons + The following options let you choose one of your installed icon packs to use + for these options. The first option takes quite some cpu power and takes therefore a bit of time. + if you don\'t need it disable it. + Show second icon from an icon pack Show only apps that currently doesn\'t have an themed icon Save + Choose an icon pack + Show Icon Show Icon selected