diff --git a/.gitignore b/.gitignore index 4440b98..ce17250 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,7 @@ # Local configuration files (sdk path, etc) local.properties +keystore.properties # Mac .DS_Store files .DS_Store @@ -32,6 +33,7 @@ captures # ignore lint html and xml output lint-*ml +*.jks /.idea/caches /.idea/libraries diff --git a/.idea/misc.xml b/.idea/misc.xml index 786cdf6..4bee64a 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -13,6 +13,10 @@ + + + + @@ -23,6 +27,8 @@ + + @@ -30,6 +36,8 @@ + + @@ -48,12 +56,15 @@ + + + diff --git a/app/build.gradle b/app/build.gradle index e9d8ab5..1c394fa 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,5 +1,6 @@ plugins { id 'com.android.application' + id 'com.mikepenz.aboutlibraries.plugin' } android { @@ -13,38 +14,93 @@ android { versionName "1.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + + // Required when setting minSdkVersion to 20 or lower + multiDexEnabled true + } + + signingConfigs { + release { + Properties buildPro = buildSign() + storeFile file(buildPro['storeFile']) + storePassword buildPro['storePassword'] + keyAlias buildPro['keyAlias'] + keyPassword buildPro['keyPassword'] + } } buildTypes { release { - minifyEnabled false + minifyEnabled true + shrinkResources true + signingConfig signingConfigs.release proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + zipAlignEnabled true } } + + android.applicationVariants.all { + variant -> + variant.outputs.all { + output -> outputFileName = new File(variant.name, "OxygenToolbox" + "_" + defaultConfig.versionName + "-" + defaultConfig.versionCode + "_" + buildType.name + ".apk") + } + } + compileOptions { + // Flag to enable support for the new language APIs + coreLibraryDesugaringEnabled true + // Sets Java compatibility to Java 8 sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } + buildFeatures { viewBinding true } + namespace 'com.fatapp.oxygentoolbox' } +def buildSign() { + Properties buildProperties = new Properties() + buildProperties.load(new FileInputStream(file("../keystore.properties"))) + return buildProperties +} + +aboutLibraries { + registerAndroidTasks = false + outputFileName = "dependencies.json" + exclusionPatterns = [ + ~'androidx.*', + ~'org.jetbrains.*', + ~"com.google.android.*", + ~"com.google.guava:listenablefuture" + ] +} + +task exportLibrariesToJson(group: 'build', description: 'Generate libraries definitions json file', type: com.mikepenz.aboutlibraries.plugin.AboutLibrariesTask, dependsOn:'collectDependencies') { + resultDirectory = project.file('src/main/res/raw/') + variant = 'release' +} + +afterEvaluate { + def assembleTask = tasks.findByName("assembleDebug") + assembleTask.dependsOn(exportLibrariesToJson) +} + dependencies { - implementation 'androidx.preference:preference:1.2.0' + //noinspection GradleDependency + coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.6' testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.1.3' androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' implementation 'androidx.appcompat:appcompat:1.4.2' - implementation 'com.google.android.material:material:1.6.1' implementation 'androidx.constraintlayout:constraintlayout:2.1.4' - implementation 'androidx.navigation:navigation-fragment-ktx:2.4.2' - implementation 'androidx.navigation:navigation-ui-ktx:2.4.2' - implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.4.1' - implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.1' + implementation 'androidx.preference:preference:1.2.0' + implementation 'androidx.navigation:navigation-fragment-ktx:2.5.0' + implementation 'androidx.navigation:navigation-ui-ktx:2.5.0' implementation 'androidx.core:core-splashscreen:1.0.0-rc01' - implementation 'androidx.preference:preference-ktx:1.2.0' + implementation 'com.google.android.material:material:1.6.1' implementation 'com.google.code.gson:gson:2.9.0' -} +} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index e509b21..2b28126 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -11,6 +11,11 @@ android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.OxygenToolbox.Default"> + () { + }.getType()); + librariesRecyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext())); + librariesAdapter = new LibrariesAdapter(this, dependencies); + librariesRecyclerView.addItemDecoration(new LibrariesAdapter.LibrariesItemDecoration()); + librariesRecyclerView.setAdapter(librariesAdapter); + } catch (IOException e) { + Log.d("TAG", e.toString()); + } + } + + @Override + public boolean onOptionsItemSelected(@NonNull MenuItem item) { + if (item.getItemId() == android.R.id.home) { + finish(); + } + + return super.onOptionsItemSelected(item); + } + + @Override + public boolean onCreateOptionsMenu(@NonNull Menu menu) { + getMenuInflater().inflate(R.menu.seach_view, menu); + SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE); + searchView = (SearchView) menu.findItem(R.id.action_search).getActionView(); + searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName())); + searchView.setMaxWidth(Integer.MAX_VALUE); + searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { + @Override + public boolean onQueryTextSubmit(String query) { + librariesAdapter.getFilter().filter(query); + return false; + } + + @Override + public boolean onQueryTextChange(String newText) { + librariesAdapter.getFilter().filter(newText); + return false; + } + }); + + return true; + } + + @Override + public void onBackPressed() { + // Close search view when back button pressed + if (!searchView.isIconified()) { + searchView.setIconified(true); + return; + } + + super.onBackPressed(); + } + + @Override + protected void attachBaseContext(Context newBase) { + super.attachBaseContext(MultiLanguageUtils.attachBaseContext(newBase)); + } + + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + MultiLanguageUtils.attachBaseContext(getApplicationContext()); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fatapp/oxygentoolbox/ui/about/util/LibrariesAdapter.java b/app/src/main/java/com/fatapp/oxygentoolbox/ui/about/util/LibrariesAdapter.java new file mode 100644 index 0000000..523a768 --- /dev/null +++ b/app/src/main/java/com/fatapp/oxygentoolbox/ui/about/util/LibrariesAdapter.java @@ -0,0 +1,179 @@ +package com.fatapp.oxygentoolbox.ui.about.util; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.Intent; +import android.graphics.Rect; +import android.net.Uri; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Filter; +import android.widget.Filterable; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import com.fatapp.oxygentoolbox.R; +import com.fatapp.oxygentoolbox.util.DependenciesJson; +import com.fatapp.oxygentoolbox.util.LicenseJson; +import com.fatapp.oxygentoolbox.util.ResourceUtil; +import com.google.android.material.card.MaterialCardView; +import com.google.android.material.dialog.MaterialAlertDialogBuilder; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.ArrayList; +import java.util.List; +import java.util.StringJoiner; + +public class LibrariesAdapter extends RecyclerView.Adapter implements Filterable { + private final Context context; + private final DependenciesJson dependencies; + private List librariesFiltered; + + public LibrariesAdapter(Context context, DependenciesJson dependencies) { + this.context = context; + this.dependencies = dependencies; + this.librariesFiltered = dependencies.getLibraries(); + } + + @NonNull + @Override + public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View inflate = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_libraries, parent, false); + + return new ViewHolder(inflate); + } + + @Override + public void onBindViewHolder(@NonNull ViewHolder holder, int position) { + DependenciesJson.LibrariesDTO library = librariesFiltered.get(position); + holder.getLibraryName().setText(library.getName()); + holder.getLibraryCreator().setText(library.getDevelopersStr()); + holder.getLibraryVersion().setText(library.getArtifactVersion()); + holder.getLibraryDescription().setText(library.getDescription()); + holder.getLibraryLicense().setText(getLicensesNameStr(library.getLicenses())); + + String url = library.getWebsite() != null && !library.getWebsite().isEmpty() ? library.getWebsite() : library.getScm() != null && library.getScm().getUrl() != null && !library.getScm().getUrl().isEmpty() ? library.getScm().getUrl() : null; + if (url != null) { + holder.cardView.setOnClickListener(view -> context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)))); + } + + holder.getLibraryLicense().setOnClickListener(view -> { + for (String license : library.getLicenses()) { + try { + String licenseStr = new JSONObject(dependencies.getLicenses()).getString(license); + LicenseJson licenseObject = new Gson().fromJson(licenseStr, new TypeToken() { + }.getType()); + new MaterialAlertDialogBuilder(context).setMessage(licenseObject.getContent()).show(); + } catch (JSONException e) { + new MaterialAlertDialogBuilder(context).setMessage(String.format("Could not load license \"%s\"", license)).show(); + } + } + }); + } + + @Override + public int getItemCount() { + return librariesFiltered.size(); + } + + private String getLicensesNameStr(List licenses) { + StringJoiner stringJoiner = new StringJoiner(", "); + for (String license : licenses) { + try { + String licenseStr = new JSONObject(dependencies.getLicenses()).getString(license); + LicenseJson licenseObject = new Gson().fromJson(licenseStr, new TypeToken() { + }.getType()); + stringJoiner.add(licenseObject.getName()); + } catch (JSONException e) { + stringJoiner.add(license); + } + } + return stringJoiner.toString(); + } + + @Override + public Filter getFilter() { + return new Filter() { + @Override + protected FilterResults performFiltering(CharSequence charSequence) { + List libraries = new ArrayList<>(); + if (charSequence.toString().isEmpty()) { + libraries = dependencies.getLibraries(); + } else { + for (DependenciesJson.LibrariesDTO library : dependencies.getLibraries()) { + if (library.getName().toLowerCase().contains(charSequence.toString().toLowerCase())) { + libraries.add(library); + } + } + } + FilterResults results = new FilterResults(); + results.count = libraries.size(); + results.values = libraries; + return results; + } + + @SuppressWarnings("unchecked") + @SuppressLint("NotifyDataSetChanged") + @Override + protected void publishResults(CharSequence charSequence, FilterResults filterResults) { + librariesFiltered = (ArrayList) filterResults.values; + notifyDataSetChanged(); + } + }; + } + + public static class ViewHolder extends RecyclerView.ViewHolder { + private final MaterialCardView cardView; + private final TextView libraryName; + private final TextView libraryCreator; + private final TextView libraryVersion; + private final TextView libraryDescription; + private final TextView libraryLicense; + + public ViewHolder(@NonNull View itemView) { + super(itemView); + cardView = (MaterialCardView) itemView; + libraryName = itemView.findViewById(R.id.library_name); + libraryCreator = itemView.findViewById(R.id.library_creator); + libraryVersion = itemView.findViewById(R.id.library_version); + libraryDescription = itemView.findViewById(R.id.library_description); + libraryLicense = itemView.findViewById(R.id.library_license); + } + + public TextView getLibraryName() { + return libraryName; + } + + public TextView getLibraryCreator() { + return libraryCreator; + } + + public TextView getLibraryVersion() { + return libraryVersion; + } + + public TextView getLibraryDescription() { + return libraryDescription; + } + + public TextView getLibraryLicense() { + return libraryLicense; + } + } + + public static class LibrariesItemDecoration extends RecyclerView.ItemDecoration { + @Override + public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) { + if (parent.getChildLayoutPosition(view) != 0) { + outRect.top = -ResourceUtil.dpToPx(10f); + } + } + } +} diff --git a/app/src/main/java/com/fatapp/oxygentoolbox/ui/home/HomeFragment.java b/app/src/main/java/com/fatapp/oxygentoolbox/ui/home/HomeFragment.java index 7622cd9..0f8d9cf 100644 --- a/app/src/main/java/com/fatapp/oxygentoolbox/ui/home/HomeFragment.java +++ b/app/src/main/java/com/fatapp/oxygentoolbox/ui/home/HomeFragment.java @@ -14,6 +14,7 @@ import androidx.viewpager2.widget.ViewPager2; import com.fatapp.oxygentoolbox.R; import com.fatapp.oxygentoolbox.ui.home.fav.FavFragment; import com.fatapp.oxygentoolbox.ui.home.tools.ToolsFragment; +import com.fatapp.oxygentoolbox.util.SharedPreferencesUtils; import com.google.android.material.bottomnavigation.BottomNavigationView; public class HomeFragment extends Fragment { @@ -29,7 +30,7 @@ public class HomeFragment extends Fragment { ViewPager2 bottomNavViewPager = root.findViewById(R.id.bottom_nav_view_pager); BottomNavigationView bottomNavigationView = root.findViewById(R.id.bottom_navigation_view); - bottomNavViewPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback(){ + bottomNavViewPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() { @Override public void onPageSelected(int position) { bottomNavigationView.getMenu().getItem(position).setChecked(true); @@ -43,13 +44,10 @@ public class HomeFragment extends Fragment { @NonNull @Override public Fragment createFragment(int position) { - switch (position) { - case 0: - return new ToolsFragment(); - case 1: - return new FavFragment(); + if (position == 1) { + return new FavFragment(); } - return null; + return new ToolsFragment(); } @Override @@ -58,6 +56,8 @@ public class HomeFragment extends Fragment { } }); + bottomNavViewPager.setCurrentItem(SharedPreferencesUtils.getLaunchPage() == SharedPreferencesUtils.LaunchPage.tools ? 0 : 1, false); + return root; } diff --git a/app/src/main/java/com/fatapp/oxygentoolbox/ui/setting/SettingFragment.java b/app/src/main/java/com/fatapp/oxygentoolbox/ui/setting/SettingFragment.java index 912f790..ff09143 100644 --- a/app/src/main/java/com/fatapp/oxygentoolbox/ui/setting/SettingFragment.java +++ b/app/src/main/java/com/fatapp/oxygentoolbox/ui/setting/SettingFragment.java @@ -1,32 +1,26 @@ package com.fatapp.oxygentoolbox.ui.setting; import android.content.Intent; -import android.os.Build; import android.os.Bundle; -import android.widget.Toast; -import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.preference.ListPreference; import androidx.preference.Preference; import androidx.preference.PreferenceFragmentCompat; -import androidx.preference.PreferenceManager; import com.fatapp.oxygentoolbox.MainActivity; import com.fatapp.oxygentoolbox.R; -import com.fatapp.oxygentoolbox.util.MultiLanguageUtils; +import com.fatapp.oxygentoolbox.ui.about.LibrariesActivity; import com.fatapp.oxygentoolbox.util.ResourceUtil; -import java.util.Objects; - public class SettingFragment extends PreferenceFragmentCompat { @Override public void onCreatePreferences(@Nullable Bundle savedInstanceState, @Nullable String rootKey) { setPreferencesFromResource(R.xml.fragment_setting, rootKey); - ListPreference appLanguage = findPreference("app_language"); - if (appLanguage != null) { - appLanguage.setOnPreferenceChangeListener((preference, newValue) -> { + ListPreference appLanguagePreference = findPreference(ResourceUtil.getString(R.string.setting_language_key)); + if (appLanguagePreference != null) { + appLanguagePreference.setOnPreferenceChangeListener((preference, newValue) -> { Intent intent = new Intent(getActivity(), MainActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); requireActivity().startActivity(intent); @@ -34,5 +28,16 @@ public class SettingFragment extends PreferenceFragmentCompat { return true; }); } + + Preference aboutPreference = findPreference(ResourceUtil.getString(R.string.setting_about_oxygen_toolbox_key)); + if (aboutPreference != null) { + aboutPreference.setOnPreferenceClickListener(preference -> { + Intent intent = new Intent(getActivity(), LibrariesActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + startActivity(intent); +// Navigation.findNavController(requireView()).navigate(R.id.action_setting_to_about); + return true; + }); + } } } \ No newline at end of file diff --git a/app/src/main/java/com/fatapp/oxygentoolbox/util/Config.java b/app/src/main/java/com/fatapp/oxygentoolbox/util/Config.java deleted file mode 100644 index 7a361f1..0000000 --- a/app/src/main/java/com/fatapp/oxygentoolbox/util/Config.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.fatapp.oxygentoolbox.util; - -public class Config { -} diff --git a/app/src/main/java/com/fatapp/oxygentoolbox/util/DependenciesJson.java b/app/src/main/java/com/fatapp/oxygentoolbox/util/DependenciesJson.java new file mode 100644 index 0000000..6e94e6c --- /dev/null +++ b/app/src/main/java/com/fatapp/oxygentoolbox/util/DependenciesJson.java @@ -0,0 +1,154 @@ +package com.fatapp.oxygentoolbox.util; + +import com.google.gson.JsonParser; +import com.google.gson.TypeAdapter; +import com.google.gson.annotations.JsonAdapter; +import com.google.gson.annotations.SerializedName; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; + +import java.io.IOException; +import java.util.List; +import java.util.StringJoiner; + +public class DependenciesJson { + + @SerializedName("metadata") + private MetadataDTO metadata; + @SerializedName("libraries") + private List libraries; + @SerializedName("licenses") + @JsonAdapter(RawStringJsonAdapter.class) + private String licenses; + + public MetadataDTO getMetadata() { + return metadata; + } + + public List getLibraries() { + return libraries; + } + + public String getLicenses() { + return licenses; + } + + public static class MetadataDTO { + @SerializedName("generated") + private String generated; + + public String getGenerated() { + return generated; + } + } + + public static class LibrariesDTO { + @SerializedName("uniqueId") + private String uniqueId; + @SerializedName("funding") + private List funding; + @SerializedName("developers") + private List developers; + @SerializedName("artifactVersion") + private String artifactVersion; + @SerializedName("description") + private String description; + @SerializedName("name") + private String name; + @SerializedName("licenses") + private List licenses; + @SerializedName("scm") + private ScmDTO scm; + @SerializedName("website") + private String website; + + public String getUniqueId() { + return uniqueId; + } + + public List getFunding() { + return funding; + } + + public List getDevelopers() { + return developers; + } + + public String getDevelopersStr() { + StringJoiner stringJoiner = new StringJoiner(", "); + for (DevelopersDTO developer : getDevelopers()) { + stringJoiner.add(developer.getName()); + } + + return stringJoiner.toString(); + } + + public String getArtifactVersion() { + return artifactVersion; + } + + public String getDescription() { + return description; + } + + public String getName() { + return name; + } + + public List getLicenses() { + return licenses; + } + + public ScmDTO getScm() { + return scm; + } + + public String getWebsite() { + return website; + } + + public static class ScmDTO { + @SerializedName("connection") + private String connection; + @SerializedName("url") + private String url; + + public String getConnection() { + return connection; + } + + public String getUrl() { + return url; + } + } + + public static class DevelopersDTO { + @SerializedName("organisationUrl") + private String organisationUrl; + @SerializedName("name") + private String name; + + public String getOrganisationUrl() { + return organisationUrl; + } + + public String getName() { + return name; + } + } + } + public static class RawStringJsonAdapter extends TypeAdapter { + + @Override + public void write(JsonWriter out, String value) throws IOException { + out.jsonValue(value); + } + + @Override + public String read(JsonReader in) { + return JsonParser.parseReader(in).toString(); + } + } + + +} diff --git a/app/src/main/java/com/fatapp/oxygentoolbox/util/LicenseJson.java b/app/src/main/java/com/fatapp/oxygentoolbox/util/LicenseJson.java new file mode 100644 index 0000000..cdd51a4 --- /dev/null +++ b/app/src/main/java/com/fatapp/oxygentoolbox/util/LicenseJson.java @@ -0,0 +1,42 @@ +package com.fatapp.oxygentoolbox.util; + +import com.google.gson.annotations.SerializedName; + +public class LicenseJson { + @SerializedName("content") + private String content; + @SerializedName("hash") + private String hash; + @SerializedName("internalHash") + private String internalHash; + @SerializedName("url") + private String url; + @SerializedName("spdxId") + private String spdxId; + @SerializedName("name") + private String name; + + public String getContent() { + return content; + } + + public String getHash() { + return hash; + } + + public String getInternalHash() { + return internalHash; + } + + public String getUrl() { + return url; + } + + public String getSpdxId() { + return spdxId; + } + + public String getName() { + return name; + } +} diff --git a/app/src/main/java/com/fatapp/oxygentoolbox/util/MultiLanguageUtils.java b/app/src/main/java/com/fatapp/oxygentoolbox/util/MultiLanguageUtils.java index 974a5e2..bff4b25 100644 --- a/app/src/main/java/com/fatapp/oxygentoolbox/util/MultiLanguageUtils.java +++ b/app/src/main/java/com/fatapp/oxygentoolbox/util/MultiLanguageUtils.java @@ -1,47 +1,25 @@ package com.fatapp.oxygentoolbox.util; -import android.app.Activity; -import android.app.Application; import android.content.Context; import android.content.res.Configuration; import android.content.res.Resources; import android.os.Build; -import android.os.Bundle; import android.os.LocaleList; -import android.text.TextUtils; import android.util.DisplayMetrics; import androidx.annotation.RequiresApi; -import androidx.appcompat.view.ContextThemeWrapper; -import androidx.core.os.ConfigurationCompat; -import androidx.core.os.LocaleListCompat; - -import com.fatapp.oxygentoolbox.R; import java.util.Locale; +import java.util.Objects; public class MultiLanguageUtils { public static Context attachBaseContext(Context context) { - String locale; - if (SharedPreferencesUtils.isNull()) { - locale = "default"; - } else { - locale = SharedPreferencesUtils.getLocale(); - } - String language; - String country; - if (!locale.equals("default")) { - language = locale.substring(0, locale.indexOf("_")); - country = locale.substring(locale.indexOf("_") + 1); - } else { - language = ResourceUtil.getSystemLocale().get(0).getLanguage(); - country = ResourceUtil.getSystemLocale().get(0).getCountry(); - } + Locale locale = SharedPreferencesUtils.getLanguage(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) { - return createConfigurationContext(context, language, country); + return createConfigurationContext(context, locale.getLanguage(), locale.getCountry()); } else { - return updateConfiguration(context, language, country); + return updateConfiguration(context, locale.getLanguage(), locale.getCountry()); } } diff --git a/app/src/main/java/com/fatapp/oxygentoolbox/util/ResourceUtil.java b/app/src/main/java/com/fatapp/oxygentoolbox/util/ResourceUtil.java index 12c5374..4f98925 100644 --- a/app/src/main/java/com/fatapp/oxygentoolbox/util/ResourceUtil.java +++ b/app/src/main/java/com/fatapp/oxygentoolbox/util/ResourceUtil.java @@ -109,4 +109,12 @@ public final class ResourceUtil { Configuration configuration = Resources.getSystem().getConfiguration(); return ConfigurationCompat.getLocales(configuration); } + + public static int dpToPx(float dp) { + return (int) (dp * getDisplayMetrics().density + 0.5f); + } + + public static float pxToDp(int px) { + return px / getDisplayMetrics().density + 0.5f; + } } \ No newline at end of file diff --git a/app/src/main/java/com/fatapp/oxygentoolbox/util/SharedPreferencesUtils.java b/app/src/main/java/com/fatapp/oxygentoolbox/util/SharedPreferencesUtils.java index 1207f58..a608453 100644 --- a/app/src/main/java/com/fatapp/oxygentoolbox/util/SharedPreferencesUtils.java +++ b/app/src/main/java/com/fatapp/oxygentoolbox/util/SharedPreferencesUtils.java @@ -5,6 +5,11 @@ import android.content.SharedPreferences; import androidx.preference.PreferenceManager; +import com.fatapp.oxygentoolbox.R; + +import java.util.Locale; +import java.util.Objects; + public class SharedPreferencesUtils { private static SharedPreferences preferences; @@ -12,11 +17,31 @@ public class SharedPreferencesUtils { preferences = PreferenceManager.getDefaultSharedPreferences(app); } - public static String getLocale() { - return preferences.getString("app_language", "default"); + public static Locale getLanguage() { + String languagePreference; + String language; + String country; + if (SharedPreferencesUtils.isNull() || + (languagePreference = preferences.getString(ResourceUtil.getString(R.string.setting_language_key), ResourceUtil.getString(R.string.setting_language_default_value))).equals(ResourceUtil.getString(R.string.setting_language_default_value))) { + language = Objects.requireNonNull(ResourceUtil.getSystemLocale().get(0)).getLanguage(); + country = Objects.requireNonNull(ResourceUtil.getSystemLocale().get(0)).getCountry(); + } else { + language = languagePreference.substring(0, languagePreference.indexOf("_")); + country = languagePreference.substring(languagePreference.indexOf("_") + 1); + } + + return new Locale(language, country); } public static boolean isNull() { return preferences == null; } + + public static LaunchPage getLaunchPage() { + return LaunchPage.valueOf(preferences.getString(ResourceUtil.getString(R.string.setting_launch_page_key), ResourceUtil.getString(R.string.setting_launch_page_default_value))); + } + + public enum LaunchPage { + tools,favourites + } } diff --git a/app/src/main/java/com/fatapp/oxygentoolbox/util/ToolsLauncher.java b/app/src/main/java/com/fatapp/oxygentoolbox/util/ToolsLauncher.java index cf94915..bb4117d 100644 --- a/app/src/main/java/com/fatapp/oxygentoolbox/util/ToolsLauncher.java +++ b/app/src/main/java/com/fatapp/oxygentoolbox/util/ToolsLauncher.java @@ -7,7 +7,6 @@ import android.content.Intent; import android.widget.Toast; import com.fatapp.oxygentoolbox.R; -import com.fatapp.oxygentoolbox.tools.TimeScreenActivity; public class ToolsLauncher { public static void launch(Context context, String activity) { diff --git a/app/src/main/java/com/fatapp/oxygentoolbox/util/ToolsList.java b/app/src/main/java/com/fatapp/oxygentoolbox/util/ToolsList.java index 50a75dc..f0027dc 100644 --- a/app/src/main/java/com/fatapp/oxygentoolbox/util/ToolsList.java +++ b/app/src/main/java/com/fatapp/oxygentoolbox/util/ToolsList.java @@ -1,28 +1,25 @@ package com.fatapp.oxygentoolbox.util; -import android.os.Build; -import android.widget.Toast; - -import com.fatapp.oxygentoolbox.MainActivity; -import com.fatapp.oxygentoolbox.ui.home.HomeFragment; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; +import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; +import java.io.InputStreamReader; import java.util.ArrayList; import java.util.List; -import java.util.Locale; public class ToolsList { private static List toolList = new ArrayList<>(); public static void init(InputStream file) throws IOException { - int i; + String str; StringBuilder jsonStringBuilder = new StringBuilder(); - - while ((i = file.read()) != -1) { - jsonStringBuilder.append((char) i); + InputStreamReader inputStreamReader = new InputStreamReader(file); + BufferedReader bufferedReader = new BufferedReader(inputStreamReader); + while ((str = bufferedReader.readLine()) != null) { + jsonStringBuilder.append(str); } file.close(); List toolsJsonList = new Gson().fromJson(jsonStringBuilder.toString(), new TypeToken>() { @@ -44,13 +41,7 @@ public class ToolsList { } private static String getLocale(Locales strings) { - String language; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - language = ResourceUtil.getResources().getConfiguration().getLocales().get(0).getLanguage(); - } else { - language = ResourceUtil.getResources().getConfiguration().locale.getLanguage(); - } - if (language.equals("zh")) { + if (SharedPreferencesUtils.getLanguage().getLanguage().equals("zh")) { return strings.getCn(); } return strings.getEn(); diff --git a/app/src/main/res/drawable/ic_launch.xml b/app/src/main/res/drawable/ic_launch.xml new file mode 100644 index 0000000..d1648bf --- /dev/null +++ b/app/src/main/res/drawable/ic_launch.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_setting_about.xml b/app/src/main/res/drawable/ic_setting_about.xml new file mode 100644 index 0000000..3caaa67 --- /dev/null +++ b/app/src/main/res/drawable/ic_setting_about.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_setting_language.xml b/app/src/main/res/drawable/ic_setting_language.xml new file mode 100644 index 0000000..940896b --- /dev/null +++ b/app/src/main/res/drawable/ic_setting_language.xml @@ -0,0 +1,12 @@ + + + diff --git a/app/src/main/res/layout/activity_libraries.xml b/app/src/main/res/layout/activity_libraries.xml new file mode 100644 index 0000000..d1331e1 --- /dev/null +++ b/app/src/main/res/layout/activity_libraries.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_libraries.xml b/app/src/main/res/layout/item_libraries.xml new file mode 100644 index 0000000..199a96a --- /dev/null +++ b/app/src/main/res/layout/item_libraries.xml @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/menu/seach_view.xml b/app/src/main/res/menu/seach_view.xml new file mode 100644 index 0000000..3c2eb94 --- /dev/null +++ b/app/src/main/res/menu/seach_view.xml @@ -0,0 +1,10 @@ + + + \ No newline at end of file diff --git a/app/src/main/res/navigation/mobile_navigation.xml b/app/src/main/res/navigation/mobile_navigation.xml index 694660c..bd52828 100644 --- a/app/src/main/res/navigation/mobile_navigation.xml +++ b/app/src/main/res/navigation/mobile_navigation.xml @@ -21,7 +21,11 @@ android:id="@+id/nav_setting" android:name="com.fatapp.oxygentoolbox.ui.setting.SettingFragment" android:label="@string/menu_setting" - tools:layout="@xml/fragment_setting" /> + tools:layout="@xml/fragment_setting"> + + 基本设置 语言 - 启动页 - 跟随系统 中文 English + 启动页 + + 工具 + 收藏 + + 开源许可 + 查找 + 关于 + 关于 氧工具 \ No newline at end of file diff --git a/app/src/main/res/values-zh-rHK/strings.xml b/app/src/main/res/values-zh-rHK/strings.xml index b243dc4..1060723 100644 --- a/app/src/main/res/values-zh-rHK/strings.xml +++ b/app/src/main/res/values-zh-rHK/strings.xml @@ -27,11 +27,14 @@ 基本设置 语言 - 启动页 - 跟随系统 中文 English + 启动页 + 开源许可 + 查找 + 关于 + 关于 氧工具 \ No newline at end of file diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index b243dc4..1060723 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -27,11 +27,14 @@ 基本设置 语言 - 启动页 - 跟随系统 中文 English + 启动页 + 开源许可 + 查找 + 关于 + 关于 氧工具 \ No newline at end of file diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 140030b..2e683a7 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -6,4 +6,10 @@ 8dp 176dp 20sp + + 16dp + 16dp + 16dp + 8dp + 16dp \ 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 deef1d3..e9a8a86 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -45,5 +45,21 @@ zh_CN en_US + default Launch Page + app_launch_page + + Tools + Favourites + + + tools + favourites + + tools + OpenSource + Search + About + About OxygenToolbox + app_about \ No newline at end of file diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 866e994..b4d380b 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -1,5 +1,6 @@ + + +