Add button for Huawei's power manager to setup wizard

This commit is contained in:
Torsten Grote
2017-11-30 12:17:40 -02:00
parent 4b88f0d9f1
commit f199105f6c
17 changed files with 437 additions and 50 deletions

View File

@@ -1,17 +1,19 @@
package org.briarproject.briar.android.login;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
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.NotNullByDefault;
import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.login.PowerView.OnCheckedChangedListener;
import org.briarproject.briar.android.util.UiUtils;
import static android.view.View.INVISIBLE;
@@ -19,12 +21,15 @@ 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;
@TargetApi(23)
public class DozeFragment extends SetupFragment {
@NotNullByDefault
public class DozeFragment extends SetupFragment
implements OnCheckedChangedListener {
private final static String TAG = DozeFragment.class.getName();
private Button dozeButton;
private DozeView dozeView;
private HuaweiView huaweiView;
private Button next;
private ProgressBar progressBar;
private boolean secondAttempt = false;
@@ -33,15 +38,22 @@ public class DozeFragment extends SetupFragment {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
public View onCreateView(LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
getActivity().setTitle(getString(R.string.setup_doze_title));
setHasOptionsMenu(false);
View v = inflater.inflate(R.layout.fragment_setup_doze, container,
false);
dozeButton = v.findViewById(R.id.dozeButton);
dozeView = v.findViewById(R.id.dozeView);
dozeView.setOnCheckedChangedListener(this);
huaweiView = v.findViewById(R.id.huaweiView);
huaweiView.setOnCheckedChangedListener(this);
next = v.findViewById(R.id.next);
progressBar = v.findViewById(R.id.progress);
dozeButton.setOnClickListener(view -> askForDozeWhitelisting());
dozeView.setOnButtonClickListener(this::askForDozeWhitelisting);
next.setOnClickListener(this);
return v;
}
@@ -65,25 +77,34 @@ public class DozeFragment extends SetupFragment {
public void onActivityResult(int request, int result, Intent data) {
super.onActivityResult(request, result, data);
if (request == REQUEST_DOZE_WHITELISTING) {
if (!setupController.needsDozeWhitelisting() || secondAttempt) {
dozeButton.setEnabled(false);
onClick(dozeButton);
} else {
if (!dozeView.needsToBeShown() || secondAttempt) {
dozeView.setChecked(true);
} else if (getContext() != null) {
secondAttempt = true;
showOnboardingDialog(getContext(), getHelpText());
}
}
}
@Override
public void onCheckedChanged() {
if (dozeView.isChecked() && huaweiView.isChecked()) {
next.setEnabled(true);
} else {
next.setEnabled(false);
}
}
@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) {
dozeButton.setVisibility(INVISIBLE);
next.setVisibility(INVISIBLE);
progressBar.setVisibility(VISIBLE);
setupController.createAccount();
}

View File

@@ -0,0 +1,60 @@
package org.briarproject.briar.android.login;
import android.content.Context;
import android.support.annotation.Nullable;
import android.support.annotation.UiThread;
import android.util.AttributeSet;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.briar.R;
import static org.briarproject.briar.android.util.UiUtils.needsDozeWhitelisting;
@UiThread
@NotNullByDefault
class DozeView extends PowerView {
@Nullable
private Runnable onButtonClickListener;
public DozeView(Context context) {
this(context, null);
}
public DozeView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public DozeView(Context context, @Nullable AttributeSet attrs,
int defStyleAttr) {
super(context, attrs, defStyleAttr);
setText(R.string.setup_doze_intro);
setButtonText(R.string.setup_doze_button);
}
@Override
public boolean needsToBeShown() {
return needsToBeShown(getContext());
}
public static boolean needsToBeShown(Context context) {
return needsDozeWhitelisting(context);
}
@Override
protected int getHelpText() {
return R.string.setup_doze_explanation;
}
@Override
protected void onButtonClick() {
if (onButtonClickListener == null) throw new IllegalStateException();
onButtonClickListener.run();
}
public void setOnButtonClickListener(Runnable runnable) {
onButtonClickListener = runnable;
}
}

View File

@@ -0,0 +1,72 @@
package org.briarproject.briar.android.login;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.support.annotation.StringRes;
import android.support.annotation.UiThread;
import android.util.AttributeSet;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.briar.R;
import java.util.List;
import javax.annotation.Nullable;
@UiThread
@NotNullByDefault
class HuaweiView extends PowerView {
private final static String PACKAGE_NAME = "com.huawei.systemmanager";
private final static String CLASS_NAME =
PACKAGE_NAME + ".optimize.process.ProtectActivity";
public HuaweiView(Context context) {
this(context, null);
}
public HuaweiView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public HuaweiView(Context context, @Nullable AttributeSet attrs,
int defStyleAttr) {
super(context, attrs, defStyleAttr);
setText(R.string.setup_huawei_text);
setButtonText(R.string.setup_huawei_button);
}
@Override
public boolean needsToBeShown() {
return needsToBeShown(getContext());
}
public static boolean needsToBeShown(Context context) {
PackageManager pm = context.getPackageManager();
List<ResolveInfo> resolveInfos = pm.queryIntentActivities(getIntent(),
PackageManager.MATCH_DEFAULT_ONLY);
return !resolveInfos.isEmpty();
}
@Override
@StringRes
protected int getHelpText() {
return R.string.setup_huawei_help;
}
@Override
protected void onButtonClick() {
getContext().startActivity(getIntent());
setChecked(true);
}
private static Intent getIntent() {
Intent intent = new Intent();
intent.setClassName(PACKAGE_NAME, CLASS_NAME);
return intent;
}
}

View File

@@ -66,7 +66,7 @@ public class PasswordFragment extends SetupFragment {
component.inject(this);
// the controller is not yet available in onCreateView()
if (!setupController.needsDozeWhitelisting()) {
if (!setupController.needToShowDozeFragment()) {
nextButton.setText(R.string.create_account_button);
}
}
@@ -102,7 +102,7 @@ public class PasswordFragment extends SetupFragment {
@Override
public void onClick(View view) {
if (!setupController.needsDozeWhitelisting()) {
if (!setupController.needToShowDozeFragment()) {
nextButton.setVisibility(INVISIBLE);
progressBar.setVisibility(VISIBLE);
}

View File

@@ -0,0 +1,162 @@
package org.briarproject.briar.android.login;
import android.content.Context;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.Nullable;
import android.support.annotation.StringRes;
import android.support.annotation.UiThread;
import android.support.constraint.ConstraintLayout;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
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 static android.content.Context.LAYOUT_INFLATER_SERVICE;
import static org.briarproject.briar.android.util.UiUtils.showOnboardingDialog;
@UiThread
@NotNullByDefault
abstract class PowerView extends ConstraintLayout {
private final TextView textView;
private final ImageView checkImage;
private final Button button;
private boolean checked = false;
@Nullable
private OnCheckedChangedListener onCheckedChangedListener;
public PowerView(Context context) {
this(context, null);
}
public PowerView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
@SuppressWarnings("ConstantConditions")
public PowerView(Context context, @Nullable AttributeSet attrs,
int defStyleAttr) {
super(context, attrs, defStyleAttr);
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(LAYOUT_INFLATER_SERVICE);
View v = inflater.inflate(R.layout.power_view, this, true);
textView = v.findViewById(R.id.textView);
checkImage = v.findViewById(R.id.checkImage);
button = v.findViewById(R.id.button);
button.setOnClickListener(view -> onButtonClick());
ImageButton helpButton = v.findViewById(R.id.helpButton);
helpButton.setOnClickListener(view -> onHelpButtonClick());
// we need to manage the checkImage state ourselves, because automatic
// state saving is done based on the view's ID and there can be
// multiple ImageViews with the same ID in the view hierarchy
setSaveFromParentEnabled(true);
if (!isInEditMode() && !needsToBeShown()) {
setVisibility(GONE);
}
}
@Nullable
@Override
protected Parcelable onSaveInstanceState() {
Parcelable superState = super.onSaveInstanceState();
SavedState ss = new SavedState(superState);
ss.value = new boolean[] {checked};
return ss;
}
@Override
protected void onRestoreInstanceState(Parcelable state) {
SavedState ss = (SavedState) state;
super.onRestoreInstanceState(ss.getSuperState());
setChecked(ss.value[0]); // also calls listener
}
public abstract boolean needsToBeShown();
public void setChecked(boolean checked) {
this.checked = checked;
if (checked) {
checkImage.setImageResource(R.drawable.ic_check_white);
} else {
checkImage.setImageResource(R.drawable.contact_disconnected);
}
if (onCheckedChangedListener != null) {
onCheckedChangedListener.onCheckedChanged();
}
}
public boolean isChecked() {
return getVisibility() == GONE || checked;
}
public void setOnCheckedChangedListener(
OnCheckedChangedListener onCheckedChangedListener) {
this.onCheckedChangedListener = onCheckedChangedListener;
}
@StringRes
protected abstract int getHelpText();
protected void setText(@StringRes int res) {
textView.setText(res);
}
protected void setButtonText(@StringRes int res) {
button.setText(res);
}
protected abstract void onButtonClick();
private void onHelpButtonClick() {
showOnboardingDialog(getContext(),
getContext().getString(getHelpText()));
}
private static class SavedState extends BaseSavedState {
private boolean[] value = {false};
private SavedState(@Nullable Parcelable superState) {
super(superState);
}
private SavedState(Parcel in) {
super(in);
in.readBooleanArray(value);
}
@Override
public void writeToParcel(Parcel out, int flags) {
super.writeToParcel(out, flags);
out.writeBooleanArray(value);
}
static final Parcelable.Creator<SavedState> CREATOR
= new Parcelable.Creator<SavedState>() {
public SavedState createFromParcel(Parcel in) {
return new SavedState(in);
}
public SavedState[] newArray(int size) {
return new SavedState[size];
}
};
}
interface OnCheckedChangedListener {
void onCheckedChanged();
}
}

View File

@@ -8,7 +8,7 @@ public interface SetupController {
void setSetupActivity(SetupActivity setupActivity);
boolean needsDozeWhitelisting();
boolean needToShowDozeFragment();
void setAuthorName(String authorName);

View File

@@ -11,7 +11,6 @@ import org.briarproject.bramble.api.db.DatabaseConfig;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.briar.android.controller.handler.ResultHandler;
import org.briarproject.briar.android.controller.handler.UiResultHandler;
import org.briarproject.briar.android.util.UiUtils;
import java.util.concurrent.Executor;
@@ -41,9 +40,10 @@ public class SetupControllerImpl extends PasswordControllerImpl
}
@Override
public boolean needsDozeWhitelisting() {
public boolean needToShowDozeFragment() {
if (setupActivity == null) throw new IllegalStateException();
return UiUtils.needsDozeWhitelisting(setupActivity);
return DozeView.needsToBeShown(setupActivity) ||
HuaweiView.needsToBeShown(setupActivity);
}
@Override
@@ -61,7 +61,7 @@ public class SetupControllerImpl extends PasswordControllerImpl
@Override
public void showDozeOrCreateAccount() {
if (setupActivity == null) throw new IllegalStateException();
if (needsDozeWhitelisting()) {
if (needToShowDozeFragment()) {
setupActivity.showDozeFragment();
} else {
createAccount();