From b40b25382cd4acf4db07329810cb968f18a29798 Mon Sep 17 00:00:00 2001 From: Iscle Date: Sun, 12 Jan 2020 02:54:54 +0100 Subject: [PATCH 01/12] Organize activities and receivers into folders This way we have a more organized source code. No functionality changes were made. --- app/src/main/AndroidManifest.xml | 48 +++++------ .../java/ru/meefik/linuxdeploy/EnvUtils.java | 8 +- .../java/ru/meefik/linuxdeploy/Logger.java | 10 ++- .../java/ru/meefik/linuxdeploy/PrefStore.java | 80 ++++++++++--------- .../ru/meefik/linuxdeploy/RemoveEnvTask.java | 4 +- .../ru/meefik/linuxdeploy/UpdateEnvTask.java | 4 +- .../{ => activity}/AboutActivity.java | 5 +- .../AppCompatPreferenceActivity.java | 2 +- .../{ => activity}/FullscreenActivity.java | 5 +- .../{ => activity}/MainActivity.java | 10 ++- .../{ => activity}/MountsActivity.java | 5 +- .../{ => activity}/ProfilesActivity.java | 5 +- .../{ => activity}/PropertiesActivity.java | 5 +- .../{ => activity}/RepositoryActivity.java | 6 +- .../{ => activity}/SettingsActivity.java | 10 ++- .../{ => receiver}/ActionReceiver.java | 6 +- .../{ => receiver}/BootReceiver.java | 5 +- .../{ => receiver}/NetworkReceiver.java | 4 +- .../{ => receiver}/PowerReceiver.java | 4 +- app/src/main/res/layout-land/content_main.xml | 2 +- app/src/main/res/layout/activity_about.xml | 2 +- .../main/res/layout/activity_fullscreen.xml | 2 +- app/src/main/res/layout/activity_mounts.xml | 2 +- app/src/main/res/layout/activity_profiles.xml | 2 +- .../main/res/layout/activity_repository.xml | 2 +- app/src/main/res/layout/content_main.xml | 2 +- 26 files changed, 143 insertions(+), 97 deletions(-) rename app/src/main/java/ru/meefik/linuxdeploy/{ => activity}/AboutActivity.java (88%) rename app/src/main/java/ru/meefik/linuxdeploy/{ => activity}/AppCompatPreferenceActivity.java (98%) rename app/src/main/java/ru/meefik/linuxdeploy/{ => activity}/FullscreenActivity.java (94%) rename app/src/main/java/ru/meefik/linuxdeploy/{ => activity}/MainActivity.java (98%) rename app/src/main/java/ru/meefik/linuxdeploy/{ => activity}/MountsActivity.java (98%) rename app/src/main/java/ru/meefik/linuxdeploy/{ => activity}/ProfilesActivity.java (98%) rename app/src/main/java/ru/meefik/linuxdeploy/{ => activity}/PropertiesActivity.java (99%) rename app/src/main/java/ru/meefik/linuxdeploy/{ => activity}/RepositoryActivity.java (99%) rename app/src/main/java/ru/meefik/linuxdeploy/{ => activity}/SettingsActivity.java (96%) rename app/src/main/java/ru/meefik/linuxdeploy/{ => receiver}/ActionReceiver.java (95%) rename app/src/main/java/ru/meefik/linuxdeploy/{ => receiver}/BootReceiver.java (91%) rename app/src/main/java/ru/meefik/linuxdeploy/{ => receiver}/NetworkReceiver.java (92%) rename app/src/main/java/ru/meefik/linuxdeploy/{ => receiver}/PowerReceiver.java (86%) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index ead33afa..19a178a1 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -22,13 +22,13 @@ android:usesCleartextTraffic="true" tools:ignore="GoogleAppIndexingWarning"> + android:targetActivity=".activity.MainActivity"> @@ -37,56 +37,56 @@ + android:parentActivityName=".activity.MainActivity"> + android:value=".activity.MainActivity" /> + android:value=".activity.MainActivity" /> + android:parentActivityName=".activity.MainActivity"> + android:value=".activity.MainActivity" /> + android:parentActivityName=".activity.MainActivity"> + android:value=".activity.MainActivity" /> + android:parentActivityName=".activity.PropertiesActivity"> + android:value=".activity.PropertiesActivity" /> + android:parentActivityName=".activity.MainActivity"> + android:value=".activity.MainActivity" /> - + @@ -95,7 +95,7 @@ @@ -103,12 +103,12 @@ diff --git a/app/src/main/java/ru/meefik/linuxdeploy/EnvUtils.java b/app/src/main/java/ru/meefik/linuxdeploy/EnvUtils.java index f9349901..8eea994f 100644 --- a/app/src/main/java/ru/meefik/linuxdeploy/EnvUtils.java +++ b/app/src/main/java/ru/meefik/linuxdeploy/EnvUtils.java @@ -19,7 +19,7 @@ import java.util.ArrayList; import java.util.List; -class EnvUtils { +public class EnvUtils { /** * Closeable helper @@ -217,7 +217,7 @@ private static boolean setVersion(Context c) { * @param c context * @return true if success */ - static boolean isLatestVersion(Context c) { + public static boolean isLatestVersion(Context c) { File f = new File(PrefStore.getEnvDir(c) + "/version"); if (!f.exists()) return false; boolean result = false; @@ -462,7 +462,7 @@ public static boolean cli(Context c, String cmd, String args) { * @param cmd command * @param args arguments */ - static void execService(Context c, String cmd, String args) { + public static void execService(Context c, String cmd, String args) { Intent service = new Intent(c, ExecService.class); service.putExtra("cmd", cmd); service.putExtra("args", args); @@ -476,7 +476,7 @@ static void execService(Context c, String cmd, String args) { * @param commands commands * @param args command and arguments */ - static void execServices(Context c, String[] commands, String args) { + public static void execServices(Context c, String[] commands, String args) { for (String cmd : commands) { execService(c, cmd, args); } diff --git a/app/src/main/java/ru/meefik/linuxdeploy/Logger.java b/app/src/main/java/ru/meefik/linuxdeploy/Logger.java index 2772e95c..9165af26 100644 --- a/app/src/main/java/ru/meefik/linuxdeploy/Logger.java +++ b/app/src/main/java/ru/meefik/linuxdeploy/Logger.java @@ -15,7 +15,9 @@ import java.util.List; import java.util.Locale; -class Logger { +import ru.meefik.linuxdeploy.activity.MainActivity; + +public class Logger { private static volatile List protocol = new ArrayList<>(); private static char lastChar = '\n'; @@ -66,7 +68,7 @@ private static synchronized void appendMessage(Context c, final String msg) { * @param c context * @return true if success */ - static boolean clear(Context c) { + public static boolean clear(Context c) { protocol.clear(); File logFile = new File(PrefStore.getLogFile(c)); return logFile.delete(); @@ -77,14 +79,14 @@ static boolean clear(Context c) { * * @return size */ - static int size() { + public static int size() { return protocol.size(); } /** * Show log on main activity */ - static void show() { + public static void show() { MainActivity.showLog(get()); } diff --git a/app/src/main/java/ru/meefik/linuxdeploy/PrefStore.java b/app/src/main/java/ru/meefik/linuxdeploy/PrefStore.java index f068b3a6..2353cfc6 100644 --- a/app/src/main/java/ru/meefik/linuxdeploy/PrefStore.java +++ b/app/src/main/java/ru/meefik/linuxdeploy/PrefStore.java @@ -25,6 +25,8 @@ import androidx.core.app.NotificationCompat; import androidx.core.app.TaskStackBuilder; +import ru.meefik.linuxdeploy.activity.MainActivity; + import static ru.meefik.linuxdeploy.App.SERVICE_CHANNEL_ID; public class PrefStore { @@ -39,7 +41,7 @@ public class PrefStore { * @param c context * @return version, format versionName-versionCode */ - static String getVersion(Context c) { + public static String getVersion(Context c) { return BuildConfig.VERSION_NAME + "-" + BuildConfig.VERSION_CODE; } @@ -49,7 +51,7 @@ static String getVersion(Context c) { * @param c context * @return path, e.g. /data/data/package/files */ - static String getEnvDir(Context c) { + public static String getEnvDir(Context c) { String envDir = SETTINGS.get(c, "env_dir"); if (envDir.isEmpty()) { envDir = c.getFilesDir().getAbsolutePath(); @@ -103,7 +105,7 @@ static String getWebDir(Context c) { * @param c context * @return true if success */ - static boolean dumpSettings(Context c) { + public static boolean dumpSettings(Context c) { return SETTINGS.dump(c, getSettingsConfFile(c)); } @@ -113,7 +115,7 @@ static boolean dumpSettings(Context c) { * @param c context * @return true if success */ - static boolean restoreSettings(Context c) { + public static boolean restoreSettings(Context c) { return SETTINGS.restore(c, getSettingsConfFile(c)); } @@ -123,7 +125,7 @@ static boolean restoreSettings(Context c) { * @param c context * @return true if success */ - static boolean dumpProperties(Context c) { + public static boolean dumpProperties(Context c) { return PROPERTIES.dump(c, getPropertiesConfFile(c)); } @@ -133,7 +135,7 @@ static boolean dumpProperties(Context c) { * @param c context * @return true if success */ - static boolean restoreProperties(Context c) { + public static boolean restoreProperties(Context c) { PROPERTIES.clear(c, true); return PROPERTIES.restore(c, getPropertiesConfFile(c)); } @@ -143,7 +145,7 @@ static boolean restoreProperties(Context c) { * * @return name */ - static String getSettingsSharedName() { + public static String getSettingsSharedName() { return SettingsStore.name; } @@ -152,7 +154,7 @@ static String getSettingsSharedName() { * * @return name */ - static String getPropertiesSharedName() { + public static String getPropertiesSharedName() { return PropertiesStore.name; } @@ -195,7 +197,7 @@ private static String getLanguage(Context c) { * @param c context * @return resource id */ - static int getTheme(Context c) { + public static int getTheme(Context c) { String theme = SETTINGS.get(c, "theme"); int themeId = R.style.DarkTheme; switch (theme) { @@ -215,7 +217,7 @@ static int getTheme(Context c) { * @param c context * @return font size */ - static int getFontSize(Context c) { + public static int getFontSize(Context c) { int fontSizeInt; String fontSize = SETTINGS.get(c, "fontsize"); try { @@ -293,7 +295,7 @@ static Boolean isLogger(Context c) { * @param c context * @return path */ - static String getLogFile(Context c) { + public static String getLogFile(Context c) { String logFile = SETTINGS.get(c, "logfile"); if (!logFile.contains("/")) { String storageDir = Environment.getExternalStorageDirectory().getAbsolutePath(); @@ -308,7 +310,7 @@ static String getLogFile(Context c) { * @param c context * @return true if enabled */ - static Boolean isScreenLock(Context c) { + public static Boolean isScreenLock(Context c) { return SETTINGS.get(c, "screenlock").equals("true"); } @@ -318,7 +320,7 @@ static Boolean isScreenLock(Context c) { * @param c context * @return true if enabled */ - static Boolean isWifiLock(Context c) { + public static Boolean isWifiLock(Context c) { return SETTINGS.get(c, "wifilock").equals("true"); } @@ -328,7 +330,7 @@ static Boolean isWifiLock(Context c) { * @param c context * @return true if enabled */ - static Boolean isWakeLock(Context c) { + public static Boolean isWakeLock(Context c) { return SETTINGS.get(c, "wakelock").equals("true"); } @@ -338,7 +340,7 @@ static Boolean isWakeLock(Context c) { * @param c context * @return true if enabled */ - static Boolean isAutostart(Context c) { + public static Boolean isAutostart(Context c) { return SETTINGS.get(c, "autostart").equals("true"); } @@ -348,7 +350,7 @@ static Boolean isAutostart(Context c) { * @param c context * @return Auto start delay in seconds */ - static Integer getAutostartDelay(Context c) { + public static Integer getAutostartDelay(Context c) { try { return Integer.parseInt(SETTINGS.get(c, "autostart_delay")); } catch (Exception e) { @@ -362,7 +364,7 @@ static Integer getAutostartDelay(Context c) { * @param c context * @return true if enabled */ - static Boolean isNetTrack(Context c) { + public static Boolean isNetTrack(Context c) { return SETTINGS.get(c, "nettrack").equals("true"); } @@ -372,7 +374,7 @@ static Boolean isNetTrack(Context c) { * @param c context * @return true if enabled */ - static Boolean isPowerTrack(Context c) { + public static Boolean isPowerTrack(Context c) { return SETTINGS.get(c, "powertrack").equals("true"); } @@ -392,7 +394,7 @@ private static Boolean isNotification(Context c) { * @param c context * @return true if enabled */ - static Boolean isStealth(Context c) { + public static Boolean isStealth(Context c) { return SETTINGS.get(c, "stealth").equals("true"); } @@ -431,7 +433,7 @@ static String getShell(Context c) { * @param c context * @return url */ - static String getRepositoryUrl(Context c) { + public static String getRepositoryUrl(Context c) { return SETTINGS.get(c, "repository_url"); } @@ -440,7 +442,7 @@ static String getRepositoryUrl(Context c) { * * @param c context */ - static void setRepositoryUrl(Context c, String url) { + public static void setRepositoryUrl(Context c, String url) { SETTINGS.set(c, "repository_url", url); } @@ -490,7 +492,7 @@ static Boolean isHttp(Context c) { * @param c context * @return port */ - static String getHttpPort(Context c) { + public static String getHttpPort(Context c) { return SETTINGS.get(c, "http_port"); } @@ -500,7 +502,7 @@ static String getHttpPort(Context c) { * @param c context * @return authentication string, e.g. /:user:password (for crypt password use httpd -m password) */ - static String getHttpConf(Context c) { + public static String getHttpConf(Context c) { String auth = SETTINGS.get(c, "http_conf"); if (auth.isEmpty()) auth = "/:android:" + generatePassword(); return auth; @@ -512,7 +514,7 @@ static String getHttpConf(Context c) { * @param c context * @return true if enabled */ - static boolean isXserver(Context c) { + public static boolean isXserver(Context c) { return PROPERTIES.get(c, "is_gui").equals("true") && PROPERTIES.get(c, "graphics").equals("x11"); } @@ -523,7 +525,7 @@ static boolean isXserver(Context c) { * @param c context * @return true if enabled */ - static boolean isFramebuffer(Context c) { + public static boolean isFramebuffer(Context c) { return PROPERTIES.get(c, "is_gui").equals("true") && PROPERTIES.get(c, "graphics").equals("fb"); } @@ -534,7 +536,7 @@ static boolean isFramebuffer(Context c) { * @param c context * @return true if enabled */ - static boolean isXsdl(Context c) { + public static boolean isXsdl(Context c) { return PROPERTIES.get(c, "x11_sdl").equals("true"); } @@ -544,7 +546,7 @@ static boolean isXsdl(Context c) { * @param c context * @return delay in ms */ - static int getXsdlDelay(Context c) { + public static int getXsdlDelay(Context c) { int deplayInt; String delay = PROPERTIES.get(c, "x11_sdl_delay"); try { @@ -583,7 +585,7 @@ static File getPropertiesConfFile(Context c) { * @param c context * @return profile */ - static String getProfileName(Context c) { + public static String getProfileName(Context c) { return SETTINGS.get(c, "profile"); } @@ -592,7 +594,7 @@ static String getProfileName(Context c) { * * @param c context */ - static void changeProfile(Context c, String profile) { + public static void changeProfile(Context c, String profile) { SETTINGS.set(c, "profile", profile); dumpSettings(c); File confFile = getPropertiesConfFile(c); @@ -607,7 +609,7 @@ static void changeProfile(Context c, String profile) { * * @param c context */ - static void setLocale(Context c) { + public static void setLocale(Context c) { String language = getLanguage(c); Locale locale = new Locale(language); Locale.setDefault(locale); @@ -622,7 +624,7 @@ static void setLocale(Context c) { * @param c context * @return list of mount points */ - static List getMountsList(Context c) { + public static List getMountsList(Context c) { String str = PROPERTIES.get(c, "mounts"); List list = new ArrayList<>(); if (!str.isEmpty()) Collections.addAll(list, str.split(" ")); @@ -635,7 +637,7 @@ static List getMountsList(Context c) { * @param c context * @param list list of mount points */ - static void setMountsList(Context c, List list) { + public static void setMountsList(Context c, List list) { PROPERTIES.set(c, "mounts", TextUtils.join(" ", list)); } @@ -644,7 +646,7 @@ static void setMountsList(Context c, List list) { * * @return plain password */ - static String generatePassword() { + public static String generatePassword() { return Long.toHexString(Double.doubleToLongBits(Math.random())).substring(8); } @@ -654,7 +656,7 @@ static String generatePassword() { * @param arch unformated architecture * @return arm, arm_64, x86, x86_64 */ - static String getArch(String arch) { + public static String getArch(String arch) { String march = "unknown"; if (arch.length() > 0) { char a = arch.toLowerCase().charAt(0); @@ -679,7 +681,7 @@ static String getArch(String arch) { * * @return arm, arm_64, x86, x86_64 */ - static String getArch() { + public static String getArch() { return getArch(System.getProperty("os.arch")); } @@ -720,7 +722,7 @@ static Integer getScreenHeight(Context c) { * * @return ip address */ - static String getLocalIpAddress() { + public static String getLocalIpAddress() { String ip = "127.0.0.1"; try { for (Enumeration en = NetworkInterface @@ -748,7 +750,7 @@ static String getLocalIpAddress() { * @param resourceType resource type * @return resource id */ - static int getResourceId(Context c, String resourceName, String resourceType) { + public static int getResourceId(Context c, String resourceName, String resourceType) { try { return c.getResources().getIdentifier(resourceName, resourceType, c.getPackageName()); } catch (Exception e) { @@ -762,7 +764,7 @@ static int getResourceId(Context c, String resourceName, String resourceType) { * @param context context * @param intent intent */ - static void showNotification(Context context, Intent intent) { + public static void showNotification(Context context, Intent intent) { NotificationManager mNotificationManager = (NotificationManager) context .getSystemService(Context.NOTIFICATION_SERVICE); if (isNotification(context)) { @@ -815,7 +817,7 @@ static void showNotification(Context context, Intent intent) { * * @param context context */ - static void hideNotification(Context context) { + public static void hideNotification(Context context) { NotificationManager mNotificationManager = (NotificationManager) context .getSystemService(Context.NOTIFICATION_SERVICE); mNotificationManager.cancel(NOTIFY_ID); diff --git a/app/src/main/java/ru/meefik/linuxdeploy/RemoveEnvTask.java b/app/src/main/java/ru/meefik/linuxdeploy/RemoveEnvTask.java index bb7dcafa..d212b717 100644 --- a/app/src/main/java/ru/meefik/linuxdeploy/RemoveEnvTask.java +++ b/app/src/main/java/ru/meefik/linuxdeploy/RemoveEnvTask.java @@ -6,12 +6,12 @@ import java.lang.ref.WeakReference; -class RemoveEnvTask extends AsyncTask { +public class RemoveEnvTask extends AsyncTask { private ProgressDialog dialog; private WeakReference contextWeakReference; - RemoveEnvTask(Context c) { + public RemoveEnvTask(Context c) { contextWeakReference = new WeakReference<>(c); } diff --git a/app/src/main/java/ru/meefik/linuxdeploy/UpdateEnvTask.java b/app/src/main/java/ru/meefik/linuxdeploy/UpdateEnvTask.java index 02171c53..a617f3dc 100644 --- a/app/src/main/java/ru/meefik/linuxdeploy/UpdateEnvTask.java +++ b/app/src/main/java/ru/meefik/linuxdeploy/UpdateEnvTask.java @@ -7,12 +7,12 @@ import java.lang.ref.WeakReference; -class UpdateEnvTask extends AsyncTask { +public class UpdateEnvTask extends AsyncTask { private ProgressDialog dialog; private WeakReference contextWeakReference; - UpdateEnvTask(Context c) { + public UpdateEnvTask(Context c) { contextWeakReference = new WeakReference<>(c); } diff --git a/app/src/main/java/ru/meefik/linuxdeploy/AboutActivity.java b/app/src/main/java/ru/meefik/linuxdeploy/activity/AboutActivity.java similarity index 88% rename from app/src/main/java/ru/meefik/linuxdeploy/AboutActivity.java rename to app/src/main/java/ru/meefik/linuxdeploy/activity/AboutActivity.java index 9f3846d6..d934d804 100644 --- a/app/src/main/java/ru/meefik/linuxdeploy/AboutActivity.java +++ b/app/src/main/java/ru/meefik/linuxdeploy/activity/AboutActivity.java @@ -1,4 +1,4 @@ -package ru.meefik.linuxdeploy; +package ru.meefik.linuxdeploy.activity; import android.os.Bundle; import android.text.method.LinkMovementMethod; @@ -6,6 +6,9 @@ import androidx.appcompat.app.AppCompatActivity; +import ru.meefik.linuxdeploy.PrefStore; +import ru.meefik.linuxdeploy.R; + public class AboutActivity extends AppCompatActivity { @Override diff --git a/app/src/main/java/ru/meefik/linuxdeploy/AppCompatPreferenceActivity.java b/app/src/main/java/ru/meefik/linuxdeploy/activity/AppCompatPreferenceActivity.java similarity index 98% rename from app/src/main/java/ru/meefik/linuxdeploy/AppCompatPreferenceActivity.java rename to app/src/main/java/ru/meefik/linuxdeploy/activity/AppCompatPreferenceActivity.java index 47873ed0..c894a877 100644 --- a/app/src/main/java/ru/meefik/linuxdeploy/AppCompatPreferenceActivity.java +++ b/app/src/main/java/ru/meefik/linuxdeploy/activity/AppCompatPreferenceActivity.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package ru.meefik.linuxdeploy; +package ru.meefik.linuxdeploy.activity; import android.content.res.Configuration; import android.os.Bundle; diff --git a/app/src/main/java/ru/meefik/linuxdeploy/FullscreenActivity.java b/app/src/main/java/ru/meefik/linuxdeploy/activity/FullscreenActivity.java similarity index 94% rename from app/src/main/java/ru/meefik/linuxdeploy/FullscreenActivity.java rename to app/src/main/java/ru/meefik/linuxdeploy/activity/FullscreenActivity.java index 09fcdc6c..2ea01c55 100644 --- a/app/src/main/java/ru/meefik/linuxdeploy/FullscreenActivity.java +++ b/app/src/main/java/ru/meefik/linuxdeploy/activity/FullscreenActivity.java @@ -1,4 +1,4 @@ -package ru.meefik.linuxdeploy; +package ru.meefik.linuxdeploy.activity; import android.content.pm.ActivityInfo; import android.os.Bundle; @@ -8,6 +8,9 @@ import androidx.appcompat.app.AppCompatActivity; +import ru.meefik.linuxdeploy.PrefStore; +import ru.meefik.linuxdeploy.R; + public class FullscreenActivity extends AppCompatActivity { @Override diff --git a/app/src/main/java/ru/meefik/linuxdeploy/MainActivity.java b/app/src/main/java/ru/meefik/linuxdeploy/activity/MainActivity.java similarity index 98% rename from app/src/main/java/ru/meefik/linuxdeploy/MainActivity.java rename to app/src/main/java/ru/meefik/linuxdeploy/activity/MainActivity.java index b0f143c2..7398f336 100644 --- a/app/src/main/java/ru/meefik/linuxdeploy/MainActivity.java +++ b/app/src/main/java/ru/meefik/linuxdeploy/activity/MainActivity.java @@ -1,4 +1,4 @@ -package ru.meefik.linuxdeploy; +package ru.meefik.linuxdeploy.activity; import android.Manifest; import android.content.Intent; @@ -37,6 +37,14 @@ import androidx.core.view.GravityCompat; import androidx.drawerlayout.widget.DrawerLayout; +import ru.meefik.linuxdeploy.EnvUtils; +import ru.meefik.linuxdeploy.Logger; +import ru.meefik.linuxdeploy.receiver.NetworkReceiver; +import ru.meefik.linuxdeploy.receiver.PowerReceiver; +import ru.meefik.linuxdeploy.PrefStore; +import ru.meefik.linuxdeploy.R; +import ru.meefik.linuxdeploy.UpdateEnvTask; + public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener { diff --git a/app/src/main/java/ru/meefik/linuxdeploy/MountsActivity.java b/app/src/main/java/ru/meefik/linuxdeploy/activity/MountsActivity.java similarity index 98% rename from app/src/main/java/ru/meefik/linuxdeploy/MountsActivity.java rename to app/src/main/java/ru/meefik/linuxdeploy/activity/MountsActivity.java index e516aeff..c9b6ac2b 100644 --- a/app/src/main/java/ru/meefik/linuxdeploy/MountsActivity.java +++ b/app/src/main/java/ru/meefik/linuxdeploy/activity/MountsActivity.java @@ -1,4 +1,4 @@ -package ru.meefik.linuxdeploy; +package ru.meefik.linuxdeploy.activity; import android.content.DialogInterface; import android.os.Bundle; @@ -20,6 +20,9 @@ import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; +import ru.meefik.linuxdeploy.PrefStore; +import ru.meefik.linuxdeploy.R; + public class MountsActivity extends AppCompatActivity { private List listItems = new ArrayList<>(); diff --git a/app/src/main/java/ru/meefik/linuxdeploy/ProfilesActivity.java b/app/src/main/java/ru/meefik/linuxdeploy/activity/ProfilesActivity.java similarity index 98% rename from app/src/main/java/ru/meefik/linuxdeploy/ProfilesActivity.java rename to app/src/main/java/ru/meefik/linuxdeploy/activity/ProfilesActivity.java index 2087533d..186abd90 100644 --- a/app/src/main/java/ru/meefik/linuxdeploy/ProfilesActivity.java +++ b/app/src/main/java/ru/meefik/linuxdeploy/activity/ProfilesActivity.java @@ -1,4 +1,4 @@ -package ru.meefik.linuxdeploy; +package ru.meefik.linuxdeploy.activity; import android.content.Context; import android.content.DialogInterface; @@ -21,6 +21,9 @@ import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; +import ru.meefik.linuxdeploy.PrefStore; +import ru.meefik.linuxdeploy.R; + public class ProfilesActivity extends AppCompatActivity implements OnTouchListener { private ListView listView; diff --git a/app/src/main/java/ru/meefik/linuxdeploy/PropertiesActivity.java b/app/src/main/java/ru/meefik/linuxdeploy/activity/PropertiesActivity.java similarity index 99% rename from app/src/main/java/ru/meefik/linuxdeploy/PropertiesActivity.java rename to app/src/main/java/ru/meefik/linuxdeploy/activity/PropertiesActivity.java index 01781541..93240fca 100644 --- a/app/src/main/java/ru/meefik/linuxdeploy/PropertiesActivity.java +++ b/app/src/main/java/ru/meefik/linuxdeploy/activity/PropertiesActivity.java @@ -1,4 +1,4 @@ -package ru.meefik.linuxdeploy; +package ru.meefik.linuxdeploy.activity; import android.content.Intent; import android.content.SharedPreferences; @@ -11,6 +11,9 @@ import android.preference.PreferenceScreen; import android.view.MenuItem; +import ru.meefik.linuxdeploy.PrefStore; +import ru.meefik.linuxdeploy.R; + public class PropertiesActivity extends AppCompatPreferenceActivity implements Preference.OnPreferenceClickListener, OnSharedPreferenceChangeListener { diff --git a/app/src/main/java/ru/meefik/linuxdeploy/RepositoryActivity.java b/app/src/main/java/ru/meefik/linuxdeploy/activity/RepositoryActivity.java similarity index 99% rename from app/src/main/java/ru/meefik/linuxdeploy/RepositoryActivity.java rename to app/src/main/java/ru/meefik/linuxdeploy/activity/RepositoryActivity.java index 24980324..6fe464be 100644 --- a/app/src/main/java/ru/meefik/linuxdeploy/RepositoryActivity.java +++ b/app/src/main/java/ru/meefik/linuxdeploy/activity/RepositoryActivity.java @@ -1,4 +1,4 @@ -package ru.meefik.linuxdeploy; +package ru.meefik.linuxdeploy.activity; import android.app.ProgressDialog; import android.content.Intent; @@ -28,7 +28,6 @@ import java.lang.ref.WeakReference; import java.net.HttpURLConnection; import java.net.URL; -import java.net.URLConnection; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -38,6 +37,9 @@ import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; +import ru.meefik.linuxdeploy.PrefStore; +import ru.meefik.linuxdeploy.R; + public class RepositoryActivity extends AppCompatActivity { private List> profiles = new ArrayList<>(); diff --git a/app/src/main/java/ru/meefik/linuxdeploy/SettingsActivity.java b/app/src/main/java/ru/meefik/linuxdeploy/activity/SettingsActivity.java similarity index 96% rename from app/src/main/java/ru/meefik/linuxdeploy/SettingsActivity.java rename to app/src/main/java/ru/meefik/linuxdeploy/activity/SettingsActivity.java index a375bab4..5cecc083 100644 --- a/app/src/main/java/ru/meefik/linuxdeploy/SettingsActivity.java +++ b/app/src/main/java/ru/meefik/linuxdeploy/activity/SettingsActivity.java @@ -1,9 +1,8 @@ -package ru.meefik.linuxdeploy; +package ru.meefik.linuxdeploy.activity; import android.Manifest; import android.content.ComponentName; import android.content.Context; -import android.content.DialogInterface; import android.content.SharedPreferences; import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.content.pm.PackageManager; @@ -19,6 +18,13 @@ import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; +import ru.meefik.linuxdeploy.receiver.BootReceiver; +import ru.meefik.linuxdeploy.EnvUtils; +import ru.meefik.linuxdeploy.PrefStore; +import ru.meefik.linuxdeploy.R; +import ru.meefik.linuxdeploy.RemoveEnvTask; +import ru.meefik.linuxdeploy.UpdateEnvTask; + public class SettingsActivity extends AppCompatPreferenceActivity implements OnSharedPreferenceChangeListener, Preference.OnPreferenceClickListener { diff --git a/app/src/main/java/ru/meefik/linuxdeploy/ActionReceiver.java b/app/src/main/java/ru/meefik/linuxdeploy/receiver/ActionReceiver.java similarity index 95% rename from app/src/main/java/ru/meefik/linuxdeploy/ActionReceiver.java rename to app/src/main/java/ru/meefik/linuxdeploy/receiver/ActionReceiver.java index 0f4831ef..5abf5cb0 100644 --- a/app/src/main/java/ru/meefik/linuxdeploy/ActionReceiver.java +++ b/app/src/main/java/ru/meefik/linuxdeploy/receiver/ActionReceiver.java @@ -1,4 +1,4 @@ -package ru.meefik.linuxdeploy; +package ru.meefik.linuxdeploy.receiver; import android.app.NotificationManager; import android.content.BroadcastReceiver; @@ -7,6 +7,10 @@ import androidx.core.app.NotificationCompat; +import ru.meefik.linuxdeploy.EnvUtils; +import ru.meefik.linuxdeploy.R; +import ru.meefik.linuxdeploy.activity.MainActivity; + import static ru.meefik.linuxdeploy.App.SERVICE_CHANNEL_ID; public class ActionReceiver extends BroadcastReceiver { diff --git a/app/src/main/java/ru/meefik/linuxdeploy/BootReceiver.java b/app/src/main/java/ru/meefik/linuxdeploy/receiver/BootReceiver.java similarity index 91% rename from app/src/main/java/ru/meefik/linuxdeploy/BootReceiver.java rename to app/src/main/java/ru/meefik/linuxdeploy/receiver/BootReceiver.java index 705beedd..0d22cf5e 100644 --- a/app/src/main/java/ru/meefik/linuxdeploy/BootReceiver.java +++ b/app/src/main/java/ru/meefik/linuxdeploy/receiver/BootReceiver.java @@ -1,9 +1,12 @@ -package ru.meefik.linuxdeploy; +package ru.meefik.linuxdeploy.receiver; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; +import ru.meefik.linuxdeploy.EnvUtils; +import ru.meefik.linuxdeploy.PrefStore; + public class BootReceiver extends BroadcastReceiver { @Override diff --git a/app/src/main/java/ru/meefik/linuxdeploy/NetworkReceiver.java b/app/src/main/java/ru/meefik/linuxdeploy/receiver/NetworkReceiver.java similarity index 92% rename from app/src/main/java/ru/meefik/linuxdeploy/NetworkReceiver.java rename to app/src/main/java/ru/meefik/linuxdeploy/receiver/NetworkReceiver.java index e557663a..460f903e 100644 --- a/app/src/main/java/ru/meefik/linuxdeploy/NetworkReceiver.java +++ b/app/src/main/java/ru/meefik/linuxdeploy/receiver/NetworkReceiver.java @@ -1,4 +1,4 @@ -package ru.meefik.linuxdeploy; +package ru.meefik.linuxdeploy.receiver; import android.content.BroadcastReceiver; import android.content.Context; @@ -6,6 +6,8 @@ import android.net.ConnectivityManager; import android.net.NetworkInfo; +import ru.meefik.linuxdeploy.EnvUtils; + public class NetworkReceiver extends BroadcastReceiver { @Override diff --git a/app/src/main/java/ru/meefik/linuxdeploy/PowerReceiver.java b/app/src/main/java/ru/meefik/linuxdeploy/receiver/PowerReceiver.java similarity index 86% rename from app/src/main/java/ru/meefik/linuxdeploy/PowerReceiver.java rename to app/src/main/java/ru/meefik/linuxdeploy/receiver/PowerReceiver.java index e5a55cf2..c0d52aa6 100644 --- a/app/src/main/java/ru/meefik/linuxdeploy/PowerReceiver.java +++ b/app/src/main/java/ru/meefik/linuxdeploy/receiver/PowerReceiver.java @@ -1,9 +1,11 @@ -package ru.meefik.linuxdeploy; +package ru.meefik.linuxdeploy.receiver; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; +import ru.meefik.linuxdeploy.EnvUtils; + public class PowerReceiver extends BroadcastReceiver { @Override diff --git a/app/src/main/res/layout-land/content_main.xml b/app/src/main/res/layout-land/content_main.xml index 70fdc924..3fcfbde5 100644 --- a/app/src/main/res/layout-land/content_main.xml +++ b/app/src/main/res/layout-land/content_main.xml @@ -4,7 +4,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior" - tools:context=".MainActivity" + tools:context=".activity.MainActivity" tools:showIn="@layout/activity_main"> + tools:context=".activity.AboutActivity"> + tools:context=".activity.FullscreenActivity"> \ No newline at end of file diff --git a/app/src/main/res/layout/activity_mounts.xml b/app/src/main/res/layout/activity_mounts.xml index fa5abc3a..debac9f1 100644 --- a/app/src/main/res/layout/activity_mounts.xml +++ b/app/src/main/res/layout/activity_mounts.xml @@ -2,7 +2,7 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" - tools:context=".MountsActivity"> + tools:context=".activity.MountsActivity"> + tools:context=".activity.ProfilesActivity"> + tools:context=".activity.RepositoryActivity"> Date: Sun, 12 Jan 2020 22:28:03 +0100 Subject: [PATCH 02/12] Refactored RepositoryActivity and its dependencies :D Added OkHttp3 dependency for web communication --- app/build.gradle | 1 + .../activity/RepositoryActivity.java | 434 ++++++------------ .../adapter/RepositoryProfileAdapter.java | 112 +++++ .../linuxdeploy/model/RepositoryProfile.java | 44 ++ .../main/res/layout/activity_repository.xml | 17 +- app/src/main/res/layout/repository_row.xml | 63 ++- 6 files changed, 353 insertions(+), 318 deletions(-) create mode 100644 app/src/main/java/ru/meefik/linuxdeploy/adapter/RepositoryProfileAdapter.java create mode 100644 app/src/main/java/ru/meefik/linuxdeploy/model/RepositoryProfile.java diff --git a/app/build.gradle b/app/build.gradle index d27ed67e..34230e8e 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -33,4 +33,5 @@ dependencies { implementation 'androidx.appcompat:appcompat:1.1.0' implementation 'androidx.browser:browser:1.2.0' implementation 'androidx.constraintlayout:constraintlayout:1.1.3' + implementation 'com.squareup.okhttp3:okhttp:4.3.1' } diff --git a/app/src/main/java/ru/meefik/linuxdeploy/activity/RepositoryActivity.java b/app/src/main/java/ru/meefik/linuxdeploy/activity/RepositoryActivity.java index 6fe464be..21ab2cc8 100644 --- a/app/src/main/java/ru/meefik/linuxdeploy/activity/RepositoryActivity.java +++ b/app/src/main/java/ru/meefik/linuxdeploy/activity/RepositoryActivity.java @@ -3,72 +3,70 @@ import android.app.ProgressDialog; import android.content.Intent; import android.content.pm.PackageManager; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; import android.net.Uri; -import android.os.AsyncTask; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ArrayAdapter; import android.widget.EditText; -import android.widget.ImageView; -import android.widget.ListView; -import android.widget.TextView; import android.widget.Toast; +import androidx.appcompat.app.AlertDialog; +import androidx.appcompat.app.AppCompatActivity; +import androidx.recyclerview.widget.DividerItemDecoration; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import org.jetbrains.annotations.NotNull; + import java.io.BufferedReader; import java.io.FileOutputStream; import java.io.IOException; -import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; -import java.lang.ref.WeakReference; -import java.net.HttpURLConnection; -import java.net.URL; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.zip.GZIPInputStream; -import androidx.appcompat.app.AlertDialog; -import androidx.appcompat.app.AppCompatActivity; - +import okhttp3.Call; +import okhttp3.Callback; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; import ru.meefik.linuxdeploy.PrefStore; import ru.meefik.linuxdeploy.R; +import ru.meefik.linuxdeploy.adapter.RepositoryProfileAdapter; +import ru.meefik.linuxdeploy.model.RepositoryProfile; public class RepositoryActivity extends AppCompatActivity { - private List> profiles = new ArrayList<>(); - private ArrayAdapter> adapter; + private RepositoryProfileAdapter adapter; private boolean isDonated() { return getPackageManager().checkSignatures(getPackageName(), "ru.meefik.donate") == PackageManager.SIGNATURE_MATCH; } - private void importDialog(final Map profile) { - final String name = profile.get("PROFILE"); + private void importDialog(final RepositoryProfile repositoryProfile) { + final String name = repositoryProfile.getProfile(); final String message = getString(R.string.repository_import_message, - profile.get("DESC"), - profile.get("SIZE")); + repositoryProfile.getDescription(), + repositoryProfile.getSize()); + AlertDialog.Builder dialog = new AlertDialog.Builder(this) .setTitle(name) .setMessage(message) .setCancelable(false) - .setNegativeButton(android.R.string.no, - (dialog13, whichButton) -> dialog13.cancel()); - if (!isDonated()) { + .setNegativeButton(android.R.string.no, (dialog13, which) -> dialog13.cancel()); + + if (isDonated()) { + dialog.setPositiveButton(R.string.repository_import_button, + (dialog1, whichButton) -> importProfile(name)); + } else { dialog.setPositiveButton(R.string.repository_purchase_button, (dialog12, whichButton) -> startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=ru.meefik.donate")))); - } else { - dialog.setPositiveButton(R.string.repository_import_button, - (dialog1, whichButton) -> importProfile(name)); } + dialog.show(); } @@ -82,87 +80,140 @@ private void changeUrlDialog() { .setPositiveButton(android.R.string.ok, (dialog, whichButton) -> { String text = input.getText().toString(); - if (text.isEmpty()) text = getString(R.string.repository_url); + if (text.isEmpty()) + text = getString(R.string.repository_url); PrefStore.setRepositoryUrl(getApplicationContext(), text); retrieveIndex(); - }).setNegativeButton(android.R.string.cancel, - (dialog, whichButton) -> dialog.cancel()).show(); + }) + .setNegativeButton(android.R.string.cancel, + (dialog, whichButton) -> dialog.cancel()) + .show(); } private void retrieveIndex() { String url = PrefStore.getRepositoryUrl(this); - new RetrieveIndexTask(this).execute(url); + + OkHttpClient client = new OkHttpClient.Builder() + .followRedirects(true) + .build(); + Request request = new Request.Builder() + .url(url + "/index.gz") + .build(); + + ProgressDialog dialog = new ProgressDialog(this); + dialog.setMessage(getString(R.string.loading_message)); + dialog.setCancelable(false); + dialog.show(); + + client.newCall(request).enqueue(new Callback() { + @Override + public void onFailure(@NotNull Call call, @NotNull IOException e) { + onFailure(); + } + + @Override + public void onResponse(@NotNull Call call, @NotNull Response response) { + if (response.isSuccessful()) { + try (BufferedReader reader = new BufferedReader(new InputStreamReader(new GZIPInputStream(response.body().byteStream())))) { + List repositoryProfiles = new ArrayList<>(); + String line; + RepositoryProfile repositoryProfile = null; + while ((line = reader.readLine()) != null) { + if (line.startsWith("PROFILE")) { + repositoryProfile = new RepositoryProfile(); + repositoryProfile.setProfile(line.split("=")[1]); + } else if (line.startsWith("DESC")) { + repositoryProfile.setDescription(line.split("=")[1]); + } else if (line.startsWith("TYPE")) { + repositoryProfile.setType(line.split("=")[1]); + } else if (line.startsWith("SIZE")) { + repositoryProfile.setSize(line.split("=")[1]); + repositoryProfiles.add(repositoryProfile); + } + } + + runOnUiThread(() -> { + adapter.setRepositoryProfiles(repositoryProfiles); + dialog.dismiss(); + }); + } catch (IOException e) { + onFailure(); + } + } else { + onFailure(); + } + } + + private void onFailure() { + runOnUiThread(() -> { + dialog.dismiss(); + Toast.makeText(RepositoryActivity.this, R.string.toast_loading_error, Toast.LENGTH_SHORT).show(); + }); + } + }); } private void importProfile(String name) { String url = PrefStore.getRepositoryUrl(this); - new ImportProfileTask(this).execute(url, name); - } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - PrefStore.setLocale(this); - setContentView(R.layout.activity_repository); + OkHttpClient client = new OkHttpClient.Builder() + .followRedirects(true) + .build(); + Request request = new Request.Builder() + .url(url + "/index.gz") + .build(); + + ProgressDialog dialog = new ProgressDialog(this); + dialog.setMessage(getString(R.string.loading_message)); + dialog.setCancelable(false); + dialog.show(); - // ListView Adapter - ListView listView = findViewById(R.id.repositoryView); - adapter = new ArrayAdapter>(this, - R.layout.repository_row, R.id.repo_entry_title, profiles) { + client.newCall(request).enqueue(new Callback() { @Override - public View getView(int position, View convertView, ViewGroup parent) { - View view = super.getView(position, convertView, parent); - TextView title = view.findViewById(R.id.repo_entry_title); - TextView subTitle = view.findViewById(R.id.repo_entry_subtitle); - ImageView icon = view.findViewById(R.id.repo_entry_icon); - String name = profiles.get(position).get("PROFILE"); - String desc = profiles.get(position).get("DESC"); - String type = profiles.get(position).get("TYPE"); - int iconRes = R.raw.linux; - if (type != null) { - switch (type) { - case "alpine": - iconRes = R.raw.alpine; - break; - case "archlinux": - iconRes = R.raw.archlinux; - break; - case "centos": - iconRes = R.raw.centos; - break; - case "debian": - iconRes = R.raw.debian; - break; - case "fedora": - iconRes = R.raw.fedora; - break; - case "kali": - iconRes = R.raw.kali; - break; - case "slackware": - iconRes = R.raw.slackware; - break; - case "ubuntu": - iconRes = R.raw.ubuntu; - break; + public void onFailure(@NotNull Call call, @NotNull IOException e) { + onFailure(); + } + + @Override + public void onResponse(@NotNull Call call, @NotNull Response response) { + if (response.isSuccessful()) { + String conf = PrefStore.getEnvDir(RepositoryActivity.this) + "/config/" + name + ".conf"; + try (OutputStream os = new FileOutputStream(conf)) { + os.write(response.body().bytes()); + + runOnUiThread(dialog::dismiss); + PrefStore.changeProfile(RepositoryActivity.this, name); + finish(); + } catch (IOException e) { + onFailure(); } + } else { + onFailure(); } - InputStream imageStream = view.getResources().openRawResource(iconRes); - Bitmap bitmap = BitmapFactory.decodeStream(imageStream); - icon.setImageBitmap(bitmap); - title.setText(name); - if (desc != null && !desc.isEmpty()) subTitle.setText(desc); - else subTitle.setText(getString(R.string.repository_default_description)); - return view; } - }; - listView.setAdapter(adapter); - // Click listener - listView.setOnItemClickListener((parent, view, position, id) -> { - Map profile = (Map) parent.getItemAtPosition(position); - importDialog(profile); + private void onFailure() { + runOnUiThread(() -> { + dialog.dismiss(); + Toast.makeText(RepositoryActivity.this, R.string.toast_loading_error, Toast.LENGTH_SHORT).show(); + }); + } }); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + PrefStore.setLocale(this); + setContentView(R.layout.activity_repository); + + // RecyclerView Adapter + RecyclerView recyclerView = findViewById(R.id.repositoryView); + adapter = new RepositoryProfileAdapter(); + adapter.setOnItemClickListener(this::importDialog); + recyclerView.setAdapter(adapter); + recyclerView.setLayoutManager(new LinearLayoutManager(this)); + recyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL)); // Load list retrieveIndex(); @@ -179,11 +230,6 @@ public void onResume() { setTitle(R.string.title_activity_repository); } - @Override - public void onPause() { - super.onPause(); - } - @Override public boolean onCreateOptionsMenu(Menu menu) { PrefStore.setLocale(this); @@ -196,196 +242,12 @@ public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.menu_refresh: retrieveIndex(); - break; + return true; case R.id.menu_change_url: changeUrlDialog(); - break; - } - return false; - } - - static class RetrieveIndexTask extends AsyncTask { - - private ProgressDialog dialog; - private WeakReference contextWeakReference; - - RetrieveIndexTask(RepositoryActivity context) { - this.contextWeakReference = new WeakReference<>(context); - } - - @Override - protected void onPreExecute() { - RepositoryActivity context = contextWeakReference.get(); - - if (context != null) { - dialog = new ProgressDialog(context); - dialog.setMessage(context.getString(R.string.loading_message)); - dialog.show(); - context.profiles.clear(); - } - } - - @Override - protected Boolean doInBackground(String... params) { - // params comes from the execute() call: params[0] is the url. - try { - downloadUrl(params[0]); - } catch (Exception e) { - e.printStackTrace(); - return false; - } - return true; - } - - @Override - protected void onPostExecute(Boolean success) { - RepositoryActivity context = contextWeakReference.get(); - - if (context != null) { - if (dialog.isShowing()) { - dialog.dismiss(); - } - context.adapter.notifyDataSetChanged(); - if (!success) { - Toast.makeText(context, R.string.toast_loading_error, Toast.LENGTH_SHORT).show(); - } - } - } - - private void downloadUrl(String url) throws IOException { - BufferedReader reader = null; - try { - url = url + "/index.gz"; - HttpURLConnection conn; - boolean redirect; - do { - redirect = false; - conn = (HttpURLConnection) (new URL(url)).openConnection(); - // normally, 3xx is redirect - int status = conn.getResponseCode(); - if (status != HttpURLConnection.HTTP_OK) { - if (status == HttpURLConnection.HTTP_MOVED_TEMP - || status == HttpURLConnection.HTTP_MOVED_PERM - || status == HttpURLConnection.HTTP_SEE_OTHER) - redirect = true; - } - if (redirect) { - url = conn.getHeaderField("Location"); - } - } while (redirect); - conn.connect(); - reader = new BufferedReader(new InputStreamReader(new GZIPInputStream(conn.getInputStream()))); - String line; - Map map = new HashMap<>(); - while ((line = reader.readLine()) != null) { - if (line.isEmpty()) { - if (!map.isEmpty()) { - RepositoryActivity context = contextWeakReference.get(); - if (context != null) { - context.profiles.add(map); - } - } - map = new HashMap<>(); - continue; - } - if (!line.startsWith("#")) { - String[] pair = line.split("="); - String key = pair[0]; - String value = pair[1]; - map.put(key, value); - } - } - } finally { - if (reader != null) reader.close(); - } - } - } - - static class ImportProfileTask extends AsyncTask { - - private ProgressDialog dialog; - private WeakReference contextWeakReference; - private String profile; - - ImportProfileTask(RepositoryActivity context) { - this.contextWeakReference = new WeakReference<>(context); - } - - @Override - protected void onPreExecute() { - RepositoryActivity context = contextWeakReference.get(); - if (context != null) { - dialog = new ProgressDialog(context); - dialog.setMessage(context.getString(R.string.loading_message)); - dialog.show(); - } - } - - @Override - protected Boolean doInBackground(String... params) { - profile = params[1]; - try { - downloadUrlAndImport(params[0], params[1]); - } catch (Exception e) { - return false; - } - return true; - } - - @Override - protected void onPostExecute(Boolean success) { - RepositoryActivity context = contextWeakReference.get(); - if (context != null) { - if (dialog.isShowing()) { - dialog.dismiss(); - } - if (success) { - PrefStore.changeProfile(context, profile); - context.finish(); - } else { - Toast.makeText(context, R.string.toast_loading_error, Toast.LENGTH_SHORT).show(); - } - } - } - - private void downloadUrlAndImport(String url, String profile) throws IOException { - RepositoryActivity context = contextWeakReference.get(); - if (context != null) { - String conf = PrefStore.getEnvDir(context) + "/config/" + profile + ".conf"; - InputStream in = null; - OutputStream out = null; - try { - url = url + "/config/" + profile + ".conf"; - HttpURLConnection conn; - boolean redirect; - do { - redirect = false; - conn = (HttpURLConnection) (new URL(url)).openConnection(); - // normally, 3xx is redirect - int status = conn.getResponseCode(); - if (status != HttpURLConnection.HTTP_OK) { - if (status == HttpURLConnection.HTTP_MOVED_TEMP - || status == HttpURLConnection.HTTP_MOVED_PERM - || status == HttpURLConnection.HTTP_SEE_OTHER) - redirect = true; - } - if (redirect) { - url = conn.getHeaderField("Location"); - } - } while (redirect); - conn.connect(); - in = conn.getInputStream(); - out = new FileOutputStream(conf); - byte[] buffer = new byte[1024]; - int read; - while ((read = in.read(buffer)) != -1) { - out.write(buffer, 0, read); - } - } finally { - if (in != null) in.close(); - if (out != null) out.close(); - } - } + return true; + default: + return super.onOptionsItemSelected(item); } } } diff --git a/app/src/main/java/ru/meefik/linuxdeploy/adapter/RepositoryProfileAdapter.java b/app/src/main/java/ru/meefik/linuxdeploy/adapter/RepositoryProfileAdapter.java new file mode 100644 index 00000000..a844b548 --- /dev/null +++ b/app/src/main/java/ru/meefik/linuxdeploy/adapter/RepositoryProfileAdapter.java @@ -0,0 +1,112 @@ +package ru.meefik.linuxdeploy.adapter; + +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import java.util.List; + +import ru.meefik.linuxdeploy.R; +import ru.meefik.linuxdeploy.model.RepositoryProfile; + +public class RepositoryProfileAdapter extends RecyclerView.Adapter { + + private List repositoryProfiles; + private OnItemClickListener listener; + + @NonNull + @Override + public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.repository_row, parent, false); + return new ViewHolder(view); + } + + @Override + public void onBindViewHolder(@NonNull ViewHolder holder, int position) { + holder.setRepository(repositoryProfiles.get(position)); + } + + @Override + public int getItemCount() { + return repositoryProfiles != null ? repositoryProfiles.size() : 0; + } + + public void setRepositoryProfiles(List repositoryProfiles) { + this.repositoryProfiles = repositoryProfiles; + notifyDataSetChanged(); + } + + public void setOnItemClickListener(OnItemClickListener listener) { + this.listener = listener; + } + + class ViewHolder extends RecyclerView.ViewHolder { + + private View view; + private TextView title; + private TextView subTitle; + private ImageView icon; + + public ViewHolder(@NonNull View itemView) { + super(itemView); + + view = itemView; + title = itemView.findViewById(R.id.repo_entry_title); + subTitle = itemView.findViewById(R.id.repo_entry_subtitle); + icon = itemView.findViewById(R.id.repo_entry_icon); + } + + public void setRepository(RepositoryProfile repositoryProfile) { + int iconRes = R.raw.linux; + if (repositoryProfile.getType() != null) { + switch (repositoryProfile.getType()) { + case "alpine": + iconRes = R.raw.alpine; + break; + case "archlinux": + iconRes = R.raw.archlinux; + break; + case "centos": + iconRes = R.raw.centos; + break; + case "debian": + iconRes = R.raw.debian; + break; + case "fedora": + iconRes = R.raw.fedora; + break; + case "kali": + iconRes = R.raw.kali; + break; + case "slackware": + iconRes = R.raw.slackware; + break; + case "ubuntu": + iconRes = R.raw.ubuntu; + break; + } + } + + icon.setImageResource(iconRes); + title.setText(repositoryProfile.getProfile()); + if (repositoryProfile.getDescription() != null && !repositoryProfile.getDescription().isEmpty()) + subTitle.setText(repositoryProfile.getDescription()); + else + subTitle.setText(view.getContext().getString(R.string.repository_default_description)); + + view.setOnClickListener(v -> { + if (listener != null) + listener.onClick(repositoryProfile); + }); + } + } + + public interface OnItemClickListener { + void onClick(RepositoryProfile repositoryProfile); + } +} diff --git a/app/src/main/java/ru/meefik/linuxdeploy/model/RepositoryProfile.java b/app/src/main/java/ru/meefik/linuxdeploy/model/RepositoryProfile.java new file mode 100644 index 00000000..9bb2f708 --- /dev/null +++ b/app/src/main/java/ru/meefik/linuxdeploy/model/RepositoryProfile.java @@ -0,0 +1,44 @@ +package ru.meefik.linuxdeploy.model; + +public class RepositoryProfile { + private String profile; + private String description; + private String type; + private String size; + + public RepositoryProfile() { + // Empty constructor + } + + public String getProfile() { + return profile; + } + + public void setProfile(String profile) { + this.profile = profile; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getSize() { + return size; + } + + public void setSize(String size) { + this.size = size; + } +} diff --git a/app/src/main/res/layout/activity_repository.xml b/app/src/main/res/layout/activity_repository.xml index 580030c4..7c596d3d 100644 --- a/app/src/main/res/layout/activity_repository.xml +++ b/app/src/main/res/layout/activity_repository.xml @@ -1,16 +1,7 @@ - - - - - + android:scrollbars="vertical" + tools:context=".activity.RepositoryActivity" /> diff --git a/app/src/main/res/layout/repository_row.xml b/app/src/main/res/layout/repository_row.xml index 0e951c38..4e796221 100644 --- a/app/src/main/res/layout/repository_row.xml +++ b/app/src/main/res/layout/repository_row.xml @@ -1,32 +1,57 @@ - + + android:layout_width="32dp" + android:layout_height="32dp" + android:layout_marginStart="8dp" + android:layout_marginLeft="8dp" + android:layout_marginTop="4dp" + android:layout_marginBottom="4dp" + android:adjustViewBounds="true" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> + android:textStyle="bold" + app:layout_constraintBottom_toTopOf="@+id/repo_entry_subtitle" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintHorizontal_bias="0.0" + app:layout_constraintStart_toEndOf="@+id/repo_entry_icon" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintVertical_chainStyle="packed" /> + android:layout_marginStart="8dp" + android:layout_marginLeft="8dp" + android:layout_marginEnd="8dp" + android:layout_marginRight="8dp" + android:layout_marginBottom="4dp" + android:textSize="14sp" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintHorizontal_bias="0.0" + app:layout_constraintStart_toEndOf="@+id/repo_entry_icon" + app:layout_constraintTop_toBottomOf="@+id/repo_entry_title" + app:layout_constraintVertical_chainStyle="packed" /> - + From 5b5b7920d462c3159d5bbcd1671c4d66d417462d Mon Sep 17 00:00:00 2001 From: Iscle Date: Sun, 12 Jan 2020 23:41:58 +0100 Subject: [PATCH 03/12] Fix API 29 class deprecation --- .../linuxdeploy/activity/MainActivity.java | 9 ++++++++- .../linuxdeploy/receiver/NetworkReceiver.java | 20 ++++++++++++++++--- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/ru/meefik/linuxdeploy/activity/MainActivity.java b/app/src/main/java/ru/meefik/linuxdeploy/activity/MainActivity.java index 7398f336..727f0e91 100644 --- a/app/src/main/java/ru/meefik/linuxdeploy/activity/MainActivity.java +++ b/app/src/main/java/ru/meefik/linuxdeploy/activity/MainActivity.java @@ -10,6 +10,7 @@ import android.net.Uri; import android.net.wifi.WifiManager; import android.net.wifi.WifiManager.WifiLock; +import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.PowerManager; @@ -39,6 +40,7 @@ import ru.meefik.linuxdeploy.EnvUtils; import ru.meefik.linuxdeploy.Logger; +import ru.meefik.linuxdeploy.fragment.PropertiesFragment; import ru.meefik.linuxdeploy.receiver.NetworkReceiver; import ru.meefik.linuxdeploy.receiver.PowerReceiver; import ru.meefik.linuxdeploy.PrefStore; @@ -116,7 +118,12 @@ public void onCreate(Bundle savedInstanceState) { // WiFi lock init WifiManager wifiManager = (WifiManager) getApplicationContext().getSystemService(android.content.Context.WIFI_SERVICE); - wifiLock = wifiManager.createWifiLock(WifiManager.WIFI_MODE_FULL, getPackageName()); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + // WIFI_MODE_FULL has been deprecated since API level 29 and will have no impact! + wifiLock = wifiManager.createWifiLock(WifiManager.WIFI_MODE_FULL_HIGH_PERF, getPackageName()); + } else { + wifiLock = wifiManager.createWifiLock(WifiManager.WIFI_MODE_FULL, getPackageName()); + } // Wake lock PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE); diff --git a/app/src/main/java/ru/meefik/linuxdeploy/receiver/NetworkReceiver.java b/app/src/main/java/ru/meefik/linuxdeploy/receiver/NetworkReceiver.java index 460f903e..fac59464 100644 --- a/app/src/main/java/ru/meefik/linuxdeploy/receiver/NetworkReceiver.java +++ b/app/src/main/java/ru/meefik/linuxdeploy/receiver/NetworkReceiver.java @@ -4,6 +4,8 @@ import android.content.Context; import android.content.Intent; import android.net.ConnectivityManager; +import android.net.Network; +import android.net.NetworkCapabilities; import android.net.NetworkInfo; import ru.meefik.linuxdeploy.EnvUtils; @@ -16,9 +18,21 @@ public void onReceive(final Context context, Intent intent) { ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); - NetworkInfo activeNetwork = cm.getActiveNetworkInfo(); - boolean isConnected = false; - if (activeNetwork != null) isConnected = activeNetwork.isConnected(); + boolean isConnected; + + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) { + Network activeNetwork = cm.getActiveNetwork(); + NetworkCapabilities networkCapabilities = cm.getNetworkCapabilities(activeNetwork); + + isConnected = networkCapabilities != null + && (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) + || networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) + || networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)); + } else { + NetworkInfo activeNetworkInfo = cm.getActiveNetworkInfo(); + isConnected = activeNetworkInfo != null && activeNetworkInfo.isConnected(); + } + if (isConnected) { EnvUtils.execService(context, "start", "core/net"); } else { From b3878ffda0537bf0733cb8960be3a7bb8fd5cc2f Mon Sep 17 00:00:00 2001 From: Iscle Date: Sun, 12 Jan 2020 23:42:45 +0100 Subject: [PATCH 04/12] Fixed deprecated Preference activity The UI is a bit different, but it's not noticeable. --- .../activity/AppCompatPreferenceActivity.java | 134 -------- .../activity/PropertiesActivity.java | 303 +---------------- .../activity/SettingsActivity.java | 186 +---------- .../fragment/PropertiesFragment.java | 305 ++++++++++++++++++ .../fragment/SettingsFragment.java | 210 ++++++++++++ 5 files changed, 537 insertions(+), 601 deletions(-) delete mode 100644 app/src/main/java/ru/meefik/linuxdeploy/activity/AppCompatPreferenceActivity.java create mode 100644 app/src/main/java/ru/meefik/linuxdeploy/fragment/PropertiesFragment.java create mode 100644 app/src/main/java/ru/meefik/linuxdeploy/fragment/SettingsFragment.java diff --git a/app/src/main/java/ru/meefik/linuxdeploy/activity/AppCompatPreferenceActivity.java b/app/src/main/java/ru/meefik/linuxdeploy/activity/AppCompatPreferenceActivity.java deleted file mode 100644 index c894a877..00000000 --- a/app/src/main/java/ru/meefik/linuxdeploy/activity/AppCompatPreferenceActivity.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package ru.meefik.linuxdeploy.activity; - -import android.content.res.Configuration; -import android.os.Bundle; -import android.preference.PreferenceActivity; -import android.view.MenuInflater; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; - -import androidx.annotation.LayoutRes; -import androidx.appcompat.app.ActionBar; -import androidx.appcompat.app.AppCompatDelegate; -import androidx.core.app.NavUtils; - -/** - * A {@link PreferenceActivity} which implements and proxies the necessary calls - * to be used with AppCompat. - *

- * This technique can be used with an {@link android.app.Activity} class, not just - * {@link PreferenceActivity}. - */ -public abstract class AppCompatPreferenceActivity extends PreferenceActivity { - private AppCompatDelegate mDelegate; - - @Override - protected void onCreate(Bundle savedInstanceState) { - getDelegate().installViewFactory(); - getDelegate().onCreate(savedInstanceState); - super.onCreate(savedInstanceState); - } - - @Override - protected void onPostCreate(Bundle savedInstanceState) { - super.onPostCreate(savedInstanceState); - getDelegate().onPostCreate(savedInstanceState); - } - - public ActionBar getSupportActionBar() { - return getDelegate().getSupportActionBar(); - } - - @Override - public MenuInflater getMenuInflater() { - return getDelegate().getMenuInflater(); - } - - @Override - public void setContentView(@LayoutRes int layoutResID) { - getDelegate().setContentView(layoutResID); - } - - @Override - public void setContentView(View view) { - getDelegate().setContentView(view); - } - - @Override - public void setContentView(View view, ViewGroup.LayoutParams params) { - getDelegate().setContentView(view, params); - } - - @Override - public void addContentView(View view, ViewGroup.LayoutParams params) { - getDelegate().addContentView(view, params); - } - - @Override - protected void onPostResume() { - super.onPostResume(); - getDelegate().onPostResume(); - } - - @Override - protected void onTitleChanged(CharSequence title, int color) { - super.onTitleChanged(title, color); - getDelegate().setTitle(title); - } - - @Override - public void onConfigurationChanged(Configuration newConfig) { - super.onConfigurationChanged(newConfig); - getDelegate().onConfigurationChanged(newConfig); - } - - @Override - protected void onStop() { - super.onStop(); - getDelegate().onStop(); - } - - @Override - protected void onDestroy() { - super.onDestroy(); - getDelegate().onDestroy(); - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case android.R.id.home: - NavUtils.navigateUpFromSameTask(this); - return true; - } - return super.onOptionsItemSelected(item); - } - - @Override - public void invalidateOptionsMenu() { - getDelegate().invalidateOptionsMenu(); - } - - private AppCompatDelegate getDelegate() { - if (mDelegate == null) { - mDelegate = AppCompatDelegate.create(this, null); - } - return mDelegate; - } -} \ No newline at end of file diff --git a/app/src/main/java/ru/meefik/linuxdeploy/activity/PropertiesActivity.java b/app/src/main/java/ru/meefik/linuxdeploy/activity/PropertiesActivity.java index 93240fca..13d3f1d9 100644 --- a/app/src/main/java/ru/meefik/linuxdeploy/activity/PropertiesActivity.java +++ b/app/src/main/java/ru/meefik/linuxdeploy/activity/PropertiesActivity.java @@ -1,65 +1,32 @@ package ru.meefik.linuxdeploy.activity; -import android.content.Intent; -import android.content.SharedPreferences; -import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.os.Bundle; -import android.preference.EditTextPreference; -import android.preference.ListPreference; -import android.preference.Preference; -import android.preference.PreferenceGroup; -import android.preference.PreferenceScreen; import android.view.MenuItem; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; + import ru.meefik.linuxdeploy.PrefStore; import ru.meefik.linuxdeploy.R; +import ru.meefik.linuxdeploy.fragment.PropertiesFragment; -public class PropertiesActivity extends AppCompatPreferenceActivity implements - Preference.OnPreferenceClickListener, OnSharedPreferenceChangeListener { +public class PropertiesActivity extends AppCompatActivity { @Override - protected void onCreate(Bundle savedInstanceState) { + protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); PrefStore.setLocale(this); + setContentView(R.layout.activity_preference); - getPreferenceManager().setSharedPreferencesName(PrefStore.getPropertiesSharedName()); + getSupportFragmentManager() + .beginTransaction() + .replace(R.id.frame_layout, new PropertiesFragment()) + .commit(); // Restore from conf file if open from main activity if (getIntent().getBooleanExtra("restore", false)) { PrefStore.restoreProperties(this); } - - Bundle b = getIntent().getExtras(); - int pref = 0; - if (b != null) - pref = b.getInt("pref"); - switch (pref) { - case 1: - addPreferencesFromResource(R.xml.properties_ssh); - break; - case 2: - addPreferencesFromResource(R.xml.properties_vnc); - break; - case 3: - addPreferencesFromResource(R.xml.properties_x11); - break; - case 4: - addPreferencesFromResource(R.xml.properties_fb); - break; - case 5: - addPreferencesFromResource(R.xml.properties_run_parts); - break; - case 6: - addPreferencesFromResource(R.xml.properties_sysv); - break; - case 7: - addPreferencesFromResource(R.xml.properties_pulse); - break; - default: - addPreferencesFromResource(R.xml.properties); - } - - initSummaries(getPreferenceScreen()); } @Override @@ -68,261 +35,19 @@ public void setTheme(int resId) { } @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case android.R.id.home: - finish(); - break; - } - return false; - } - - @Override - public void onResume() { + protected void onResume() { super.onResume(); String titleMsg = getString(R.string.title_activity_properties) + ": " + PrefStore.getProfileName(this); setTitle(titleMsg); - - getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this); } @Override - public void onPause() { + protected void onPause() { super.onPause(); - getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this); - - // update configuration file + // Update configuration file PrefStore.dumpProperties(this); } - - @Override - public boolean onPreferenceClick(Preference preference) { - if (preference.getKey().equals("ssh_properties")) { - Intent intent = new Intent(this, PropertiesActivity.class); - Bundle b = new Bundle(); - b.putInt("pref", 1); - intent.putExtras(b); - startActivity(intent); - } - if (preference.getKey().equals("gui_properties")) { - ListPreference graphics = (ListPreference) findPreference("graphics"); - Intent intent = new Intent(this, PropertiesActivity.class); - Bundle b = new Bundle(); - if (graphics.getValue().equals("vnc")) { - b.putInt("pref", 2); - } - if (graphics.getValue().equals("x11")) { - b.putInt("pref", 3); - } - if (graphics.getValue().equals("fb")) { - b.putInt("pref", 4); - } - intent.putExtras(b); - startActivity(intent); - } - if (preference.getKey().equals("init_properties")) { - ListPreference init = (ListPreference) findPreference("init"); - Intent intent = new Intent(this, PropertiesActivity.class); - Bundle b = new Bundle(); - if (init.getValue().equals("run-parts")) { - b.putInt("pref", 5); - } - if (init.getValue().equals("sysv")) { - b.putInt("pref", 6); - } - intent.putExtras(b); - startActivity(intent); - } - if (preference.getKey().equals("pulse_properties")) { - Intent intent = new Intent(this, PropertiesActivity.class); - Bundle b = new Bundle(); - b.putInt("pref", 7); - intent.putExtras(b); - startActivity(intent); - } - if (preference.getKey().equals("mounts_editor")) { - Intent intent = new Intent(this, MountsActivity.class); - startActivity(intent); - } - return true; - } - - @Override - public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { - Preference pref = findPreference(key); - setSummary(pref, true); - } - - private void initSummaries(PreferenceGroup pg) { - for (int i = 0; i < pg.getPreferenceCount(); ++i) { - Preference p = pg.getPreference(i); - if (p instanceof PreferenceGroup) - initSummaries((PreferenceGroup) p); - else - setSummary(p, false); - if (p instanceof PreferenceScreen) - p.setOnPreferenceClickListener(this); - } - } - - private void setSummary(Preference pref, boolean init) { - if (pref instanceof EditTextPreference) { - EditTextPreference editPref = (EditTextPreference) pref; - pref.setSummary(editPref.getText()); - - if (editPref.getKey().equals("dns") - && editPref.getText().isEmpty()) { - pref.setSummary(getString(R.string.summary_dns_preference)); - } - if (editPref.getKey().equals("disk_size") - && editPref.getText().equals("0")) { - pref.setSummary(getString(R.string.summary_disk_size_preference)); - } - if (editPref.getKey().equals("user_password") && - editPref.getText().isEmpty()) { - editPref.setText(PrefStore.generatePassword()); - pref.setSummary(editPref.getText()); - } - } - - if (pref instanceof ListPreference) { - ListPreference listPref = (ListPreference) pref; - pref.setSummary(listPref.getEntry()); - - if (listPref.getKey().equals("distrib")) { - ListPreference suite = (ListPreference) findPreference("suite"); - ListPreference architecture = (ListPreference) findPreference("arch"); - EditTextPreference sourcepath = (EditTextPreference) findPreference("source_path"); - - String distributionStr = listPref.getValue(); - - // suite - int suiteValuesId = PrefStore.getResourceId(this, - distributionStr + "_suite_values", "array"); - if (suiteValuesId > 0) { - suite.setEntries(suiteValuesId); - suite.setEntryValues(suiteValuesId); - } - if (init) { - int suiteId = PrefStore.getResourceId(this, distributionStr - + "_suite", "string"); - if (suiteId > 0) { - String suiteStr = getString(suiteId); - if (suiteStr.length() > 0) - suite.setValue(suiteStr); - } - } - suite.setSummary(suite.getEntry()); - suite.setEnabled(true); - - // architecture - int architectureValuesId = PrefStore.getResourceId(this, - distributionStr + "_arch_values", "array"); - if (suiteValuesId > 0) { - architecture.setEntries(architectureValuesId); - architecture.setEntryValues(architectureValuesId); - } - if (init || architecture.getValue().length() == 0) { - int architectureId = PrefStore.getResourceId(this, - PrefStore.getArch() + "_" + distributionStr - + "_arch", "string"); - if (architectureId > 0) { - String architectureStr = getString(architectureId); - if (architectureStr.length() > 0) - architecture.setValue(architectureStr); - } - } - architecture.setSummary(architecture.getEntry()); - architecture.setEnabled(true); - - // source path - if (init || sourcepath.getText().length() == 0) { - int sourcepathId = PrefStore - .getResourceId(this, PrefStore.getArch() + "_" - + distributionStr + "_source_path", "string"); - if (sourcepathId > 0) { - sourcepath.setText(getString(sourcepathId)); - } - } - sourcepath.setSummary(sourcepath.getText()); - sourcepath.setEnabled(true); - - // RootFS - if (distributionStr.equals("rootfs")) { - // suite - suite.setEnabled(false); - // architecture - architecture.setEnabled(false); - // source path - if (init) { - String archiveFile = getString(R.string.rootfs_archive); - sourcepath.setText(archiveFile); - } - sourcepath.setSummary(sourcepath.getText()); - sourcepath.setEnabled(true); - } - } - if (listPref.getKey().equals("arch") && init) { - ListPreference distribution = (ListPreference) findPreference("distrib"); - EditTextPreference sourcepath = (EditTextPreference) findPreference("source_path"); - - String architectureStr = PrefStore.getArch(listPref.getValue()); - String distributionStr = distribution.getValue(); - - int sourcePathId = PrefStore.getResourceId(this, architectureStr - + "_" + distributionStr + "_source_path", "string"); - if (sourcePathId > 0) { - sourcepath.setText(getString(sourcePathId)); - } - - sourcepath.setSummary(sourcepath.getText()); - } - if (listPref.getKey().equals("target_type")) { - EditTextPreference targetpath = (EditTextPreference) findPreference("target_path"); - EditTextPreference disksize = (EditTextPreference) findPreference("disk_size"); - ListPreference fstype = (ListPreference) findPreference("fs_type"); - - switch (listPref.getValue()) { - case "file": - if (init) { - targetpath.setText(getString(R.string.target_path_file)); - } - disksize.setEnabled(true); - fstype.setEnabled(true); - break; - case "directory": - if (init) { - targetpath.setText(getString(R.string.target_path_directory)); - } - disksize.setEnabled(false); - fstype.setEnabled(false); - break; - case "partition": - if (init) { - targetpath.setText(getString(R.string.target_path_partition)); - } - disksize.setEnabled(false); - fstype.setEnabled(true); - break; - case "ram": - if (init) { - targetpath.setText(getString(R.string.target_path_ram)); - } - disksize.setEnabled(true); - fstype.setEnabled(false); - break; - case "custom": - if (init) { - targetpath.setText(getString(R.string.target_path_custom)); - } - disksize.setEnabled(false); - fstype.setEnabled(false); - break; - } - } - } - } } diff --git a/app/src/main/java/ru/meefik/linuxdeploy/activity/SettingsActivity.java b/app/src/main/java/ru/meefik/linuxdeploy/activity/SettingsActivity.java index 5cecc083..23dd2828 100644 --- a/app/src/main/java/ru/meefik/linuxdeploy/activity/SettingsActivity.java +++ b/app/src/main/java/ru/meefik/linuxdeploy/activity/SettingsActivity.java @@ -1,46 +1,28 @@ package ru.meefik.linuxdeploy.activity; -import android.Manifest; -import android.content.ComponentName; -import android.content.Context; -import android.content.SharedPreferences; -import android.content.SharedPreferences.OnSharedPreferenceChangeListener; -import android.content.pm.PackageManager; import android.os.Bundle; -import android.preference.CheckBoxPreference; -import android.preference.EditTextPreference; -import android.preference.ListPreference; -import android.preference.Preference; -import android.preference.PreferenceGroup; -import android.preference.PreferenceScreen; -import androidx.appcompat.app.AlertDialog; -import androidx.core.app.ActivityCompat; -import androidx.core.content.ContextCompat; +import androidx.appcompat.app.AppCompatActivity; -import ru.meefik.linuxdeploy.receiver.BootReceiver; -import ru.meefik.linuxdeploy.EnvUtils; import ru.meefik.linuxdeploy.PrefStore; import ru.meefik.linuxdeploy.R; -import ru.meefik.linuxdeploy.RemoveEnvTask; -import ru.meefik.linuxdeploy.UpdateEnvTask; +import ru.meefik.linuxdeploy.fragment.SettingsFragment; -public class SettingsActivity extends AppCompatPreferenceActivity implements - OnSharedPreferenceChangeListener, Preference.OnPreferenceClickListener { +public class SettingsActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); PrefStore.setLocale(this); + setContentView(R.layout.activity_preference); - getPreferenceManager().setSharedPreferencesName(PrefStore.getSettingsSharedName()); + getSupportFragmentManager() + .beginTransaction() + .replace(R.id.frame_layout, new SettingsFragment()) + .commit(); // Restore from conf file PrefStore.restoreSettings(this); - - addPreferencesFromResource(R.xml.settings); - - initSummaries(getPreferenceScreen()); } @Override @@ -53,165 +35,13 @@ public void onResume() { super.onResume(); setTitle(R.string.title_activity_settings); - getPreferenceScreen().getSharedPreferences() - .registerOnSharedPreferenceChangeListener(this); } @Override public void onPause() { super.onPause(); - getPreferenceScreen().getSharedPreferences() - .unregisterOnSharedPreferenceChangeListener(this); - // update configuration file PrefStore.dumpSettings(this); } - - @Override - public boolean onPreferenceClick(Preference preference) { - if (preference.getKey().equals("installenv")) { - updateEnvDialog(); - } - if (preference.getKey().equals("removeenv")) { - removeEnvDialog(); - } - return true; - } - - @Override - public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { - Preference pref = findPreference(key); - setSummary(pref, true); - switch (key) { - case "is_telnet": - // start/stop telnetd - EnvUtils.execService(getBaseContext(), "telnetd", null); - break; - case "telnet_port": - // restart telnetd - EnvUtils.execService(getBaseContext(), "telnetd", "restart"); - // restart httpd - EnvUtils.execService(getBaseContext(), "httpd", "restart"); - case "telnet_localhost": - // restart telnetd - EnvUtils.execService(getBaseContext(), "telnetd", "restart"); - break; - case "is_http": - // start/stop httpd - EnvUtils.execService(getBaseContext(), "httpd", null); - break; - case "http_port": - case "http_conf": - // restart httpd - EnvUtils.execService(getBaseContext(), "httpd", "restart"); - break; - case "autostart": - // set autostart settings - int autostartFlag = (PrefStore.isAutostart(this) ? - PackageManager.COMPONENT_ENABLED_STATE_ENABLED - : PackageManager.COMPONENT_ENABLED_STATE_DISABLED); - ComponentName bootComponent = new ComponentName(this, BootReceiver.class); - getPackageManager().setComponentEnabledSetting(bootComponent, autostartFlag, - PackageManager.DONT_KILL_APP); - break; - case "stealth": - // set stealth mode - // Run app without launcher: am start -n ru.meefik.linuxdeploy/.MainActivity - int stealthFlag = PrefStore.isStealth(this) ? - PackageManager.COMPONENT_ENABLED_STATE_DISABLED - : PackageManager.COMPONENT_ENABLED_STATE_ENABLED; - ComponentName mainComponent = new ComponentName(getPackageName(), getPackageName() + ".Launcher"); - getPackageManager().setComponentEnabledSetting(mainComponent, stealthFlag, - PackageManager.DONT_KILL_APP); - break; - } - } - - private void initSummaries(PreferenceGroup pg) { - for (int i = 0; i < pg.getPreferenceCount(); ++i) { - Preference p = pg.getPreference(i); - if (p instanceof PreferenceGroup) - initSummaries((PreferenceGroup) p); - else - setSummary(p, false); - if (p instanceof PreferenceScreen) - p.setOnPreferenceClickListener(this); - } - } - - private void setSummary(Preference pref, boolean init) { - if (pref instanceof EditTextPreference) { - EditTextPreference editPref = (EditTextPreference) pref; - pref.setSummary(editPref.getText()); - - if (editPref.getKey().equals("env_dir") && !init) { - editPref.setText(PrefStore.getEnvDir(this)); - pref.setSummary(editPref.getText()); - } - - if (editPref.getKey().equals("http_conf") && - editPref.getText().isEmpty()) { - editPref.setText(PrefStore.getHttpConf(this)); - pref.setSummary(editPref.getText()); - } - - if (editPref.getKey().equals("logfile") && !init) { - editPref.setText(PrefStore.getLogFile(this)); - pref.setSummary(editPref.getText()); - } - } - - if (pref instanceof ListPreference) { - ListPreference listPref = (ListPreference) pref; - pref.setSummary(listPref.getEntry()); - } - - if (pref instanceof CheckBoxPreference) { - CheckBoxPreference checkPref = (CheckBoxPreference) pref; - - if (checkPref.getKey().equals("logger") && checkPref.isChecked() && init) { - requestWritePermissions(); - } - } - } - - private void updateEnvDialog() { - final Context context = this; - new AlertDialog.Builder(this) - .setTitle(R.string.title_installenv_preference) - .setMessage(R.string.message_installenv_confirm_dialog) - .setIcon(android.R.drawable.ic_dialog_alert) - .setCancelable(false) - .setPositiveButton(android.R.string.yes, - (dialog, id) -> new UpdateEnvTask(context).execute()) - .setNegativeButton(android.R.string.no, - (dialog, id) -> dialog.cancel()).show(); - } - - private void removeEnvDialog() { - final Context context = this; - new AlertDialog.Builder(this) - .setTitle(R.string.title_removeenv_preference) - .setMessage(R.string.message_removeenv_confirm_dialog) - .setIcon(android.R.drawable.ic_dialog_alert) - .setCancelable(false) - .setPositiveButton(android.R.string.yes, - (dialog, id) -> new RemoveEnvTask(context).execute()) - .setNegativeButton(android.R.string.no, - (dialog, id) -> dialog.cancel()).show(); - } - - /** - * Request permission for write to storage - */ - private void requestWritePermissions() { - int REQUEST_WRITE_STORAGE = 112; - boolean hasPermission = (ContextCompat.checkSelfPermission(this, - Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED); - if (!hasPermission) { - ActivityCompat.requestPermissions(this, - new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_WRITE_STORAGE); - } - } } diff --git a/app/src/main/java/ru/meefik/linuxdeploy/fragment/PropertiesFragment.java b/app/src/main/java/ru/meefik/linuxdeploy/fragment/PropertiesFragment.java new file mode 100644 index 00000000..510b7210 --- /dev/null +++ b/app/src/main/java/ru/meefik/linuxdeploy/fragment/PropertiesFragment.java @@ -0,0 +1,305 @@ +package ru.meefik.linuxdeploy.fragment; + +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.SharedPreferences.OnSharedPreferenceChangeListener; +import android.os.Bundle; + +import androidx.preference.EditTextPreference; +import androidx.preference.ListPreference; +import androidx.preference.Preference; +import androidx.preference.PreferenceFragmentCompat; +import androidx.preference.PreferenceGroup; +import androidx.preference.PreferenceScreen; + +import ru.meefik.linuxdeploy.PrefStore; +import ru.meefik.linuxdeploy.R; +import ru.meefik.linuxdeploy.activity.PropertiesActivity; + +public class PropertiesFragment extends PreferenceFragmentCompat implements + Preference.OnPreferenceClickListener, OnSharedPreferenceChangeListener { + + @Override + public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { + getPreferenceManager().setSharedPreferencesName(PrefStore.getPropertiesSharedName()); + + Intent i = getActivity().getIntent(); + if (i != null) { + switch (i.getIntExtra("pref", 0)) { + case 1: + setPreferencesFromResource(R.xml.properties_ssh, rootKey); + break; + case 2: + setPreferencesFromResource(R.xml.properties_vnc, rootKey); + break; + case 3: + setPreferencesFromResource(R.xml.properties_x11, rootKey); + break; + case 4: + setPreferencesFromResource(R.xml.properties_fb, rootKey); + break; + case 5: + setPreferencesFromResource(R.xml.properties_run_parts, rootKey); + break; + case 6: + setPreferencesFromResource(R.xml.properties_sysv, rootKey); + break; + case 7: + setPreferencesFromResource(R.xml.properties_pulse, rootKey); + break; + default: + setPreferencesFromResource(R.xml.properties, rootKey); + } + } + + initSummaries(getPreferenceScreen()); + } + + @Override + public void onResume() { + super.onResume(); + getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this); + } + + @Override + public void onPause() { + super.onPause(); + getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this); + } + + @Override + public boolean onPreferenceClick(Preference preference) { + switch (preference.getKey()) { + case "ssh_properties": { + Intent intent = new Intent(getContext(), PropertiesActivity.class); + intent.putExtra("pref", 1); + startActivity(intent); + break; + } + case "gui_properties": { + Intent intent = new Intent(getContext(), PropertiesActivity.class); + + ListPreference graphics = findPreference("graphics"); + switch (graphics.getValue()) { + case "vnc": + intent.putExtra("pref", 2); + break; + case "x11": + intent.putExtra("pref", 3); + break; + case "fb": + intent.putExtra("pref", 4); + break; + } + + startActivity(intent); + break; + } + case "init_properties": { + Intent intent = new Intent(getContext(), PropertiesActivity.class); + + ListPreference init = findPreference("init"); + switch (init.getValue()) { + case "run-parts": + intent.putExtra("pref", 5); + break; + case "sysv": + intent.putExtra("pref", 6); + break; + } + + startActivity(intent); + break; + } + case "pulse_properties": { + Intent intent = new Intent(getContext(), PropertiesActivity.class); + intent.putExtra("pref", 7); + startActivity(intent); + break; + } + case "mounts_editor": { + Intent intent = new Intent(getContext(), PropertiesActivity.class); + startActivity(intent); + break; + } + } + + return true; + } + + @Override + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { + Preference pref = findPreference(key); + setSummary(pref, true); + } + + private void initSummaries(PreferenceGroup pg) { + for (int i = 0; i < pg.getPreferenceCount(); ++i) { + Preference p = pg.getPreference(i); + if (p instanceof PreferenceGroup) + initSummaries((PreferenceGroup) p); + else + setSummary(p, false); + if (p instanceof PreferenceScreen) + p.setOnPreferenceClickListener(this); + } + } + + private void setSummary(Preference pref, boolean init) { + if (pref instanceof EditTextPreference) { + EditTextPreference editPref = (EditTextPreference) pref; + pref.setSummary(editPref.getText()); + + if (editPref.getKey().equals("dns") + && editPref.getText().isEmpty()) { + pref.setSummary(getString(R.string.summary_dns_preference)); + } + if (editPref.getKey().equals("disk_size") + && editPref.getText().equals("0")) { + pref.setSummary(getString(R.string.summary_disk_size_preference)); + } + if (editPref.getKey().equals("user_password") && + editPref.getText().isEmpty()) { + editPref.setText(PrefStore.generatePassword()); + pref.setSummary(editPref.getText()); + } + } + + if (pref instanceof ListPreference) { + ListPreference listPref = (ListPreference) pref; + pref.setSummary(listPref.getEntry()); + + if (listPref.getKey().equals("distrib")) { + ListPreference suite = findPreference("suite"); + ListPreference architecture = findPreference("arch"); + EditTextPreference sourcepath = findPreference("source_path"); + + String distributionStr = listPref.getValue(); + + // suite + int suiteValuesId = PrefStore.getResourceId(getContext(), + distributionStr + "_suite_values", "array"); + if (suiteValuesId > 0) { + suite.setEntries(suiteValuesId); + suite.setEntryValues(suiteValuesId); + } + if (init) { + int suiteId = PrefStore.getResourceId(getContext(), distributionStr + + "_suite", "string"); + if (suiteId > 0) { + String suiteStr = getString(suiteId); + if (suiteStr.length() > 0) + suite.setValue(suiteStr); + } + } + suite.setSummary(suite.getEntry()); + suite.setEnabled(true); + + // architecture + int architectureValuesId = PrefStore.getResourceId(getContext(), + distributionStr + "_arch_values", "array"); + if (suiteValuesId > 0) { + architecture.setEntries(architectureValuesId); + architecture.setEntryValues(architectureValuesId); + } + if (init || architecture.getValue().length() == 0) { + int architectureId = PrefStore.getResourceId(getContext(), + PrefStore.getArch() + "_" + distributionStr + + "_arch", "string"); + if (architectureId > 0) { + String architectureStr = getString(architectureId); + if (architectureStr.length() > 0) + architecture.setValue(architectureStr); + } + } + architecture.setSummary(architecture.getEntry()); + architecture.setEnabled(true); + + // source path + if (init || sourcepath.getText().length() == 0) { + int sourcepathId = PrefStore + .getResourceId(getContext(), PrefStore.getArch() + "_" + + distributionStr + "_source_path", "string"); + if (sourcepathId > 0) { + sourcepath.setText(getString(sourcepathId)); + } + } + sourcepath.setSummary(sourcepath.getText()); + sourcepath.setEnabled(true); + + // RootFS + if (distributionStr.equals("rootfs")) { + // suite + suite.setEnabled(false); + // architecture + architecture.setEnabled(false); + // source path + if (init) { + String archiveFile = getString(R.string.rootfs_archive); + sourcepath.setText(archiveFile); + } + sourcepath.setSummary(sourcepath.getText()); + sourcepath.setEnabled(true); + } + } + if (listPref.getKey().equals("arch") && init) { + ListPreference distribution = findPreference("distrib"); + EditTextPreference sourcepath = findPreference("source_path"); + + String architectureStr = PrefStore.getArch(listPref.getValue()); + String distributionStr = distribution.getValue(); + + int sourcePathId = PrefStore.getResourceId(getContext(), architectureStr + + "_" + distributionStr + "_source_path", "string"); + if (sourcePathId > 0) { + sourcepath.setText(getString(sourcePathId)); + } + + sourcepath.setSummary(sourcepath.getText()); + } + if (listPref.getKey().equals("target_type")) { + EditTextPreference targetpath = findPreference("target_path"); + EditTextPreference disksize = findPreference("disk_size"); + ListPreference fstype = findPreference("fs_type"); + + switch (listPref.getValue()) { + case "file": + if (init) { + targetpath.setText(getString(R.string.target_path_file)); + } + disksize.setEnabled(true); + fstype.setEnabled(true); + break; + case "directory": + if (init) { + targetpath.setText(getString(R.string.target_path_directory)); + } + disksize.setEnabled(false); + fstype.setEnabled(false); + break; + case "partition": + if (init) { + targetpath.setText(getString(R.string.target_path_partition)); + } + disksize.setEnabled(false); + fstype.setEnabled(true); + break; + case "ram": + if (init) { + targetpath.setText(getString(R.string.target_path_ram)); + } + disksize.setEnabled(true); + fstype.setEnabled(false); + break; + case "custom": + if (init) { + targetpath.setText(getString(R.string.target_path_custom)); + } + disksize.setEnabled(false); + fstype.setEnabled(false); + break; + } + } + } + } +} diff --git a/app/src/main/java/ru/meefik/linuxdeploy/fragment/SettingsFragment.java b/app/src/main/java/ru/meefik/linuxdeploy/fragment/SettingsFragment.java new file mode 100644 index 00000000..a0d58ca4 --- /dev/null +++ b/app/src/main/java/ru/meefik/linuxdeploy/fragment/SettingsFragment.java @@ -0,0 +1,210 @@ +package ru.meefik.linuxdeploy.fragment; + +import android.Manifest; +import android.content.ComponentName; +import android.content.Context; +import android.content.SharedPreferences; +import android.content.SharedPreferences.OnSharedPreferenceChangeListener; +import android.content.pm.PackageManager; +import android.os.Bundle; + +import androidx.appcompat.app.AlertDialog; +import androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; +import androidx.preference.CheckBoxPreference; +import androidx.preference.EditTextPreference; +import androidx.preference.ListPreference; +import androidx.preference.Preference; +import androidx.preference.PreferenceFragmentCompat; +import androidx.preference.PreferenceGroup; +import androidx.preference.PreferenceScreen; + +import ru.meefik.linuxdeploy.EnvUtils; +import ru.meefik.linuxdeploy.PrefStore; +import ru.meefik.linuxdeploy.R; +import ru.meefik.linuxdeploy.RemoveEnvTask; +import ru.meefik.linuxdeploy.UpdateEnvTask; +import ru.meefik.linuxdeploy.receiver.BootReceiver; + +public class SettingsFragment extends PreferenceFragmentCompat implements + OnSharedPreferenceChangeListener, Preference.OnPreferenceClickListener { + + @Override + public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { + getPreferenceManager().setSharedPreferencesName(PrefStore.getSettingsSharedName()); + setPreferencesFromResource(R.xml.settings, rootKey); + initSummaries(getPreferenceScreen()); + } + + @Override + public void onResume() { + super.onResume(); + + getPreferenceScreen().getSharedPreferences() + .registerOnSharedPreferenceChangeListener(this); + } + + @Override + public void onPause() { + super.onPause(); + + getPreferenceScreen().getSharedPreferences() + .unregisterOnSharedPreferenceChangeListener(this); + } + + @Override + public boolean onPreferenceClick(Preference preference) { + switch (preference.getKey()) { + case "installenv": + updateEnvDialog(); + return true; + case "removeenv": + removeEnvDialog(); + return true; + default: + return false; + } + } + + @Override + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { + Preference pref = findPreference(key); + setSummary(pref, true); + switch (key) { + case "is_telnet": + // start/stop telnetd + EnvUtils.execService(getContext(), "telnetd", null); + break; + case "telnet_port": + // restart telnetd + EnvUtils.execService(getContext(), "telnetd", "restart"); + // restart httpd + EnvUtils.execService(getContext(), "httpd", "restart"); + break; + case "telnet_localhost": + // restart telnetd + EnvUtils.execService(getContext(), "telnetd", "restart"); + break; + case "is_http": + // start/stop httpd + EnvUtils.execService(getContext(), "httpd", null); + break; + case "http_port": + case "http_conf": + // restart httpd + EnvUtils.execService(getContext(), "httpd", "restart"); + break; + case "autostart": + // set autostart settings + int autostartFlag = (PrefStore.isAutostart(getContext()) ? + PackageManager.COMPONENT_ENABLED_STATE_ENABLED + : PackageManager.COMPONENT_ENABLED_STATE_DISABLED); + ComponentName bootComponent = new ComponentName(getContext(), BootReceiver.class); + getContext().getPackageManager().setComponentEnabledSetting(bootComponent, autostartFlag, + PackageManager.DONT_KILL_APP); + break; + case "stealth": + // set stealth mode + // Run app without launcher: am start -n ru.meefik.linuxdeploy/.MainActivity + int stealthFlag = PrefStore.isStealth(getContext()) ? + PackageManager.COMPONENT_ENABLED_STATE_DISABLED + : PackageManager.COMPONENT_ENABLED_STATE_ENABLED; + ComponentName mainComponent = new ComponentName(getContext().getPackageName(), getContext().getPackageName() + ".Launcher"); + getContext().getPackageManager().setComponentEnabledSetting(mainComponent, stealthFlag, + PackageManager.DONT_KILL_APP); + break; + } + } + + private void initSummaries(PreferenceGroup pg) { + for (int i = 0; i < pg.getPreferenceCount(); ++i) { + Preference p = pg.getPreference(i); + if (p instanceof PreferenceGroup) + initSummaries((PreferenceGroup) p); + else + setSummary(p, false); + if (p instanceof PreferenceScreen) + p.setOnPreferenceClickListener(this); + } + } + + private void setSummary(Preference pref, boolean init) { + if (pref instanceof EditTextPreference) { + EditTextPreference editPref = (EditTextPreference) pref; + pref.setSummary(editPref.getText()); + + switch (editPref.getKey()) { + case "env_dir": + if (!init) { + editPref.setText(PrefStore.getEnvDir(getContext())); + pref.setSummary(editPref.getText()); + } + break; + case "http_conf": + if (editPref.getText().isEmpty()) { + editPref.setText(PrefStore.getHttpConf(getContext())); + pref.setSummary(editPref.getText()); + } + break; + case "logfile": + if (!init) { + editPref.setText(PrefStore.getLogFile(getContext())); + pref.setSummary(editPref.getText()); + } + break; + } + } + + if (pref instanceof ListPreference) { + ListPreference listPref = (ListPreference) pref; + pref.setSummary(listPref.getEntry()); + } + + if (pref instanceof CheckBoxPreference) { + CheckBoxPreference checkPref = (CheckBoxPreference) pref; + + if (checkPref.getKey().equals("logger") && checkPref.isChecked() && init) { + requestWritePermissions(); + } + } + } + + private void updateEnvDialog() { + final Context context = getContext(); + new AlertDialog.Builder(getContext()) + .setTitle(R.string.title_installenv_preference) + .setMessage(R.string.message_installenv_confirm_dialog) + .setIcon(android.R.drawable.ic_dialog_alert) + .setCancelable(false) + .setPositiveButton(android.R.string.yes, + (dialog, id) -> new UpdateEnvTask(context).execute()) + .setNegativeButton(android.R.string.no, + (dialog, id) -> dialog.cancel()).show(); + } + + private void removeEnvDialog() { + final Context context = getContext(); + new AlertDialog.Builder(getContext()) + .setTitle(R.string.title_removeenv_preference) + .setMessage(R.string.message_removeenv_confirm_dialog) + .setIcon(android.R.drawable.ic_dialog_alert) + .setCancelable(false) + .setPositiveButton(android.R.string.yes, + (dialog, id) -> new RemoveEnvTask(context).execute()) + .setNegativeButton(android.R.string.no, + (dialog, id) -> dialog.cancel()).show(); + } + + /** + * Request permission for write to storage + */ + private void requestWritePermissions() { + int REQUEST_WRITE_STORAGE = 112; + boolean hasPermission = (ContextCompat.checkSelfPermission(getContext(), + Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED); + if (!hasPermission) { + ActivityCompat.requestPermissions(getActivity(), + new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_WRITE_STORAGE); + } + } +} From 3d8d0889e06ba19681f4b7f829246019590e5a7d Mon Sep 17 00:00:00 2001 From: Iscle Date: Mon, 13 Jan 2020 01:02:25 +0100 Subject: [PATCH 05/12] Add androidx preference dependency (missed on last commit!) --- app/build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/app/build.gradle b/app/build.gradle index 34230e8e..5b5a4428 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -34,4 +34,5 @@ dependencies { implementation 'androidx.browser:browser:1.2.0' implementation 'androidx.constraintlayout:constraintlayout:1.1.3' implementation 'com.squareup.okhttp3:okhttp:4.3.1' + implementation 'androidx.preference:preference:1.1.0' } From 016d5579215956eea9081f37b70be9f32f8618f5 Mon Sep 17 00:00:00 2001 From: Iscle Date: Mon, 13 Jan 2020 01:04:40 +0100 Subject: [PATCH 06/12] Add activity_preference.xml (missed on last commit!) --- app/src/main/res/layout/activity_preference.xml | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 app/src/main/res/layout/activity_preference.xml diff --git a/app/src/main/res/layout/activity_preference.xml b/app/src/main/res/layout/activity_preference.xml new file mode 100644 index 00000000..76a157b1 --- /dev/null +++ b/app/src/main/res/layout/activity_preference.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file From a21896ae881552a53a8a9d1287b8145d2c6ecf1a Mon Sep 17 00:00:00 2001 From: Iscle Date: Mon, 13 Jan 2020 03:29:20 +0100 Subject: [PATCH 07/12] Fixed wrong class for Mounts --- .../ru/meefik/linuxdeploy/fragment/PropertiesFragment.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/ru/meefik/linuxdeploy/fragment/PropertiesFragment.java b/app/src/main/java/ru/meefik/linuxdeploy/fragment/PropertiesFragment.java index 510b7210..508b30d9 100644 --- a/app/src/main/java/ru/meefik/linuxdeploy/fragment/PropertiesFragment.java +++ b/app/src/main/java/ru/meefik/linuxdeploy/fragment/PropertiesFragment.java @@ -14,6 +14,7 @@ import ru.meefik.linuxdeploy.PrefStore; import ru.meefik.linuxdeploy.R; +import ru.meefik.linuxdeploy.activity.MountsActivity; import ru.meefik.linuxdeploy.activity.PropertiesActivity; public class PropertiesFragment extends PreferenceFragmentCompat implements @@ -118,7 +119,7 @@ public boolean onPreferenceClick(Preference preference) { break; } case "mounts_editor": { - Intent intent = new Intent(getContext(), PropertiesActivity.class); + Intent intent = new Intent(getContext(), MountsActivity.class); startActivity(intent); break; } From 09c022fbcc9e2d2ccee35e6689e6834c9bf4a13a Mon Sep 17 00:00:00 2001 From: Iscle Date: Tue, 14 Jan 2020 16:49:39 +0100 Subject: [PATCH 08/12] Improve Mounts activity Still more improvements are in the way, this is just to get started :) --- .../java/ru/meefik/linuxdeploy/EnvUtils.java | 4 +- .../java/ru/meefik/linuxdeploy/PrefStore.java | 39 ++-- .../linuxdeploy/activity/AboutActivity.java | 2 +- .../linuxdeploy/activity/MainActivity.java | 4 +- .../linuxdeploy/activity/MountsActivity.java | 188 +++++++----------- .../linuxdeploy/adapter/MountAdapter.java | 120 +++++++++++ .../ru/meefik/linuxdeploy/model/Mount.java | 30 +++ .../res/drawable/ic_warning_white_24dp.xml | 9 + app/src/main/res/layout/activity_mounts.xml | 17 +- app/src/main/res/layout/mounts_row.xml | 18 +- app/src/main/res/layout/properties_mounts.xml | 8 +- app/src/main/res/values/strings.xml | 6 +- 12 files changed, 272 insertions(+), 173 deletions(-) create mode 100644 app/src/main/java/ru/meefik/linuxdeploy/adapter/MountAdapter.java create mode 100644 app/src/main/java/ru/meefik/linuxdeploy/model/Mount.java create mode 100644 app/src/main/res/drawable/ic_warning_white_24dp.xml diff --git a/app/src/main/java/ru/meefik/linuxdeploy/EnvUtils.java b/app/src/main/java/ru/meefik/linuxdeploy/EnvUtils.java index 8eea994f..6c2b04da 100644 --- a/app/src/main/java/ru/meefik/linuxdeploy/EnvUtils.java +++ b/app/src/main/java/ru/meefik/linuxdeploy/EnvUtils.java @@ -201,7 +201,7 @@ private static boolean setVersion(Context c) { BufferedWriter bw = null; try { bw = new BufferedWriter(new FileWriter(f)); - bw.write(PrefStore.getVersion(c)); + bw.write(PrefStore.getVersion()); result = true; } catch (IOException e) { e.printStackTrace(); @@ -225,7 +225,7 @@ public static boolean isLatestVersion(Context c) { try { br = new BufferedReader(new FileReader(f)); String line = br.readLine(); - if (PrefStore.getVersion(c).equals(line)) result = true; + if (PrefStore.getVersion().equals(line)) result = true; } catch (IOException e) { e.printStackTrace(); } finally { diff --git a/app/src/main/java/ru/meefik/linuxdeploy/PrefStore.java b/app/src/main/java/ru/meefik/linuxdeploy/PrefStore.java index 2353cfc6..3b1e2839 100644 --- a/app/src/main/java/ru/meefik/linuxdeploy/PrefStore.java +++ b/app/src/main/java/ru/meefik/linuxdeploy/PrefStore.java @@ -38,10 +38,9 @@ public class PrefStore { /** * Get application version * - * @param c context * @return version, format versionName-versionCode */ - public static String getVersion(Context c) { + public static String getVersion() { return BuildConfig.VERSION_NAME + "-" + BuildConfig.VERSION_CODE; } @@ -691,14 +690,12 @@ public static String getArch() { * @param c context * @return screen width */ - static Integer getScreenWidth(Context c) { - int width; + static int getScreenWidth(Context c) { WindowManager wm = (WindowManager) c.getSystemService(Context.WINDOW_SERVICE); Display display = wm.getDefaultDisplay(); Point size = new Point(); display.getSize(size); - width = size.x; - return width; + return size.x; } /** @@ -707,14 +704,12 @@ static Integer getScreenWidth(Context c) { * @param c context * @return screen height */ - static Integer getScreenHeight(Context c) { - int height; + static int getScreenHeight(Context c) { WindowManager wm = (WindowManager) c.getSystemService(Context.WINDOW_SERVICE); Display display = wm.getDefaultDisplay(); Point size = new Point(); display.getSize(size); - height = size.y; - return height; + return size.y; } /** @@ -765,11 +760,11 @@ public static int getResourceId(Context c, String resourceName, String resourceT * @param intent intent */ public static void showNotification(Context context, Intent intent) { - NotificationManager mNotificationManager = (NotificationManager) context + NotificationManager notificationManager = (NotificationManager) context .getSystemService(Context.NOTIFICATION_SERVICE); if (isNotification(context)) { setLocale(context); - NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context, SERVICE_CHANNEL_ID) + NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context, SERVICE_CHANNEL_ID) .setSmallIcon(R.mipmap.ic_launcher) .setContentTitle(context.getString(R.string.app_name)) .setContentText(context.getString(R.string.notification_current_profile) @@ -780,7 +775,7 @@ public static void showNotification(Context context, Intent intent) { stealthReceive.setAction("ru.meefik.linuxdeploy.BROADCAST_ACTION"); stealthReceive.putExtra("show", true); PendingIntent pendingIntentStealth = PendingIntent.getBroadcast(context, 2, stealthReceive, PendingIntent.FLAG_UPDATE_CURRENT); - mBuilder.setContentIntent(pendingIntentStealth); + notificationBuilder.setContentIntent(pendingIntentStealth); } else { Intent resultIntent = intent; if (resultIntent == null) resultIntent = new Intent(context, MainActivity.class); @@ -788,27 +783,27 @@ public static void showNotification(Context context, Intent intent) { stackBuilder.addParentStack(MainActivity.class); stackBuilder.addNextIntent(resultIntent); PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(1, PendingIntent.FLAG_UPDATE_CURRENT); - mBuilder.setContentIntent(resultPendingIntent); + notificationBuilder.setContentIntent(resultPendingIntent); Intent startReceive = new Intent(); startReceive.setAction("ru.meefik.linuxdeploy.BROADCAST_ACTION"); startReceive.putExtra("start", true); PendingIntent pendingIntentStart = PendingIntent.getBroadcast(context, 3, startReceive, PendingIntent.FLAG_UPDATE_CURRENT); int startIcon = SETTINGS.get(context, "theme").equals("dark") ? R.drawable.ic_action_start_dark : R.drawable.ic_action_start_light; - mBuilder.addAction(startIcon, context.getString(R.string.menu_start), pendingIntentStart); + notificationBuilder.addAction(startIcon, context.getString(R.string.menu_start), pendingIntentStart); Intent stopReceive = new Intent(); stopReceive.setAction("ru.meefik.linuxdeploy.BROADCAST_ACTION"); stopReceive.putExtra("stop", true); PendingIntent pendingIntentStop = PendingIntent.getBroadcast(context, 4, stopReceive, PendingIntent.FLAG_UPDATE_CURRENT); int stopIcon = SETTINGS.get(context, "theme").equals("dark") ? R.drawable.ic_action_stop_dark : R.drawable.ic_action_stop_light; - mBuilder.addAction(stopIcon, context.getString(R.string.menu_stop), pendingIntentStop); + notificationBuilder.addAction(stopIcon, context.getString(R.string.menu_stop), pendingIntentStop); } - mBuilder.setOngoing(true); - mBuilder.setWhen(0); - mNotificationManager.notify(NOTIFY_ID, mBuilder.build()); + notificationBuilder.setOngoing(true); + notificationBuilder.setWhen(0); + notificationManager.notify(NOTIFY_ID, notificationBuilder.build()); } else { - mNotificationManager.cancel(NOTIFY_ID); + notificationManager.cancel(NOTIFY_ID); } } @@ -818,8 +813,8 @@ public static void showNotification(Context context, Intent intent) { * @param context context */ public static void hideNotification(Context context) { - NotificationManager mNotificationManager = (NotificationManager) context + NotificationManager notificationManager = (NotificationManager) context .getSystemService(Context.NOTIFICATION_SERVICE); - mNotificationManager.cancel(NOTIFY_ID); + notificationManager.cancel(NOTIFY_ID); } } diff --git a/app/src/main/java/ru/meefik/linuxdeploy/activity/AboutActivity.java b/app/src/main/java/ru/meefik/linuxdeploy/activity/AboutActivity.java index d934d804..c5c1395f 100644 --- a/app/src/main/java/ru/meefik/linuxdeploy/activity/AboutActivity.java +++ b/app/src/main/java/ru/meefik/linuxdeploy/activity/AboutActivity.java @@ -19,7 +19,7 @@ public void onCreate(Bundle savedInstanceState) { TextView atv = findViewById(R.id.aboutTextView); atv.setMovementMethod(LinkMovementMethod.getInstance()); TextView vtv = findViewById(R.id.versionView); - vtv.setText(getString(R.string.app_version, PrefStore.getVersion(this))); + vtv.setText(getString(R.string.app_version, PrefStore.getVersion())); } @Override diff --git a/app/src/main/java/ru/meefik/linuxdeploy/activity/MainActivity.java b/app/src/main/java/ru/meefik/linuxdeploy/activity/MainActivity.java index 727f0e91..8e6bb1fa 100644 --- a/app/src/main/java/ru/meefik/linuxdeploy/activity/MainActivity.java +++ b/app/src/main/java/ru/meefik/linuxdeploy/activity/MainActivity.java @@ -213,7 +213,8 @@ public boolean onOptionsItemSelected(MenuItem item) { default: return super.onOptionsItemSelected(item); } - return false; + + return true; } @Override @@ -266,6 +267,7 @@ public boolean onNavigationItemSelected(MenuItem item) { finish(); break; } + DrawerLayout drawer = findViewById(R.id.drawer_layout); drawer.closeDrawer(GravityCompat.START); return true; diff --git a/app/src/main/java/ru/meefik/linuxdeploy/activity/MountsActivity.java b/app/src/main/java/ru/meefik/linuxdeploy/activity/MountsActivity.java index c9b6ac2b..d0a9e6b0 100644 --- a/app/src/main/java/ru/meefik/linuxdeploy/activity/MountsActivity.java +++ b/app/src/main/java/ru/meefik/linuxdeploy/activity/MountsActivity.java @@ -1,118 +1,90 @@ package ru.meefik.linuxdeploy.activity; -import android.content.DialogInterface; import android.os.Bundle; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; -import android.view.ViewGroup; -import android.widget.AdapterView; -import android.widget.ArrayAdapter; -import android.widget.Button; import android.widget.EditText; -import android.widget.ListView; -import android.widget.TextView; - -import java.util.ArrayList; -import java.util.List; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; +import androidx.recyclerview.widget.DividerItemDecoration; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; import ru.meefik.linuxdeploy.PrefStore; import ru.meefik.linuxdeploy.R; +import ru.meefik.linuxdeploy.adapter.MountAdapter; +import ru.meefik.linuxdeploy.model.Mount; public class MountsActivity extends AppCompatActivity { - private List listItems = new ArrayList<>(); - private ArrayAdapter adapter; + private MountAdapter adapter; private void addDialog() { - LayoutInflater layoutInflater = LayoutInflater.from(this); - View view = layoutInflater.inflate(R.layout.properties_mounts, null); - final EditText inputSrc = view.findViewById(R.id.editTextSrc); - final EditText inputTarget = view.findViewById(R.id.editTextTarget); + View view = LayoutInflater.from(this).inflate(R.layout.properties_mounts, null); + EditText inputSrc = view.findViewById(R.id.editTextSrc); + EditText inputTarget = view.findViewById(R.id.editTextTarget); + new AlertDialog.Builder(this) .setTitle(R.string.new_mount_title) .setView(view) .setPositiveButton(android.R.string.ok, (dialog, whichButton) -> { - String text = ""; String src = inputSrc.getText().toString() .replaceAll("[ :]", "_"); String target = inputTarget.getText().toString() .replaceAll("[ :]", "_"); - if (src.length() > 0) { - text = src; - if (target.length() > 0) { - text = text + ":" + target; - } - } - if (text.length() > 0) { - listItems.add(text); - adapter.notifyDataSetChanged(); + if (!src.isEmpty()) { + adapter.addMount(new Mount(src, target)); } - }).setNegativeButton(android.R.string.cancel, - (dialog, whichButton) -> dialog.cancel()).show(); + }) + .setNegativeButton(android.R.string.cancel, + (dialog, whichButton) -> dialog.cancel()).show(); } - private void editDialog(final int position) { - LayoutInflater layoutInflater = LayoutInflater.from(this); - View view = layoutInflater.inflate(R.layout.properties_mounts, null); - final EditText inputSrc = view.findViewById(R.id.editTextSrc); - final EditText inputTarget = view.findViewById(R.id.editTextTarget); - if (position >= 0 && position < listItems.size()) { - String text = listItems.get(position); - final String[] arr = text.split(":", 2); - try { - inputSrc.setText(arr[0]); - inputSrc.setSelection(arr[0].length()); - - inputTarget.setText(arr[1]); - inputTarget.setSelection(arr[1].length()); - } catch (IndexOutOfBoundsException ignored) { - } - - new AlertDialog.Builder(this) - .setTitle(R.string.edit_mount_title) - .setView(view) - .setPositiveButton(android.R.string.ok, - (dialog, whichButton) -> { - String text1 = ""; - String src = inputSrc.getText().toString() - .replaceAll("[ :]", "_"); - String target = inputTarget.getText().toString() - .replaceAll("[ :]", "_"); - if (src.length() > 0) { - text1 = src; - if (target.length() > 0) { - text1 = text1 + ":" + target; - } - } - if (text1.length() > 0) { - listItems.set(position, text1); - adapter.notifyDataSetChanged(); - } - }).setNegativeButton(android.R.string.cancel, - (dialog, whichButton) -> dialog.cancel()).show(); - } - } + private void editDialog(Mount mount) { + View view = LayoutInflater.from(this).inflate(R.layout.properties_mounts, null); + EditText inputSrc = view.findViewById(R.id.editTextSrc); + EditText inputTarget = view.findViewById(R.id.editTextTarget); - private void deleteDialog(final int position) { - if (position >= 0 && position < listItems.size()) { - new AlertDialog.Builder(this) - .setTitle(R.string.confirm_mount_discard_title) - .setMessage(R.string.confirm_mount_discard_message) - .setIcon(android.R.drawable.ic_dialog_alert) - .setCancelable(false) - .setPositiveButton(android.R.string.yes, - (dialog, whichButton) -> { - listItems.remove(position); + inputSrc.setText(mount.getSource()); + inputSrc.setSelection(mount.getSource().length()); + + inputTarget.setText(mount.getTarget()); + inputTarget.setSelection(mount.getTarget().length()); + + new AlertDialog.Builder(this) + .setTitle(R.string.edit_mount_title) + .setView(view) + .setPositiveButton(android.R.string.ok, + (dialog, whichButton) -> { + String src = inputSrc.getText().toString() + .replaceAll("[ :]", "_"); + String target = inputTarget.getText().toString() + .replaceAll("[ :]", "_"); + if (!src.isEmpty()) { + mount.setSource(src); + mount.setTarget(target); adapter.notifyDataSetChanged(); - }).setNegativeButton(android.R.string.no, - (dialog, whichButton) -> dialog.cancel()).show(); - } + } + }) + .setNegativeButton(android.R.string.cancel, + (dialog, whichButton) -> dialog.cancel()) + .show(); + } + + private void deleteDialog(Mount mount) { + new AlertDialog.Builder(this) + .setTitle(R.string.confirm_mount_discard_title) + .setMessage(R.string.confirm_mount_discard_message) + .setIcon(R.drawable.ic_warning_white_24dp) + .setPositiveButton(android.R.string.yes, + (dialog, whichButton) -> adapter.removeMount(mount)) + .setNegativeButton(android.R.string.no, + (dialog, whichButton) -> dialog.cancel()) + .show(); } @Override @@ -121,37 +93,15 @@ protected void onCreate(Bundle savedInstanceState) { PrefStore.setLocale(this); setContentView(R.layout.activity_mounts); - // ListView Adapter - ListView listView = findViewById(R.id.mountsView); - adapter = new ArrayAdapter(this, R.layout.mounts_row, R.id.mount_point, listItems) { - @Override - public View getView(final int position, View convertView, final ViewGroup parent) { - View view = super.getView(position, convertView, parent); - TextView tv = view.findViewById(R.id.mount_point); - Button btn = view.findViewById(R.id.delete_mount); - - String item = getItem(position); - tv.setText(item); - - tv.setOnClickListener(v -> { - ((ListView) parent).performItemClick(v, position, 0); // Let the event be handled in onItemClick() - }); - - btn.setOnClickListener(v -> { - ((ListView) parent).performItemClick(v, position, 0); // Let the event be handled in onItemClick() - }); - - return view; - } - }; - listView.setAdapter(adapter); - - // Click listener - listView.setOnItemClickListener((parent, view, position, id) -> { - long viewId = view.getId(); - if (viewId == R.id.delete_mount) deleteDialog(position); - else editDialog(position); - }); + // RecyclerView Adapter + RecyclerView recyclerView = findViewById(R.id.recycler_view); + adapter = new MountAdapter(); + adapter.setOnItemClickListener(this::editDialog); + adapter.setOnItemDeleteListener(this::deleteDialog); + + recyclerView.setAdapter(adapter); + recyclerView.setLayoutManager(new LinearLayoutManager(this)); + recyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL)); } @Override @@ -168,11 +118,11 @@ public boolean onCreateOptionsMenu(Menu menu) { @Override public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case R.id.menu_add: - addDialog(); - break; + if (item.getItemId() == R.id.menu_add) { + addDialog(); + return true; } + return false; } @@ -184,13 +134,13 @@ public void onResume() { + PrefStore.getProfileName(this); setTitle(titleMsg); - listItems.addAll(PrefStore.getMountsList(this)); + adapter.setMounts(PrefStore.getMountsList(this)); } @Override public void onPause() { super.onPause(); - PrefStore.setMountsList(this, listItems); + PrefStore.setMountsList(this, adapter.getMounts()); } } diff --git a/app/src/main/java/ru/meefik/linuxdeploy/adapter/MountAdapter.java b/app/src/main/java/ru/meefik/linuxdeploy/adapter/MountAdapter.java new file mode 100644 index 00000000..2a256477 --- /dev/null +++ b/app/src/main/java/ru/meefik/linuxdeploy/adapter/MountAdapter.java @@ -0,0 +1,120 @@ +package ru.meefik.linuxdeploy.adapter; + +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import java.util.ArrayList; +import java.util.List; + +import ru.meefik.linuxdeploy.R; +import ru.meefik.linuxdeploy.model.Mount; + +public class MountAdapter extends RecyclerView.Adapter { + + private List mounts; + private OnItemClickListener clickListener; + private OnItemDeleteListener deleteListener; + + public MountAdapter() { + this.mounts = new ArrayList<>(); + } + + @NonNull + @Override + public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.mounts_row, parent, false); + return new ViewHolder(view); + } + + @Override + public void onBindViewHolder(@NonNull ViewHolder holder, int position) { + holder.setMount(mounts.get(position)); + } + + @Override + public int getItemCount() { + return mounts == null ? 0 : mounts.size(); + } + + public void addMount(Mount mount) { + mounts.add(mount); + notifyDataSetChanged(); + } + + public void removeMount(Mount mount) { + mounts.remove(mount); + notifyDataSetChanged(); + } + + public void setMounts(List mounts) { + this.mounts.clear(); + for (String mount : mounts) { + String[] tmp = mount.split(":", 2); + this.mounts.add(new Mount(tmp[0], tmp[1])); + } + notifyDataSetChanged(); + } + + public List getMounts() { + List mounts = new ArrayList<>(); + for (Mount mount : this.mounts) { + mounts.add(mount.getSource() + ":" + mount.getTarget()); + } + return mounts; + } + + public void setOnItemClickListener(OnItemClickListener clickListener) { + this.clickListener = clickListener; + } + + public void setOnItemDeleteListener(OnItemDeleteListener deleteListener) { + this.deleteListener = deleteListener; + } + + public interface OnItemClickListener { + void onItemClick(Mount mount); + } + + public interface OnItemDeleteListener { + void onItemDelete(Mount mount); + } + + class ViewHolder extends RecyclerView.ViewHolder { + + private View view; + private TextView mountPoint; + private ImageView delete; + + ViewHolder(@NonNull View itemView) { + super(itemView); + + view = itemView; + mountPoint = itemView.findViewById(R.id.mount_point); + delete = itemView.findViewById(R.id.delete_mount); + } + + void setMount(Mount mount) { + if (mount.getTarget().isEmpty()) { + mountPoint.setText(mount.getSource()); + } else { + mountPoint.setText(mount.getSource() + " - " + mount.getTarget()); + } + + view.setOnClickListener(v -> { + if (clickListener != null) + clickListener.onItemClick(mount); + }); + + delete.setOnClickListener(v -> { + if (deleteListener != null) + deleteListener.onItemDelete(mount); + }); + } + } +} diff --git a/app/src/main/java/ru/meefik/linuxdeploy/model/Mount.java b/app/src/main/java/ru/meefik/linuxdeploy/model/Mount.java new file mode 100644 index 00000000..763f2639 --- /dev/null +++ b/app/src/main/java/ru/meefik/linuxdeploy/model/Mount.java @@ -0,0 +1,30 @@ +package ru.meefik.linuxdeploy.model; + +public class Mount { + private String source; + private String target; + + public Mount() { + } + + public Mount(String source, String target) { + this.source = source; + this.target = target; + } + + public String getSource() { + return source; + } + + public void setSource(String source) { + this.source = source; + } + + public String getTarget() { + return target; + } + + public void setTarget(String target) { + this.target = target; + } +} diff --git a/app/src/main/res/drawable/ic_warning_white_24dp.xml b/app/src/main/res/drawable/ic_warning_white_24dp.xml new file mode 100644 index 00000000..7c69ee84 --- /dev/null +++ b/app/src/main/res/drawable/ic_warning_white_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/layout/activity_mounts.xml b/app/src/main/res/layout/activity_mounts.xml index debac9f1..c4c4d43c 100644 --- a/app/src/main/res/layout/activity_mounts.xml +++ b/app/src/main/res/layout/activity_mounts.xml @@ -1,17 +1,6 @@ - - - - - + tools:context=".activity.MountsActivity" /> diff --git a/app/src/main/res/layout/mounts_row.xml b/app/src/main/res/layout/mounts_row.xml index 07d47682..eaf0f792 100644 --- a/app/src/main/res/layout/mounts_row.xml +++ b/app/src/main/res/layout/mounts_row.xml @@ -1,10 +1,14 @@ @@ -17,15 +21,15 @@ android:paddingRight="4dp" android:textSize="18sp" /> -