Loading app/src/main/java/net/fabiszewski/ulogger/MainActivity.java +8 −0 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ import androidx.appcompat.widget.Toolbar; import androidx.core.text.HtmlCompat; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentTransaction; import androidx.preference.PreferenceManager; import java.util.concurrent.ExecutorService; Loading Loading @@ -141,6 +142,13 @@ public class MainActivity extends AppCompatActivity Intent intent = new Intent(this, SettingsActivity.class); settingsLauncher.launch(intent); return true; } else if (id == R.id.menu_self_check) { SelfCheckFragment fragment = new SelfCheckFragment(); FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); transaction.replace(R.id.fragment_placeholder, fragment); transaction.addToBackStack(null); transaction.commit(); return true; } else if (id == R.id.menu_about) { showAbout(); return true; Loading app/src/main/java/net/fabiszewski/ulogger/SelfCheckFragment.java 0 → 100644 +234 −0 Original line number Diff line number Diff line /* * Copyright (c) 2019 Bartek Fabiszewski * http://www.fabiszewski.net * * This file is part of μlogger-android. * Licensed under GPL, either version 3, or any later. * See <http://www.gnu.org/licenses/> */ package net.fabiszewski.ulogger; import static android.Manifest.permission.ACCESS_BACKGROUND_LOCATION; import static android.Manifest.permission.ACCESS_COARSE_LOCATION; import static android.Manifest.permission.ACCESS_FINE_LOCATION; import static android.Manifest.permission.POST_NOTIFICATIONS; import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE; import android.content.Context; import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.content.pm.PermissionInfo; import android.location.LocationManager; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.os.PowerManager; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; import androidx.appcompat.widget.SwitchCompat; import androidx.core.app.ActivityCompat; import androidx.fragment.app.Fragment; import androidx.preference.PreferenceManager; import org.json.JSONException; import java.io.IOException; public class SelfCheckFragment extends Fragment { private static final String TAG = SelfCheckFragment.class.getSimpleName(); private SwitchCompat preciseLocationSwitch; private TextView approximateLocationLabel; private SwitchCompat approximateLocationSwitch; private TextView preciseLocationLabel; private View backgroundLocationLayout; private TextView backgroundLocationLabel; private SwitchCompat backgroundLocationSwitch; private View storageLayout; private TextView storageLabel; private SwitchCompat storageSwitch; private View notificationsLayout; private TextView notificationsLabel; private SwitchCompat notificationsSwitch; private SwitchCompat locationGpsSwitch; private SwitchCompat locationNetSwitch; private SwitchCompat serverConfiguredSwitch; private SwitchCompat serverReachableSwitch; private TextView serverReachableDetails; private TextView validAccountDetails; private SwitchCompat validAccountSwitch; private View batteryUsageLayout; private SwitchCompat batteryUsageSwitch; public SelfCheckFragment() { } @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { if (Logger.DEBUG) { Log.d(TAG, "[onCreateView]"); } View layout = inflater.inflate(R.layout.fragment_self_check, container, false); approximateLocationSwitch = layout.findViewById(R.id.permissionApproximateLocationResult); approximateLocationLabel = layout.findViewById(R.id.permissionApproximateLocationLabel); preciseLocationSwitch = layout.findViewById(R.id.permissionPreciseLocationResult); preciseLocationLabel = layout.findViewById(R.id.permissionPreciseLocationLabel); backgroundLocationLayout = layout.findViewById(R.id.permissionBackgroundLocationSelfCheck); backgroundLocationLabel = layout.findViewById(R.id.permissionBackgroundLocationLabel); backgroundLocationSwitch = layout.findViewById(R.id.permissionBackgroundLocationResult); storageLayout = layout.findViewById(R.id.permissionStorageSelfCheck); storageLabel = layout.findViewById(R.id.permissionStorageLabel); storageSwitch = layout.findViewById(R.id.permissionStorageResult); notificationsLayout = layout.findViewById(R.id.permissionNotificationsSelfCheck); notificationsLabel = layout.findViewById(R.id.permissionNotificationsLabel); notificationsSwitch = layout.findViewById(R.id.permissionNotificationsResult); locationGpsSwitch = layout.findViewById(R.id.providerGpsResult); locationNetSwitch = layout.findViewById(R.id.providerNetResult); serverConfiguredSwitch = layout.findViewById(R.id.serverConfiguredResult); serverReachableSwitch = layout.findViewById(R.id.serverReachableResult); serverReachableDetails = layout.findViewById(R.id.serverReachableDetails); validAccountDetails = layout.findViewById(R.id.validAccountDetails); validAccountSwitch = layout.findViewById(R.id.validAccountResult); batteryUsageLayout = layout.findViewById(R.id.batteryUnrestrictedSelfCheck); batteryUsageSwitch = layout.findViewById(R.id.batteryUnrestrictedUsageResult); selfCheck(); return layout; } private void selfCheck() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { checkPermissions(); } checkProviders(); checkServer(); } private void checkServer() { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(requireContext()); String host = prefs.getString(SettingsActivity.KEY_HOST, "").replaceAll("/+$", ""); serverConfiguredSwitch.setChecked(!host.isEmpty()); serverReachableSwitch.setChecked(false); validAccountSwitch.setChecked(false); if (!host.isEmpty()) { Handler handler = new Handler(Looper.getMainLooper()); new Thread(() -> { WebHelper webHelper = new WebHelper(requireContext()); boolean isReachable = false; String details = null; try { isReachable = webHelper.isReachable(); } catch (IOException e) { details = e.getLocalizedMessage(); } boolean finalIsReachable = isReachable; String finalDetails = details; handler.post(() -> { if (finalDetails != null) { serverReachableDetails.setText(finalDetails); } serverReachableSwitch.setChecked(finalIsReachable); }); if (isReachable) { boolean isValidAccount = false; try { webHelper.checkAuthorization(); isValidAccount = true; } catch (IOException | WebAuthException | JSONException e) { details = e.getLocalizedMessage(); } boolean finalIsValidAccount = isValidAccount; String finalAccountDetails = details; handler.post(() -> { if (finalAccountDetails != null) { validAccountDetails.setText(finalAccountDetails); } validAccountSwitch.setChecked(finalIsValidAccount); }); } }).start(); } } private void checkProviders() { LocationManager locationManager = (LocationManager) requireContext().getSystemService(Context.LOCATION_SERVICE); locationGpsSwitch.setChecked(locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)); locationNetSwitch.setChecked(locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)); } @RequiresApi(api = Build.VERSION_CODES.M) private void checkPermissions() { setItem(null, approximateLocationLabel, approximateLocationSwitch, ACCESS_COARSE_LOCATION); setItem(null, preciseLocationLabel, preciseLocationSwitch, ACCESS_FINE_LOCATION); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { setItem(backgroundLocationLayout, backgroundLocationLabel, backgroundLocationSwitch, ACCESS_BACKGROUND_LOCATION); } if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) { setItem(storageLayout, storageLabel, storageSwitch, WRITE_EXTERNAL_STORAGE); } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { setItem(notificationsLayout, notificationsLabel, notificationsSwitch, POST_NOTIFICATIONS); } checkBatteryUsage(); } @RequiresApi(api = Build.VERSION_CODES.M) private void setItem(@Nullable View layout, @NonNull TextView label, @NonNull SwitchCompat switchCompat, @NonNull String permission) { if (layout != null) { layout.setVisibility(View.VISIBLE); } switchCompat.setChecked(isAllowed(permission)); label.setText(getPermissionLabel(permission)); } @RequiresApi(api = Build.VERSION_CODES.M) private boolean isAllowed(@NonNull String permission) { boolean isAllowed = ActivityCompat.checkSelfPermission(requireContext(), permission) == PackageManager.PERMISSION_GRANTED; if (Logger.DEBUG) { Log.d(TAG, "[isAllowed " + permission + ": " + isAllowed + " ]"); } return isAllowed; } private CharSequence getPermissionLabel(@NonNull String permission) { try { PackageManager pm = requireContext().getPackageManager(); PermissionInfo info = pm.getPermissionInfo(permission, 0); CharSequence label = info.loadLabel(pm); return new StringBuilder(label.length()) .appendCodePoint(Character.toTitleCase(Character.codePointAt(label, 0))) .append(label, Character.offsetByCodePoints(label, 0, 1), label.length()); } catch (PackageManager.NameNotFoundException e) { if (Logger.DEBUG) { Log.d(TAG, "[getPermissionLabel not found:" + e + "]"); } } return permission; } @RequiresApi(api = Build.VERSION_CODES.M) private void checkBatteryUsage() { batteryUsageLayout.setVisibility(View.VISIBLE); PowerManager pm = (PowerManager) requireContext().getSystemService(Context.POWER_SERVICE); boolean isIgnoringOptimizations = pm.isIgnoringBatteryOptimizations(requireContext().getPackageName()); batteryUsageSwitch.setChecked(isIgnoringOptimizations); if (Logger.DEBUG) { Log.d(TAG, "[isIgnoringOptimizations: " + isIgnoringOptimizations + " ]"); } } } app/src/main/java/net/fabiszewski/ulogger/WebHelper.java +75 −0 Original line number Diff line number Diff line Loading @@ -12,6 +12,9 @@ package net.fabiszewski.ulogger; import android.content.ContentResolver; import android.content.Context; import android.content.SharedPreferences; import android.net.ConnectivityManager; import android.net.NetworkCapabilities; import android.net.NetworkInfo; import android.net.Uri; import android.os.Build; import android.util.Base64; Loading Loading @@ -459,6 +462,78 @@ class WebHelper { isAuthorized = false; } void checkAuthorization() throws JSONException, IOException, WebAuthException { boolean wasAuthorized = isAuthorized; try { authorize(); if (!wasAuthorized) { deauthorize(); } } catch (IOException | WebAuthException | JSONException e) { if (Logger.DEBUG) { Log.d(TAG, "[isValidAccount exception: " + e + "]"); } throw e; } } /** * Ping server without authorization * @throws IOException Exception on timeout or server internal error */ boolean isReachable() throws IOException { if (!isNetworkAvailable()) { return false; } HttpURLConnection connection = null; try { URL url = new URL(host + "/" + CLIENT_SCRIPT); connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("HEAD"); connection.setRequestProperty("User-Agent", userAgent); connection.setConnectTimeout(SOCKET_TIMEOUT); connection.setReadTimeout(SOCKET_TIMEOUT); int responseCode = connection.getResponseCode(); if (Logger.DEBUG) { Log.d(TAG, "[isReachable " + host + ": " + responseCode + "]"); } if (responseCode / 100 == 5) { throw new IOException(context.getString(R.string.e_http_code, responseCode)); } return true; } catch (IOException e) { if (Logger.DEBUG) { Log.d(TAG, "[isReachable exception: " + e + "]"); } throw e; } finally { if (connection != null) { connection.disconnect(); } } } private boolean isNetworkAvailable() { boolean isAvailable = false; ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); if (connectivityManager != null) { if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) { NetworkCapabilities capabilities = connectivityManager.getNetworkCapabilities(connectivityManager.getActiveNetwork()); if (capabilities != null) { isAvailable = capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED); } } else { isAvailable = isNetworkAvailableApi21(connectivityManager); } } if (Logger.DEBUG) { Log.d(TAG, "[isNetworkAvailable " + isAvailable + "]"); } return isAvailable; } @SuppressWarnings({"deprecation", "RedundantSuppression"}) private boolean isNetworkAvailableApi21(ConnectivityManager connectivityManager) { NetworkInfo info = connectivityManager.getActiveNetworkInfo(); return info != null && info.isAvailable() && info.isConnected(); } /** * Get settings from shared preferences * @param context Context Loading app/src/main/res/drawable/ic_baseline_check_box_24.xml 0 → 100644 +5 −0 Original line number Diff line number Diff line <vector android:height="24dp" android:tint="#FFFFFF" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> <path android:fillColor="@android:color/white" android:pathData="M19,3L5,3c-1.11,0 -2,0.9 -2,2v14c0,1.1 0.89,2 2,2h14c1.11,0 2,-0.9 2,-2L21,5c0,-1.1 -0.89,-2 -2,-2zM10,17l-5,-5 1.41,-1.41L10,14.17l7.59,-7.59L19,8l-9,9z"/> </vector> app/src/main/res/layout/fragment_self_check.xml 0 → 100644 +493 −0 File added.Preview size limit exceeded, changes collapsed. Show changes Loading
app/src/main/java/net/fabiszewski/ulogger/MainActivity.java +8 −0 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ import androidx.appcompat.widget.Toolbar; import androidx.core.text.HtmlCompat; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentTransaction; import androidx.preference.PreferenceManager; import java.util.concurrent.ExecutorService; Loading Loading @@ -141,6 +142,13 @@ public class MainActivity extends AppCompatActivity Intent intent = new Intent(this, SettingsActivity.class); settingsLauncher.launch(intent); return true; } else if (id == R.id.menu_self_check) { SelfCheckFragment fragment = new SelfCheckFragment(); FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); transaction.replace(R.id.fragment_placeholder, fragment); transaction.addToBackStack(null); transaction.commit(); return true; } else if (id == R.id.menu_about) { showAbout(); return true; Loading
app/src/main/java/net/fabiszewski/ulogger/SelfCheckFragment.java 0 → 100644 +234 −0 Original line number Diff line number Diff line /* * Copyright (c) 2019 Bartek Fabiszewski * http://www.fabiszewski.net * * This file is part of μlogger-android. * Licensed under GPL, either version 3, or any later. * See <http://www.gnu.org/licenses/> */ package net.fabiszewski.ulogger; import static android.Manifest.permission.ACCESS_BACKGROUND_LOCATION; import static android.Manifest.permission.ACCESS_COARSE_LOCATION; import static android.Manifest.permission.ACCESS_FINE_LOCATION; import static android.Manifest.permission.POST_NOTIFICATIONS; import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE; import android.content.Context; import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.content.pm.PermissionInfo; import android.location.LocationManager; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.os.PowerManager; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; import androidx.appcompat.widget.SwitchCompat; import androidx.core.app.ActivityCompat; import androidx.fragment.app.Fragment; import androidx.preference.PreferenceManager; import org.json.JSONException; import java.io.IOException; public class SelfCheckFragment extends Fragment { private static final String TAG = SelfCheckFragment.class.getSimpleName(); private SwitchCompat preciseLocationSwitch; private TextView approximateLocationLabel; private SwitchCompat approximateLocationSwitch; private TextView preciseLocationLabel; private View backgroundLocationLayout; private TextView backgroundLocationLabel; private SwitchCompat backgroundLocationSwitch; private View storageLayout; private TextView storageLabel; private SwitchCompat storageSwitch; private View notificationsLayout; private TextView notificationsLabel; private SwitchCompat notificationsSwitch; private SwitchCompat locationGpsSwitch; private SwitchCompat locationNetSwitch; private SwitchCompat serverConfiguredSwitch; private SwitchCompat serverReachableSwitch; private TextView serverReachableDetails; private TextView validAccountDetails; private SwitchCompat validAccountSwitch; private View batteryUsageLayout; private SwitchCompat batteryUsageSwitch; public SelfCheckFragment() { } @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { if (Logger.DEBUG) { Log.d(TAG, "[onCreateView]"); } View layout = inflater.inflate(R.layout.fragment_self_check, container, false); approximateLocationSwitch = layout.findViewById(R.id.permissionApproximateLocationResult); approximateLocationLabel = layout.findViewById(R.id.permissionApproximateLocationLabel); preciseLocationSwitch = layout.findViewById(R.id.permissionPreciseLocationResult); preciseLocationLabel = layout.findViewById(R.id.permissionPreciseLocationLabel); backgroundLocationLayout = layout.findViewById(R.id.permissionBackgroundLocationSelfCheck); backgroundLocationLabel = layout.findViewById(R.id.permissionBackgroundLocationLabel); backgroundLocationSwitch = layout.findViewById(R.id.permissionBackgroundLocationResult); storageLayout = layout.findViewById(R.id.permissionStorageSelfCheck); storageLabel = layout.findViewById(R.id.permissionStorageLabel); storageSwitch = layout.findViewById(R.id.permissionStorageResult); notificationsLayout = layout.findViewById(R.id.permissionNotificationsSelfCheck); notificationsLabel = layout.findViewById(R.id.permissionNotificationsLabel); notificationsSwitch = layout.findViewById(R.id.permissionNotificationsResult); locationGpsSwitch = layout.findViewById(R.id.providerGpsResult); locationNetSwitch = layout.findViewById(R.id.providerNetResult); serverConfiguredSwitch = layout.findViewById(R.id.serverConfiguredResult); serverReachableSwitch = layout.findViewById(R.id.serverReachableResult); serverReachableDetails = layout.findViewById(R.id.serverReachableDetails); validAccountDetails = layout.findViewById(R.id.validAccountDetails); validAccountSwitch = layout.findViewById(R.id.validAccountResult); batteryUsageLayout = layout.findViewById(R.id.batteryUnrestrictedSelfCheck); batteryUsageSwitch = layout.findViewById(R.id.batteryUnrestrictedUsageResult); selfCheck(); return layout; } private void selfCheck() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { checkPermissions(); } checkProviders(); checkServer(); } private void checkServer() { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(requireContext()); String host = prefs.getString(SettingsActivity.KEY_HOST, "").replaceAll("/+$", ""); serverConfiguredSwitch.setChecked(!host.isEmpty()); serverReachableSwitch.setChecked(false); validAccountSwitch.setChecked(false); if (!host.isEmpty()) { Handler handler = new Handler(Looper.getMainLooper()); new Thread(() -> { WebHelper webHelper = new WebHelper(requireContext()); boolean isReachable = false; String details = null; try { isReachable = webHelper.isReachable(); } catch (IOException e) { details = e.getLocalizedMessage(); } boolean finalIsReachable = isReachable; String finalDetails = details; handler.post(() -> { if (finalDetails != null) { serverReachableDetails.setText(finalDetails); } serverReachableSwitch.setChecked(finalIsReachable); }); if (isReachable) { boolean isValidAccount = false; try { webHelper.checkAuthorization(); isValidAccount = true; } catch (IOException | WebAuthException | JSONException e) { details = e.getLocalizedMessage(); } boolean finalIsValidAccount = isValidAccount; String finalAccountDetails = details; handler.post(() -> { if (finalAccountDetails != null) { validAccountDetails.setText(finalAccountDetails); } validAccountSwitch.setChecked(finalIsValidAccount); }); } }).start(); } } private void checkProviders() { LocationManager locationManager = (LocationManager) requireContext().getSystemService(Context.LOCATION_SERVICE); locationGpsSwitch.setChecked(locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)); locationNetSwitch.setChecked(locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)); } @RequiresApi(api = Build.VERSION_CODES.M) private void checkPermissions() { setItem(null, approximateLocationLabel, approximateLocationSwitch, ACCESS_COARSE_LOCATION); setItem(null, preciseLocationLabel, preciseLocationSwitch, ACCESS_FINE_LOCATION); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { setItem(backgroundLocationLayout, backgroundLocationLabel, backgroundLocationSwitch, ACCESS_BACKGROUND_LOCATION); } if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) { setItem(storageLayout, storageLabel, storageSwitch, WRITE_EXTERNAL_STORAGE); } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { setItem(notificationsLayout, notificationsLabel, notificationsSwitch, POST_NOTIFICATIONS); } checkBatteryUsage(); } @RequiresApi(api = Build.VERSION_CODES.M) private void setItem(@Nullable View layout, @NonNull TextView label, @NonNull SwitchCompat switchCompat, @NonNull String permission) { if (layout != null) { layout.setVisibility(View.VISIBLE); } switchCompat.setChecked(isAllowed(permission)); label.setText(getPermissionLabel(permission)); } @RequiresApi(api = Build.VERSION_CODES.M) private boolean isAllowed(@NonNull String permission) { boolean isAllowed = ActivityCompat.checkSelfPermission(requireContext(), permission) == PackageManager.PERMISSION_GRANTED; if (Logger.DEBUG) { Log.d(TAG, "[isAllowed " + permission + ": " + isAllowed + " ]"); } return isAllowed; } private CharSequence getPermissionLabel(@NonNull String permission) { try { PackageManager pm = requireContext().getPackageManager(); PermissionInfo info = pm.getPermissionInfo(permission, 0); CharSequence label = info.loadLabel(pm); return new StringBuilder(label.length()) .appendCodePoint(Character.toTitleCase(Character.codePointAt(label, 0))) .append(label, Character.offsetByCodePoints(label, 0, 1), label.length()); } catch (PackageManager.NameNotFoundException e) { if (Logger.DEBUG) { Log.d(TAG, "[getPermissionLabel not found:" + e + "]"); } } return permission; } @RequiresApi(api = Build.VERSION_CODES.M) private void checkBatteryUsage() { batteryUsageLayout.setVisibility(View.VISIBLE); PowerManager pm = (PowerManager) requireContext().getSystemService(Context.POWER_SERVICE); boolean isIgnoringOptimizations = pm.isIgnoringBatteryOptimizations(requireContext().getPackageName()); batteryUsageSwitch.setChecked(isIgnoringOptimizations); if (Logger.DEBUG) { Log.d(TAG, "[isIgnoringOptimizations: " + isIgnoringOptimizations + " ]"); } } }
app/src/main/java/net/fabiszewski/ulogger/WebHelper.java +75 −0 Original line number Diff line number Diff line Loading @@ -12,6 +12,9 @@ package net.fabiszewski.ulogger; import android.content.ContentResolver; import android.content.Context; import android.content.SharedPreferences; import android.net.ConnectivityManager; import android.net.NetworkCapabilities; import android.net.NetworkInfo; import android.net.Uri; import android.os.Build; import android.util.Base64; Loading Loading @@ -459,6 +462,78 @@ class WebHelper { isAuthorized = false; } void checkAuthorization() throws JSONException, IOException, WebAuthException { boolean wasAuthorized = isAuthorized; try { authorize(); if (!wasAuthorized) { deauthorize(); } } catch (IOException | WebAuthException | JSONException e) { if (Logger.DEBUG) { Log.d(TAG, "[isValidAccount exception: " + e + "]"); } throw e; } } /** * Ping server without authorization * @throws IOException Exception on timeout or server internal error */ boolean isReachable() throws IOException { if (!isNetworkAvailable()) { return false; } HttpURLConnection connection = null; try { URL url = new URL(host + "/" + CLIENT_SCRIPT); connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("HEAD"); connection.setRequestProperty("User-Agent", userAgent); connection.setConnectTimeout(SOCKET_TIMEOUT); connection.setReadTimeout(SOCKET_TIMEOUT); int responseCode = connection.getResponseCode(); if (Logger.DEBUG) { Log.d(TAG, "[isReachable " + host + ": " + responseCode + "]"); } if (responseCode / 100 == 5) { throw new IOException(context.getString(R.string.e_http_code, responseCode)); } return true; } catch (IOException e) { if (Logger.DEBUG) { Log.d(TAG, "[isReachable exception: " + e + "]"); } throw e; } finally { if (connection != null) { connection.disconnect(); } } } private boolean isNetworkAvailable() { boolean isAvailable = false; ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); if (connectivityManager != null) { if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) { NetworkCapabilities capabilities = connectivityManager.getNetworkCapabilities(connectivityManager.getActiveNetwork()); if (capabilities != null) { isAvailable = capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED); } } else { isAvailable = isNetworkAvailableApi21(connectivityManager); } } if (Logger.DEBUG) { Log.d(TAG, "[isNetworkAvailable " + isAvailable + "]"); } return isAvailable; } @SuppressWarnings({"deprecation", "RedundantSuppression"}) private boolean isNetworkAvailableApi21(ConnectivityManager connectivityManager) { NetworkInfo info = connectivityManager.getActiveNetworkInfo(); return info != null && info.isAvailable() && info.isConnected(); } /** * Get settings from shared preferences * @param context Context Loading
app/src/main/res/drawable/ic_baseline_check_box_24.xml 0 → 100644 +5 −0 Original line number Diff line number Diff line <vector android:height="24dp" android:tint="#FFFFFF" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> <path android:fillColor="@android:color/white" android:pathData="M19,3L5,3c-1.11,0 -2,0.9 -2,2v14c0,1.1 0.89,2 2,2h14c1.11,0 2,-0.9 2,-2L21,5c0,-1.1 -0.89,-2 -2,-2zM10,17l-5,-5 1.41,-1.41L10,14.17l7.59,-7.59L19,8l-9,9z"/> </vector>
app/src/main/res/layout/fragment_self_check.xml 0 → 100644 +493 −0 File added.Preview size limit exceeded, changes collapsed. Show changes