mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-11 18:29:05 +01:00
Factor out power management UI code into library
This commit is contained in:
@@ -99,13 +99,14 @@ dependencies {
|
||||
implementation project(path: ':briar-core', configuration: 'default')
|
||||
implementation project(path: ':bramble-core', configuration: 'default')
|
||||
implementation project(':bramble-android')
|
||||
implementation project(':dont-kill-me-lib')
|
||||
|
||||
implementation 'androidx.fragment:fragment:1.3.4'
|
||||
implementation "androidx.fragment:fragment:$androidx_fragment_version"
|
||||
implementation 'androidx.preference:preference:1.1.1'
|
||||
implementation 'androidx.exifinterface:exifinterface:1.3.2'
|
||||
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
|
||||
implementation 'com.google.android.material:material:1.3.0'
|
||||
implementation "androidx.constraintlayout:constraintlayout:$androidx_constraintlayout_version"
|
||||
implementation "com.google.android.material:material:$google_material_version"
|
||||
implementation 'androidx.recyclerview:recyclerview-selection:1.1.0'
|
||||
|
||||
implementation 'info.guardianproject.panic:panic:1.0'
|
||||
|
||||
@@ -39,11 +39,11 @@ import static androidx.test.espresso.matcher.ViewMatchers.withId;
|
||||
import static androidx.test.espresso.matcher.ViewMatchers.withText;
|
||||
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
|
||||
import static java.lang.Thread.sleep;
|
||||
import static org.briarproject.android.dontkillmelib.PowerUtils.needsDozeWhitelisting;
|
||||
import static org.briarproject.bramble.api.plugin.LanTcpConstants.ID;
|
||||
import static org.briarproject.briar.android.OverlayTapViewAction.visualClick;
|
||||
import static org.briarproject.briar.android.ViewActions.waitFor;
|
||||
import static org.briarproject.briar.android.ViewActions.waitUntilMatches;
|
||||
import static org.briarproject.briar.android.util.UiUtils.needsDozeWhitelisting;
|
||||
import static org.hamcrest.CoreMatchers.allOf;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
|
||||
@@ -26,9 +26,9 @@ import static androidx.test.espresso.matcher.ViewMatchers.isEnabled;
|
||||
import static androidx.test.espresso.matcher.ViewMatchers.withId;
|
||||
import static androidx.test.espresso.matcher.ViewMatchers.withText;
|
||||
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
|
||||
import static org.briarproject.android.dontkillmelib.PowerUtils.needsDozeWhitelisting;
|
||||
import static org.briarproject.bramble.api.plugin.LanTcpConstants.ID;
|
||||
import static org.briarproject.briar.android.ViewActions.waitUntilMatches;
|
||||
import static org.briarproject.briar.android.util.UiUtils.needsDozeWhitelisting;
|
||||
import static org.hamcrest.Matchers.allOf;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
tools:ignore="ScopedStorage" />
|
||||
|
||||
<uses-permission-sdk-23 android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
<uses-permission-sdk-23 android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
|
||||
<uses-permission-sdk-23 android:name="android.permission.USE_BIOMETRIC" />
|
||||
<uses-permission-sdk-23 android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
|
||||
@@ -477,9 +476,6 @@
|
||||
|
||||
<queries>
|
||||
<package android:name="info.guardianproject.ripple" />
|
||||
<package android:name="com.huawei.systemmanager" />
|
||||
<package android:name="com.huawei.powergenie" />
|
||||
<package android:name="com.evenwell.PowerMonitor" />
|
||||
|
||||
<intent>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
@@ -33,6 +33,7 @@ import org.briarproject.bramble.plugin.tor.CircumventionProvider;
|
||||
import org.briarproject.bramble.system.ClockModule;
|
||||
import org.briarproject.briar.BriarCoreEagerSingletons;
|
||||
import org.briarproject.briar.BriarCoreModule;
|
||||
import org.briarproject.briar.android.account.DoNotKillMeFragment;
|
||||
import org.briarproject.briar.android.attachment.AttachmentModule;
|
||||
import org.briarproject.briar.android.attachment.media.MediaModule;
|
||||
import org.briarproject.briar.android.contact.connect.BluetoothIntroFragment;
|
||||
@@ -239,4 +240,6 @@ public interface AndroidComponent
|
||||
void inject(ReceiveFragment receiveFragment);
|
||||
|
||||
void inject(BluetoothIntroFragment bluetoothIntroFragment);
|
||||
|
||||
void inject(DoNotKillMeFragment dozeFragment);
|
||||
}
|
||||
|
||||
@@ -1,57 +1,16 @@
|
||||
package org.briarproject.briar.android;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.PowerManager;
|
||||
|
||||
import org.briarproject.android.dontkillmelib.AbstractDozeWatchdogImpl;
|
||||
import org.briarproject.bramble.api.lifecycle.Service;
|
||||
import org.briarproject.bramble.api.lifecycle.ServiceException;
|
||||
import org.briarproject.briar.api.android.DozeWatchdog;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import static android.content.Context.POWER_SERVICE;
|
||||
import static android.os.Build.VERSION.SDK_INT;
|
||||
import static android.os.PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED;
|
||||
|
||||
class DozeWatchdogImpl implements DozeWatchdog, Service {
|
||||
|
||||
private final Context appContext;
|
||||
private final AtomicBoolean dozed = new AtomicBoolean(false);
|
||||
private final BroadcastReceiver receiver = new DozeBroadcastReceiver();
|
||||
class DozeWatchdogImpl extends AbstractDozeWatchdogImpl
|
||||
implements DozeWatchdog, Service {
|
||||
|
||||
DozeWatchdogImpl(Context appContext) {
|
||||
this.appContext = appContext;
|
||||
super(appContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getAndResetDozeFlag() {
|
||||
return dozed.getAndSet(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startService() throws ServiceException {
|
||||
if (SDK_INT < 23) return;
|
||||
IntentFilter filter = new IntentFilter(ACTION_DEVICE_IDLE_MODE_CHANGED);
|
||||
appContext.registerReceiver(receiver, filter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopService() throws ServiceException {
|
||||
if (SDK_INT < 23) return;
|
||||
appContext.unregisterReceiver(receiver);
|
||||
}
|
||||
|
||||
private class DozeBroadcastReceiver extends BroadcastReceiver {
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (SDK_INT < 23) return;
|
||||
PowerManager pm =
|
||||
(PowerManager) appContext.getSystemService(POWER_SERVICE);
|
||||
if (pm.isDeviceIdleMode()) dozed.set(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
package org.briarproject.briar.android.account;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import org.briarproject.android.dontkillmelib.AbstractDoNotKillMeFragment;
|
||||
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
||||
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
|
||||
import static org.briarproject.briar.android.AppModule.getAndroidComponent;
|
||||
|
||||
@MethodsNotNullByDefault
|
||||
@ParametersNotNullByDefault
|
||||
public class DoNotKillMeFragment extends AbstractDoNotKillMeFragment {
|
||||
|
||||
@Inject
|
||||
ViewModelProvider.Factory viewModelFactory;
|
||||
SetupViewModel viewModel;
|
||||
|
||||
@Override
|
||||
public void onAttach(Context context) {
|
||||
super.onAttach(context);
|
||||
FragmentActivity activity = requireActivity();
|
||||
getAndroidComponent(activity).inject(this);
|
||||
viewModel = new ViewModelProvider(activity, viewModelFactory)
|
||||
.get(SetupViewModel.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onButtonClicked() {
|
||||
viewModel.dozeExceptionConfirmed();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,119 +0,0 @@
|
||||
package org.briarproject.briar.android.account;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.ProgressBar;
|
||||
|
||||
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
||||
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.android.account.PowerView.OnCheckedChangedListener;
|
||||
import org.briarproject.briar.android.util.UiUtils;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import static android.view.View.INVISIBLE;
|
||||
import static android.view.View.VISIBLE;
|
||||
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_DOZE_WHITELISTING;
|
||||
import static org.briarproject.briar.android.util.UiUtils.showOnboardingDialog;
|
||||
|
||||
@MethodsNotNullByDefault
|
||||
@ParametersNotNullByDefault
|
||||
public class DozeFragment extends SetupFragment
|
||||
implements OnCheckedChangedListener {
|
||||
|
||||
private final static String TAG = DozeFragment.class.getName();
|
||||
|
||||
private DozeView dozeView;
|
||||
private HuaweiProtectedAppsView huaweiProtectedAppsView;
|
||||
private HuaweiAppLaunchView huaweiAppLaunchView;
|
||||
private XiaomiView xiaomiView;
|
||||
private Button next;
|
||||
private boolean secondAttempt = false;
|
||||
|
||||
public static DozeFragment newInstance() {
|
||||
return new DozeFragment();
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater,
|
||||
@Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
requireActivity().setTitle(getString(R.string.setup_doze_title));
|
||||
setHasOptionsMenu(false);
|
||||
View v = inflater.inflate(R.layout.fragment_setup_doze, container,
|
||||
false);
|
||||
dozeView = v.findViewById(R.id.dozeView);
|
||||
dozeView.setOnCheckedChangedListener(this);
|
||||
huaweiProtectedAppsView = v.findViewById(R.id.huaweiProtectedAppsView);
|
||||
huaweiProtectedAppsView.setOnCheckedChangedListener(this);
|
||||
huaweiAppLaunchView = v.findViewById(R.id.huaweiAppLaunchView);
|
||||
huaweiAppLaunchView.setOnCheckedChangedListener(this);
|
||||
xiaomiView = v.findViewById(R.id.xiaomiView);
|
||||
xiaomiView.setOnCheckedChangedListener(this);
|
||||
next = v.findViewById(R.id.next);
|
||||
ProgressBar progressBar = v.findViewById(R.id.progress);
|
||||
|
||||
dozeView.setOnButtonClickListener(this::askForDozeWhitelisting);
|
||||
next.setOnClickListener(this);
|
||||
|
||||
viewModel.getIsCreatingAccount()
|
||||
.observe(getViewLifecycleOwner(), isCreatingAccount -> {
|
||||
if (isCreatingAccount) {
|
||||
next.setVisibility(INVISIBLE);
|
||||
progressBar.setVisibility(VISIBLE);
|
||||
}
|
||||
});
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUniqueTag() {
|
||||
return TAG;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getHelpText() {
|
||||
return getString(R.string.setup_doze_explanation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int request, int result,
|
||||
@Nullable Intent data) {
|
||||
super.onActivityResult(request, result, data);
|
||||
if (request == REQUEST_DOZE_WHITELISTING) {
|
||||
if (!dozeView.needsToBeShown() || secondAttempt) {
|
||||
dozeView.setChecked(true);
|
||||
} else if (getContext() != null) {
|
||||
secondAttempt = true;
|
||||
showOnboardingDialog(getContext(), getHelpText());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCheckedChanged() {
|
||||
next.setEnabled(dozeView.isChecked() &&
|
||||
huaweiProtectedAppsView.isChecked() &&
|
||||
huaweiAppLaunchView.isChecked() &&
|
||||
xiaomiView.isChecked());
|
||||
}
|
||||
|
||||
@SuppressLint("BatteryLife")
|
||||
private void askForDozeWhitelisting() {
|
||||
if (getContext() == null) return;
|
||||
Intent i = UiUtils.getDozeWhitelistingIntent(getContext());
|
||||
startActivityForResult(i, REQUEST_DOZE_WHITELISTING);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
viewModel.dozeExceptionConfirmed();
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
package org.briarproject.briar.android.account;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
interface DozeHelper {
|
||||
|
||||
boolean needToShowDozeFragment(Context context);
|
||||
}
|
||||
@@ -1,5 +1,8 @@
|
||||
package org.briarproject.briar.android.account;
|
||||
|
||||
import org.briarproject.android.dontkillmelib.DozeHelper;
|
||||
import org.briarproject.android.dontkillmelib.DozeHelperImpl;
|
||||
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
|
||||
|
||||
@@ -14,12 +14,14 @@ import org.briarproject.briar.android.fragment.BaseFragment.BaseFragmentListener
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
|
||||
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
|
||||
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
|
||||
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
|
||||
import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
|
||||
import static androidx.lifecycle.Lifecycle.State.STARTED;
|
||||
import static org.briarproject.briar.android.BriarApplication.ENTRY_ACTIVITY;
|
||||
import static org.briarproject.briar.android.account.SetupViewModel.State.AUTHOR_NAME;
|
||||
import static org.briarproject.briar.android.account.SetupViewModel.State.CREATED;
|
||||
@@ -28,6 +30,7 @@ import static org.briarproject.briar.android.account.SetupViewModel.State.FAILED
|
||||
import static org.briarproject.briar.android.account.SetupViewModel.State.SET_PASSWORD;
|
||||
import static org.briarproject.briar.android.util.UiUtils.setInputStateAlwaysVisible;
|
||||
import static org.briarproject.briar.android.util.UiUtils.setInputStateHidden;
|
||||
import static org.briarproject.briar.android.util.UiUtils.showFragment;
|
||||
|
||||
@MethodsNotNullByDefault
|
||||
@ParametersNotNullByDefault
|
||||
@@ -77,7 +80,10 @@ public class SetupActivity extends BaseActivity
|
||||
|
||||
@TargetApi(23)
|
||||
void showDozeFragment() {
|
||||
showNextFragment(DozeFragment.newInstance());
|
||||
Fragment f = new DoNotKillMeFragment();
|
||||
String tag = DoNotKillMeFragment.TAG;
|
||||
if (!getLifecycle().getCurrentState().isAtLeast(STARTED)) return;
|
||||
showFragment(getSupportFragmentManager(), f, tag);
|
||||
}
|
||||
|
||||
void showApp() {
|
||||
|
||||
@@ -2,6 +2,7 @@ package org.briarproject.briar.android.account;
|
||||
|
||||
import android.app.Application;
|
||||
|
||||
import org.briarproject.android.dontkillmelib.DozeHelper;
|
||||
import org.briarproject.bramble.api.account.AccountManager;
|
||||
import org.briarproject.bramble.api.crypto.PasswordStrengthEstimator;
|
||||
import org.briarproject.bramble.api.lifecycle.IoExecutor;
|
||||
@@ -95,7 +96,7 @@ class SetupViewModel extends AndroidViewModel {
|
||||
}
|
||||
|
||||
boolean needToShowDozeFragment() {
|
||||
return dozeHelper.needToShowDozeFragment(getApplication());
|
||||
return dozeHelper.needToShowDoNotKillMeFragment(getApplication());
|
||||
}
|
||||
|
||||
void dozeExceptionConfirmed() {
|
||||
|
||||
@@ -36,11 +36,11 @@ import static android.content.Intent.FLAG_ACTIVITY_NO_ANIMATION;
|
||||
import static android.os.Build.VERSION.SDK_INT;
|
||||
import static java.util.logging.Level.INFO;
|
||||
import static java.util.logging.Logger.getLogger;
|
||||
import static org.briarproject.android.dontkillmelib.PowerUtils.getDozeWhitelistingIntent;
|
||||
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_DOZE_WHITELISTING;
|
||||
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_PASSWORD;
|
||||
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_UNLOCK;
|
||||
import static org.briarproject.briar.android.util.UiUtils.excludeSystemUi;
|
||||
import static org.briarproject.briar.android.util.UiUtils.getDozeWhitelistingIntent;
|
||||
import static org.briarproject.briar.android.util.UiUtils.isSamsung7;
|
||||
|
||||
@MethodsNotNullByDefault
|
||||
|
||||
@@ -27,10 +27,10 @@ import androidx.annotation.CallSuper;
|
||||
|
||||
import static java.util.logging.Level.WARNING;
|
||||
import static java.util.logging.Logger.getLogger;
|
||||
import static org.briarproject.android.dontkillmelib.PowerUtils.needsDozeWhitelisting;
|
||||
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.STARTING_SERVICES;
|
||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||
import static org.briarproject.briar.android.settings.SettingsFragment.SETTINGS_NAMESPACE;
|
||||
import static org.briarproject.briar.android.util.UiUtils.needsDozeWhitelisting;
|
||||
|
||||
@NotNullByDefault
|
||||
public class BriarControllerImpl implements BriarController {
|
||||
|
||||
@@ -25,11 +25,11 @@ import androidx.lifecycle.MutableLiveData;
|
||||
import static java.util.concurrent.TimeUnit.DAYS;
|
||||
import static java.util.logging.Level.WARNING;
|
||||
import static java.util.logging.Logger.getLogger;
|
||||
import static org.briarproject.android.dontkillmelib.PowerUtils.needsDozeWhitelisting;
|
||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||
import static org.briarproject.briar.android.TestingConstants.EXPIRY_DATE;
|
||||
import static org.briarproject.briar.android.controller.BriarControllerImpl.DOZE_ASK_AGAIN;
|
||||
import static org.briarproject.briar.android.settings.SettingsFragment.SETTINGS_NAMESPACE;
|
||||
import static org.briarproject.briar.android.util.UiUtils.needsDozeWhitelisting;
|
||||
|
||||
@NotNullByDefault
|
||||
public class NavDrawerViewModel extends DbViewModel {
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package org.briarproject.briar.android.util;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.app.KeyguardManager;
|
||||
import android.content.ActivityNotFoundException;
|
||||
@@ -12,7 +10,6 @@ import android.content.res.Resources;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.location.LocationManager;
|
||||
import android.net.Uri;
|
||||
import android.os.PowerManager;
|
||||
import android.text.Spannable;
|
||||
import android.text.SpannableString;
|
||||
import android.text.SpannableStringBuilder;
|
||||
@@ -68,13 +65,11 @@ import androidx.lifecycle.Observer;
|
||||
import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat;
|
||||
|
||||
import static android.content.Context.KEYGUARD_SERVICE;
|
||||
import static android.content.Context.POWER_SERVICE;
|
||||
import static android.content.Intent.CATEGORY_DEFAULT;
|
||||
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
|
||||
import static android.os.Build.MANUFACTURER;
|
||||
import static android.os.Build.VERSION.SDK_INT;
|
||||
import static android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS;
|
||||
import static android.provider.Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS;
|
||||
import static android.text.format.DateUtils.DAY_IN_MILLIS;
|
||||
import static android.text.format.DateUtils.FORMAT_ABBREV_ALL;
|
||||
import static android.text.format.DateUtils.FORMAT_ABBREV_MONTH;
|
||||
@@ -323,23 +318,6 @@ public class UiUtils {
|
||||
.show();
|
||||
}
|
||||
|
||||
public static boolean needsDozeWhitelisting(Context ctx) {
|
||||
if (SDK_INT < 23) return false;
|
||||
PowerManager pm = (PowerManager) ctx.getSystemService(POWER_SERVICE);
|
||||
String packageName = ctx.getPackageName();
|
||||
if (pm == null) throw new AssertionError();
|
||||
return !pm.isIgnoringBatteryOptimizations(packageName);
|
||||
}
|
||||
|
||||
@TargetApi(23)
|
||||
@SuppressLint("BatteryLife")
|
||||
public static Intent getDozeWhitelistingIntent(Context ctx) {
|
||||
Intent i = new Intent();
|
||||
i.setAction(ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
|
||||
i.setData(Uri.parse("package:" + ctx.getPackageName()));
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if location is enabled,
|
||||
* or it isn't required due to this being a SDK < 28 device.
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<org.briarproject.briar.android.view.BriarRecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/feedList"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:emptyText="@string/blogs_rss_feeds_manage_empty_state"
|
||||
app:scrollToEnd="false"
|
||||
tools:listitem="@layout/list_item_rss_feed" />
|
||||
@@ -65,6 +65,12 @@
|
||||
<item name="android:minWidth">@dimen/button_size</item>
|
||||
</style>
|
||||
|
||||
<style name="HelpButton" parent="BriarButtonFlat.Positive">
|
||||
<item name="android:tint">@color/briar_button_text_positive</item>
|
||||
</style>
|
||||
|
||||
<style name="DoNotKillMeButton" parent="BriarButton" />
|
||||
|
||||
<style name="Divider">
|
||||
<item name="android:background">@color/divider</item>
|
||||
</style>
|
||||
|
||||
@@ -3,6 +3,7 @@ package org.briarproject.briar.android.account;
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
|
||||
import org.briarproject.android.dontkillmelib.DozeHelper;
|
||||
import org.briarproject.bramble.api.account.AccountManager;
|
||||
import org.briarproject.bramble.api.crypto.PasswordStrengthEstimator;
|
||||
import org.briarproject.bramble.test.BrambleMockTestCase;
|
||||
@@ -48,7 +49,7 @@ public class SetupViewModelTest extends BrambleMockTestCase {
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(accountManager).accountExists();
|
||||
will(returnValue(false));
|
||||
allowing(dozeHelper).needToShowDozeFragment(app);
|
||||
allowing(dozeHelper).needToShowDoNotKillMeFragment(app);
|
||||
allowing(app).getApplicationContext();
|
||||
will(returnValue(appContext));
|
||||
allowing(appContext).getPackageManager();
|
||||
|
||||
@@ -36,4 +36,8 @@ buildscript {
|
||||
ext.dagger_version = "2.33"
|
||||
ext.junit_version = "4.13.2"
|
||||
ext.jmock_version = '2.12.0'
|
||||
|
||||
ext.androidx_fragment_version = '1.3.4'
|
||||
ext.androidx_constraintlayout_version = '2.0.4'
|
||||
ext.google_material_version = '1.3.0'
|
||||
}
|
||||
|
||||
1
dont-kill-me-lib/.gitignore
vendored
Normal file
1
dont-kill-me-lib/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/build
|
||||
32
dont-kill-me-lib/build.gradle
Normal file
32
dont-kill-me-lib/build.gradle
Normal file
@@ -0,0 +1,32 @@
|
||||
plugins {
|
||||
id 'com.android.library'
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 31
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 30
|
||||
|
||||
vectorDrawables.useSupportLibrary = true
|
||||
consumerProguardFiles "consumer-rules.pro"
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation "androidx.fragment:fragment:$androidx_fragment_version"
|
||||
implementation "androidx.constraintlayout:constraintlayout:$androidx_constraintlayout_version"
|
||||
implementation "com.google.android.material:material:$google_material_version"
|
||||
}
|
||||
0
dont-kill-me-lib/consumer-rules.pro
Normal file
0
dont-kill-me-lib/consumer-rules.pro
Normal file
21
dont-kill-me-lib/proguard-rules.pro
vendored
Normal file
21
dont-kill-me-lib/proguard-rules.pro
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
13
dont-kill-me-lib/src/main/AndroidManifest.xml
Normal file
13
dont-kill-me-lib/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="org.briarproject.android.dontkillmelib">
|
||||
|
||||
<uses-permission-sdk-23 android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
|
||||
|
||||
<queries>
|
||||
<package android:name="com.huawei.systemmanager" />
|
||||
<package android:name="com.huawei.powergenie" />
|
||||
<package android:name="com.evenwell.PowerMonitor" />
|
||||
</queries>
|
||||
|
||||
</manifest>
|
||||
@@ -0,0 +1,115 @@
|
||||
package org.briarproject.android.dontkillmelib;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.ProgressBar;
|
||||
|
||||
import org.briarproject.android.dontkillmelib.PowerView.OnCheckedChangedListener;
|
||||
|
||||
import androidx.activity.result.ActivityResult;
|
||||
import androidx.activity.result.ActivityResultCallback;
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import static android.view.View.INVISIBLE;
|
||||
import static android.view.View.VISIBLE;
|
||||
import static org.briarproject.android.dontkillmelib.PowerUtils.getDozeWhitelistingIntent;
|
||||
import static org.briarproject.android.dontkillmelib.PowerUtils.showOnboardingDialog;
|
||||
|
||||
public abstract class AbstractDoNotKillMeFragment extends Fragment
|
||||
implements OnCheckedChangedListener,
|
||||
ActivityResultCallback<ActivityResult> {
|
||||
|
||||
public final static String TAG =
|
||||
AbstractDoNotKillMeFragment.class.getName();
|
||||
|
||||
private DozeView dozeView;
|
||||
private HuaweiProtectedAppsView huaweiProtectedAppsView;
|
||||
private HuaweiAppLaunchView huaweiAppLaunchView;
|
||||
private XiaomiView xiaomiView;
|
||||
private Button next;
|
||||
private boolean secondAttempt = false;
|
||||
private boolean buttonWasClicked = false;
|
||||
|
||||
private final ActivityResultLauncher<Intent> dozeLauncher =
|
||||
registerForActivityResult(new StartActivityForResult(), this);
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater,
|
||||
@Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
requireActivity().setTitle(getString(R.string.setup_doze_title));
|
||||
setHasOptionsMenu(false);
|
||||
View v = inflater.inflate(R.layout.fragment_dont_kill_me, container,
|
||||
false);
|
||||
dozeView = v.findViewById(R.id.dozeView);
|
||||
dozeView.setOnCheckedChangedListener(this);
|
||||
huaweiProtectedAppsView = v.findViewById(R.id.huaweiProtectedAppsView);
|
||||
huaweiProtectedAppsView.setOnCheckedChangedListener(this);
|
||||
huaweiAppLaunchView = v.findViewById(R.id.huaweiAppLaunchView);
|
||||
huaweiAppLaunchView.setOnCheckedChangedListener(this);
|
||||
xiaomiView = v.findViewById(R.id.xiaomiView);
|
||||
xiaomiView.setOnCheckedChangedListener(this);
|
||||
next = v.findViewById(R.id.next);
|
||||
ProgressBar progressBar = v.findViewById(R.id.progress);
|
||||
|
||||
dozeView.setOnButtonClickListener(this::askForDozeWhitelisting);
|
||||
next.setOnClickListener(view -> {
|
||||
buttonWasClicked = true;
|
||||
next.setVisibility(INVISIBLE);
|
||||
progressBar.setVisibility(VISIBLE);
|
||||
onButtonClicked();
|
||||
});
|
||||
|
||||
// restore UI state if button was clicked already
|
||||
buttonWasClicked = savedInstanceState != null &&
|
||||
savedInstanceState.getBoolean("buttonWasClicked", false);
|
||||
if (buttonWasClicked) {
|
||||
next.setVisibility(INVISIBLE);
|
||||
progressBar.setVisibility(VISIBLE);
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
protected abstract void onButtonClicked();
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(@NonNull Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putBoolean("buttonWasClicked", buttonWasClicked);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(ActivityResult result) {
|
||||
if (!dozeView.needsToBeShown() || secondAttempt) {
|
||||
dozeView.setChecked(true);
|
||||
} else if (getContext() != null) {
|
||||
secondAttempt = true;
|
||||
String s = getString(R.string.setup_doze_explanation);
|
||||
showOnboardingDialog(getContext(), s);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCheckedChanged() {
|
||||
next.setEnabled(dozeView.isChecked() &&
|
||||
huaweiProtectedAppsView.isChecked() &&
|
||||
huaweiAppLaunchView.isChecked() &&
|
||||
xiaomiView.isChecked());
|
||||
}
|
||||
|
||||
@SuppressLint("BatteryLife")
|
||||
private void askForDozeWhitelisting() {
|
||||
if (getContext() == null) return;
|
||||
dozeLauncher.launch(getDozeWhitelistingIntent(getContext()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package org.briarproject.android.dontkillmelib;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.PowerManager;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import static android.content.Context.POWER_SERVICE;
|
||||
import static android.os.Build.VERSION.SDK_INT;
|
||||
import static android.os.PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED;
|
||||
|
||||
public abstract class AbstractDozeWatchdogImpl {
|
||||
|
||||
private final Context appContext;
|
||||
private final AtomicBoolean dozed = new AtomicBoolean(false);
|
||||
private final BroadcastReceiver receiver = new DozeBroadcastReceiver();
|
||||
|
||||
public AbstractDozeWatchdogImpl(Context appContext) {
|
||||
this.appContext = appContext;
|
||||
}
|
||||
|
||||
public boolean getAndResetDozeFlag() {
|
||||
return dozed.getAndSet(false);
|
||||
}
|
||||
|
||||
public void startService() {
|
||||
if (SDK_INT < 23) return;
|
||||
IntentFilter filter = new IntentFilter(ACTION_DEVICE_IDLE_MODE_CHANGED);
|
||||
appContext.registerReceiver(receiver, filter);
|
||||
}
|
||||
|
||||
public void stopService() {
|
||||
if (SDK_INT < 23) return;
|
||||
appContext.unregisterReceiver(receiver);
|
||||
}
|
||||
|
||||
private class DozeBroadcastReceiver extends BroadcastReceiver {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (SDK_INT < 23) return;
|
||||
PowerManager pm =
|
||||
(PowerManager) appContext.getSystemService(POWER_SERVICE);
|
||||
if (pm.isDeviceIdleMode()) dozed.set(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package org.briarproject.android.dontkillmelib;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
public interface DozeHelper {
|
||||
boolean needToShowDoNotKillMeFragment(Context context);
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
package org.briarproject.briar.android.account;
|
||||
package org.briarproject.android.dontkillmelib;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import static org.briarproject.briar.android.util.UiUtils.needsDozeWhitelisting;
|
||||
import static org.briarproject.android.dontkillmelib.PowerUtils.needsDozeWhitelisting;
|
||||
|
||||
class DozeHelperImpl implements DozeHelper {
|
||||
public class DozeHelperImpl implements DozeHelper {
|
||||
@Override
|
||||
public boolean needToShowDozeFragment(Context context) {
|
||||
public boolean needToShowDoNotKillMeFragment(Context context) {
|
||||
Context appContext = context.getApplicationContext();
|
||||
return needsDozeWhitelisting(appContext) ||
|
||||
HuaweiProtectedAppsView.needsToBeShown(appContext) ||
|
||||
@@ -1,19 +1,15 @@
|
||||
package org.briarproject.briar.android.account;
|
||||
package org.briarproject.android.dontkillmelib;
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.briar.R;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.UiThread;
|
||||
|
||||
import static org.briarproject.briar.android.util.UiUtils.needsDozeWhitelisting;
|
||||
import static org.briarproject.android.dontkillmelib.PowerUtils.needsDozeWhitelisting;
|
||||
|
||||
@UiThread
|
||||
@NotNullByDefault
|
||||
class DozeView extends PowerView {
|
||||
|
||||
@Nullable
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.briarproject.briar.android.account;
|
||||
package org.briarproject.android.dontkillmelib;
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
@@ -7,13 +7,9 @@ import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.briar.R;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.annotation.UiThread;
|
||||
|
||||
@@ -21,7 +17,6 @@ import static android.content.pm.PackageManager.MATCH_DEFAULT_ONLY;
|
||||
import static android.os.Build.VERSION.SDK_INT;
|
||||
|
||||
@UiThread
|
||||
@NotNullByDefault
|
||||
class HuaweiAppLaunchView extends PowerView {
|
||||
|
||||
private final static String PACKAGE_NAME = "com.huawei.systemmanager";
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.briarproject.briar.android.account;
|
||||
package org.briarproject.android.dontkillmelib;
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
@@ -7,13 +7,9 @@ import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.briar.R;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.annotation.UiThread;
|
||||
|
||||
@@ -21,7 +17,6 @@ import static android.content.pm.PackageManager.MATCH_DEFAULT_ONLY;
|
||||
import static android.os.Build.VERSION.SDK_INT;
|
||||
|
||||
@UiThread
|
||||
@NotNullByDefault
|
||||
class HuaweiProtectedAppsView extends PowerView {
|
||||
|
||||
private final static String PACKAGE_NAME = "com.huawei.systemmanager";
|
||||
@@ -0,0 +1,60 @@
|
||||
package org.briarproject.android.dontkillmelib;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.PowerManager;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Scanner;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
|
||||
import static android.content.Context.POWER_SERVICE;
|
||||
import static android.os.Build.VERSION.SDK_INT;
|
||||
import static android.provider.Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS;
|
||||
import static java.lang.Runtime.getRuntime;
|
||||
|
||||
public class PowerUtils {
|
||||
|
||||
public static boolean needsDozeWhitelisting(Context ctx) {
|
||||
if (SDK_INT < 23) return false;
|
||||
PowerManager pm = (PowerManager) ctx.getSystemService(POWER_SERVICE);
|
||||
String packageName = ctx.getPackageName();
|
||||
if (pm == null) throw new AssertionError();
|
||||
return !pm.isIgnoringBatteryOptimizations(packageName);
|
||||
}
|
||||
|
||||
@TargetApi(23)
|
||||
@SuppressLint("BatteryLife")
|
||||
public static Intent getDozeWhitelistingIntent(Context ctx) {
|
||||
Intent i = new Intent();
|
||||
i.setAction(ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
|
||||
i.setData(Uri.parse("package:" + ctx.getPackageName()));
|
||||
return i;
|
||||
}
|
||||
|
||||
static void showOnboardingDialog(Context ctx, String text) {
|
||||
new AlertDialog.Builder(ctx, R.style.OnboardingDialogTheme)
|
||||
.setMessage(text)
|
||||
.setNeutralButton(R.string.got_it,
|
||||
(dialog, which) -> dialog.cancel())
|
||||
.show();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
static String getSystemProperty(String propName) {
|
||||
try {
|
||||
Process p = getRuntime().exec("getprop " + propName);
|
||||
Scanner s = new Scanner(p.getInputStream());
|
||||
String line = s.nextLine();
|
||||
s.close();
|
||||
return line;
|
||||
} catch (SecurityException | IOException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.briarproject.briar.android.account;
|
||||
package org.briarproject.android.dontkillmelib;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Parcel;
|
||||
@@ -11,19 +11,15 @@ import android.widget.ImageButton;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.briar.R;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.annotation.UiThread;
|
||||
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||
|
||||
import static android.content.Context.LAYOUT_INFLATER_SERVICE;
|
||||
import static org.briarproject.briar.android.util.UiUtils.showOnboardingDialog;
|
||||
import static org.briarproject.android.dontkillmelib.PowerUtils.showOnboardingDialog;
|
||||
|
||||
@UiThread
|
||||
@NotNullByDefault
|
||||
abstract class PowerView extends ConstraintLayout {
|
||||
|
||||
private final TextView textView;
|
||||
@@ -1,24 +1,18 @@
|
||||
package org.briarproject.briar.android.account;
|
||||
package org.briarproject.android.dontkillmelib;
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.briar.R;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.annotation.UiThread;
|
||||
|
||||
import static android.os.Build.BRAND;
|
||||
import static org.briarproject.bramble.util.AndroidUtils.getSystemProperty;
|
||||
import static org.briarproject.bramble.util.StringUtils.isNullOrEmpty;
|
||||
import static org.briarproject.briar.android.util.UiUtils.showOnboardingDialog;
|
||||
import static org.briarproject.android.dontkillmelib.PowerUtils.getSystemProperty;
|
||||
import static org.briarproject.android.dontkillmelib.PowerUtils.showOnboardingDialog;
|
||||
|
||||
@UiThread
|
||||
@NotNullByDefault
|
||||
class XiaomiView extends PowerView {
|
||||
|
||||
public XiaomiView(Context context) {
|
||||
@@ -63,7 +57,7 @@ class XiaomiView extends PowerView {
|
||||
|
||||
private boolean isMiuiTenOrLater() {
|
||||
String version = getSystemProperty("ro.miui.ui.version.name");
|
||||
if (isNullOrEmpty(version)) return false;
|
||||
if (version == null || version.equals("")) return false;
|
||||
version = version.replaceAll("[^\\d]", "");
|
||||
try {
|
||||
return Integer.parseInt(version) >= 10;
|
||||
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportHeight="24.0"
|
||||
android:viewportWidth="24.0">
|
||||
<path
|
||||
android:fillColor="#FFFFFFFF"
|
||||
android:pathData="M9,16.17L4.83,12l-1.42,1.41L9,19 21,7l-1.41,-1.41z" />
|
||||
</vector>
|
||||
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportHeight="24.0"
|
||||
android:viewportWidth="24.0">
|
||||
<path
|
||||
android:fillColor="#FFFFFFFF"
|
||||
android:pathData="M11,18h2v-2h-2v2zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8zM12,6c-2.21,0 -4,1.79 -4,4h2c0,-1.1 0.9,-2 2,-2s2,0.9 2,2c0,2 -3,1.75 -3,5h2c0,-2.25 3,-2.5 3,-5 0,-2.21 -1.79,-4 -4,-4z" />
|
||||
</vector>
|
||||
@@ -9,47 +9,47 @@
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="@dimen/margin_activity_vertical">
|
||||
android:padding="16dp">
|
||||
|
||||
<org.briarproject.briar.android.account.DozeView
|
||||
<org.briarproject.android.dontkillmelib.DozeView
|
||||
android:id="@+id/dozeView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/margin_large"
|
||||
android:paddingBottom="16dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<org.briarproject.briar.android.account.HuaweiProtectedAppsView
|
||||
<org.briarproject.android.dontkillmelib.HuaweiProtectedAppsView
|
||||
android:id="@+id/huaweiProtectedAppsView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/margin_large"
|
||||
android:paddingBottom="16dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/dozeView" />
|
||||
|
||||
<org.briarproject.briar.android.account.HuaweiAppLaunchView
|
||||
<org.briarproject.android.dontkillmelib.HuaweiAppLaunchView
|
||||
android:id="@+id/huaweiAppLaunchView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/margin_large"
|
||||
android:paddingBottom="16dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/huaweiProtectedAppsView" />
|
||||
|
||||
<org.briarproject.briar.android.account.XiaomiView
|
||||
<org.briarproject.android.dontkillmelib.XiaomiView
|
||||
android:id="@+id/xiaomiView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/margin_large"
|
||||
android:paddingBottom="16dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/huaweiAppLaunchView" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/next"
|
||||
style="@style/BriarButton"
|
||||
style="@style/DoNotKillMeButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:enabled="false"
|
||||
@@ -10,12 +10,12 @@
|
||||
android:id="@+id/textView"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/margin_large"
|
||||
android:layout_marginLeft="@dimen/margin_large"
|
||||
android:layout_marginTop="@dimen/margin_medium"
|
||||
android:layout_marginEnd="@dimen/margin_large"
|
||||
android:layout_marginRight="@dimen/margin_large"
|
||||
android:textSize="@dimen/text_size_medium"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
@@ -25,7 +25,7 @@
|
||||
android:id="@+id/checkImage"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_margin="@dimen/margin_medium"
|
||||
android:layout_margin="8dp"
|
||||
android:visibility="invisible"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/button"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
@@ -36,10 +36,10 @@
|
||||
|
||||
<Button
|
||||
android:id="@+id/button"
|
||||
style="@style/BriarButton"
|
||||
style="@style/DoNotKillMeButton"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="@dimen/margin_medium"
|
||||
android:layout_margin="8dp"
|
||||
app:layout_constraintEnd_toStartOf="@+id/helpButton"
|
||||
app:layout_constraintStart_toEndOf="@+id/checkImage"
|
||||
app:layout_constraintTop_toBottomOf="@+id/textView"
|
||||
@@ -47,12 +47,11 @@
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/helpButton"
|
||||
style="@style/BriarButtonFlat.Positive"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_margin="@dimen/margin_medium"
|
||||
style="@style/HelpButton"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:contentDescription="@string/help"
|
||||
android:tint="@color/briar_button_text_positive"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/button"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/button"
|
||||
29
dont-kill-me-lib/src/main/res/values/strings.xml
Normal file
29
dont-kill-me-lib/src/main/res/values/strings.xml
Normal file
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation">
|
||||
|
||||
<!--
|
||||
WARNING: These strings typically get overwritten by library consumers.
|
||||
If adding/removing strings here, consumers need to adapt.
|
||||
-->
|
||||
|
||||
<string name="setup_doze_title">Background Connections</string>
|
||||
<string name="setup_doze_intro">To work properly, this app needs to run in the background.</string>
|
||||
<string name="setup_doze_explanation">Please disable battery optimizations so this app can run in the background.</string>
|
||||
<string name="setup_doze_button">Allow Connections</string>
|
||||
<string name="create_account_button">Continue</string>
|
||||
|
||||
<string name="setup_huawei_text">Please tap the button below and make sure this app is protected in the \"Protected Apps\" screen.</string>
|
||||
<string name="setup_huawei_button">Protect this app</string>
|
||||
<string name="setup_huawei_help">If this app is not added to the protected apps list, it will be unable to run in the background.</string>
|
||||
<string name="setup_huawei_app_launch_text">Please tap the button below, open the \"App launch\" screen and make sure this app is set to \"Manage manually\".</string>
|
||||
<string name="setup_huawei_app_launch_button">Open Battery Settings</string>
|
||||
<string name="setup_huawei_app_launch_help">If this app is not set to \"Manage manually\" in the \"App launch\" screen, it will not be able to run in the background.</string>
|
||||
<string name="setup_xiaomi_text">To run in the background, this app needs to be locked to the recent apps list.</string>
|
||||
<string name="setup_xiaomi_button">Protect this app</string>
|
||||
<string name="setup_xiaomi_help">If this app is not locked to the recent apps list, it will be unable to run in the background.</string>
|
||||
<string name="setup_xiaomi_dialog_body_old">1. Open the recent apps list (also called the app switcher)\n\n2. Swipe down on the image of this app to show the padlock icon\n\n3. If the padlock is not locked, tap to lock it</string>
|
||||
<string name="setup_xiaomi_dialog_body_new">1. Open the recent apps list (also called the app switcher)\n\n2. Press and hold the image of this app until the padlock button appears\n\n3. If the padlock is not locked, tap to lock it</string>
|
||||
|
||||
<string name="got_it">Got it</string>
|
||||
<string name="help">Help</string>
|
||||
</resources>
|
||||
12
dont-kill-me-lib/src/main/res/values/styles.xml
Normal file
12
dont-kill-me-lib/src/main/res/values/styles.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<style name="OnboardingDialogTheme" parent="Theme.AppCompat.DayNight.Dialog.MinWidth" />
|
||||
|
||||
<style name="DoNotKillMeButton" parent="Widget.AppCompat.Button.Colored" />
|
||||
|
||||
<style name="HelpButton" parent="Widget.AppCompat.Button.Borderless">
|
||||
<item name="android:tint">#418cd8</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
@@ -6,3 +6,4 @@ include ':briar-api'
|
||||
include ':briar-core'
|
||||
include ':briar-android'
|
||||
include ':briar-headless'
|
||||
include ':dont-kill-me-lib'
|
||||
|
||||
Reference in New Issue
Block a user