mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-13 11:19:04 +01:00
Don't show tap protection dialog until it's needed.
This commit is contained in:
@@ -183,15 +183,13 @@ public class ScreenFilterMonitorImpl extends BroadcastReceiver
|
||||
|
||||
@Override
|
||||
@UiThread
|
||||
public void storeAppsAsShown(Collection<String> s, boolean persistent) {
|
||||
HashSet<String> buf = new HashSet<>(s);
|
||||
shownApps.addAll(buf);
|
||||
if (persistent && !s.isEmpty()) {
|
||||
buf.addAll(getShownScreenFilterApps());
|
||||
prefs.edit()
|
||||
.putStringSet(PREF_SCREEN_FILTER_APPS, buf)
|
||||
.apply();
|
||||
}
|
||||
public void storeAppsAsShown(Collection<String> shown) {
|
||||
shownApps.addAll(shown);
|
||||
HashSet<String> buf = new HashSet<>(shown);
|
||||
buf.addAll(getShownScreenFilterApps());
|
||||
prefs.edit()
|
||||
.putStringSet(PREF_SCREEN_FILTER_APPS, buf)
|
||||
.apply();
|
||||
}
|
||||
|
||||
private Set<String> getInstalledScreenFilterApps() {
|
||||
|
||||
@@ -27,7 +27,7 @@ public class StartupFailureActivity extends BaseActivity {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void showNewScreenFilterWarning() {
|
||||
protected void showScreenFilterWarning() {
|
||||
// Don't show here, service might not be available
|
||||
}
|
||||
|
||||
|
||||
@@ -2,9 +2,13 @@ package org.briarproject.briar.android.activity;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.support.annotation.LayoutRes;
|
||||
import android.support.annotation.UiThread;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewGroup.LayoutParams;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
|
||||
import org.briarproject.bramble.api.db.DbException;
|
||||
@@ -13,7 +17,9 @@ import org.briarproject.briar.android.BriarApplication;
|
||||
import org.briarproject.briar.android.DestroyableContext;
|
||||
import org.briarproject.briar.android.controller.ActivityLifecycleController;
|
||||
import org.briarproject.briar.android.forum.ForumModule;
|
||||
import org.briarproject.briar.android.fragment.SFDialogFragment;
|
||||
import org.briarproject.briar.android.fragment.ScreenFilterDialogFragment;
|
||||
import org.briarproject.briar.android.widget.TapSafeFrameLayout;
|
||||
import org.briarproject.briar.android.widget.TapSafeFrameLayout.OnTapFilteredListener;
|
||||
import org.briarproject.briar.api.android.ScreenFilterMonitor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -23,21 +29,23 @@ import java.util.Set;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
|
||||
import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
|
||||
import static android.view.inputmethod.InputMethodManager.SHOW_IMPLICIT;
|
||||
import static org.briarproject.briar.android.TestingConstants.PREVENT_SCREENSHOTS;
|
||||
|
||||
public abstract class BaseActivity extends AppCompatActivity
|
||||
implements DestroyableContext {
|
||||
implements DestroyableContext, OnTapFilteredListener {
|
||||
|
||||
@Inject
|
||||
protected ScreenFilterMonitor screenFilterMonitor;
|
||||
|
||||
protected ActivityComponent activityComponent;
|
||||
|
||||
private final List<ActivityLifecycleController> lifecycleControllers =
|
||||
new ArrayList<>();
|
||||
private boolean destroyed = false;
|
||||
|
||||
@Inject
|
||||
protected ScreenFilterMonitor screenFilterMonitor;
|
||||
private SFDialogFragment dialogFrag;
|
||||
private ScreenFilterDialogFragment dialogFrag;
|
||||
|
||||
public abstract void injectActivity(ActivityComponent component);
|
||||
|
||||
@@ -65,7 +73,6 @@ public abstract class BaseActivity extends AppCompatActivity
|
||||
for (ActivityLifecycleController alc : lifecycleControllers) {
|
||||
alc.onActivityCreate(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public ActivityComponent getActivityComponent() {
|
||||
@@ -97,12 +104,6 @@ public abstract class BaseActivity extends AppCompatActivity
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostResume() {
|
||||
super.onPostResume();
|
||||
showNewScreenFilterWarning();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
@@ -112,18 +113,18 @@ public abstract class BaseActivity extends AppCompatActivity
|
||||
}
|
||||
}
|
||||
|
||||
protected void showNewScreenFilterWarning() {
|
||||
final Set<String> apps = screenFilterMonitor.getApps();
|
||||
if (apps.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
dialogFrag = SFDialogFragment.newInstance(new ArrayList<>(apps));
|
||||
protected void showScreenFilterWarning() {
|
||||
if (dialogFrag != null && dialogFrag.isVisible()) return;
|
||||
Set<String> apps = screenFilterMonitor.getApps();
|
||||
if (apps.isEmpty()) return;
|
||||
dialogFrag =
|
||||
ScreenFilterDialogFragment.newInstance(new ArrayList<>(apps));
|
||||
dialogFrag.setCancelable(false);
|
||||
dialogFrag.show(getSupportFragmentManager(), "SFDialog");
|
||||
dialogFrag.show(getSupportFragmentManager(), dialogFrag.getTag());
|
||||
}
|
||||
|
||||
public void rememberShownApps(ArrayList<String> s, boolean permanent) {
|
||||
screenFilterMonitor.storeAppsAsShown(s, permanent);
|
||||
public void rememberShownApps(ArrayList<String> s) {
|
||||
screenFilterMonitor.storeAppsAsShown(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -161,4 +162,70 @@ public abstract class BaseActivity extends AppCompatActivity
|
||||
supportFinishAfterTransition();
|
||||
}
|
||||
|
||||
/*
|
||||
* Wraps the given view in a wrapper that notifies this activity when an
|
||||
* obscured touch has been filtered, and returns the wrapper.
|
||||
*/
|
||||
private View makeTapSafeWrapper(View v) {
|
||||
TapSafeFrameLayout wrapper = new TapSafeFrameLayout(this);
|
||||
wrapper.setLayoutParams(new LayoutParams(MATCH_PARENT, MATCH_PARENT));
|
||||
wrapper.setOnTapFilteredListener(this);
|
||||
wrapper.addView(v);
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
/*
|
||||
* Finds the AppCompat toolbar, if any, and configures it to filter
|
||||
* obscured touches. If a custom toolbar is used, it will be part of the
|
||||
* content view and thus protected by the wrapper. But the default toolbar
|
||||
* is outside the wrapper.
|
||||
*/
|
||||
private void protectToolbar() {
|
||||
View decorView = getWindow().getDecorView();
|
||||
if (decorView instanceof ViewGroup) {
|
||||
Toolbar toolbar = findToolbar((ViewGroup) decorView);
|
||||
if (toolbar != null) toolbar.setFilterTouchesWhenObscured(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Toolbar findToolbar(ViewGroup vg) {
|
||||
for (int i = 0, len = vg.getChildCount(); i < len; i++) {
|
||||
View child = vg.getChildAt(i);
|
||||
if (child instanceof Toolbar) return (Toolbar) child;
|
||||
if (child instanceof ViewGroup) {
|
||||
Toolbar toolbar = findToolbar((ViewGroup) child);
|
||||
if (toolbar != null) return toolbar;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setContentView(@LayoutRes int layoutRes) {
|
||||
setContentView(getLayoutInflater().inflate(layoutRes, null));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setContentView(View v) {
|
||||
super.setContentView(makeTapSafeWrapper(v));
|
||||
protectToolbar();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setContentView(View v, LayoutParams layoutParams) {
|
||||
super.setContentView(makeTapSafeWrapper(v), layoutParams);
|
||||
protectToolbar();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addContentView(View v, LayoutParams layoutParams) {
|
||||
super.addContentView(makeTapSafeWrapper(v), layoutParams);
|
||||
protectToolbar();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTapFiltered() {
|
||||
showScreenFilterWarning();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,10 +22,11 @@ import javax.annotation.Nullable;
|
||||
|
||||
@MethodsNotNullByDefault
|
||||
@ParametersNotNullByDefault
|
||||
public class SFDialogFragment extends DialogFragment {
|
||||
public class ScreenFilterDialogFragment extends DialogFragment {
|
||||
|
||||
public static SFDialogFragment newInstance(ArrayList<String> apps) {
|
||||
SFDialogFragment frag = new SFDialogFragment();
|
||||
public static ScreenFilterDialogFragment newInstance(
|
||||
ArrayList<String> apps) {
|
||||
ScreenFilterDialogFragment frag = new ScreenFilterDialogFragment();
|
||||
Bundle args = new Bundle();
|
||||
args.putStringArrayList("apps", apps);
|
||||
frag.setArguments(args);
|
||||
@@ -34,31 +35,25 @@ public class SFDialogFragment extends DialogFragment {
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
|
||||
AlertDialog.Builder builder =
|
||||
new AlertDialog.Builder(
|
||||
getActivity(),
|
||||
R.style.BriarDialogThemeNoFilter);
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity(),
|
||||
R.style.BriarDialogThemeNoFilter);
|
||||
builder.setTitle(R.string.screen_filter_title);
|
||||
LayoutInflater li = getActivity().getLayoutInflater();
|
||||
//Pass null here because it's an AlertDialog
|
||||
View v =
|
||||
li.inflate(R.layout.alert_dialog_checkbox, null,
|
||||
false);
|
||||
// Pass null here because it's an AlertDialog
|
||||
View v = li.inflate(R.layout.alert_dialog_checkbox, null, false);
|
||||
TextView t = (TextView) v.findViewById(R.id.alert_dialog_text);
|
||||
final ArrayList<String> apps =
|
||||
getArguments().getStringArrayList("apps");
|
||||
t.setText(getString(R.string.screen_filter_body, TextUtils
|
||||
.join("\n", apps)));
|
||||
final CheckBox cb =
|
||||
(CheckBox) v.findViewById(
|
||||
R.id.checkBox_screen_filter_reminder);
|
||||
final CheckBox cb = (CheckBox) v.findViewById(
|
||||
R.id.checkbox_dont_show_again);
|
||||
builder.setNeutralButton(R.string.continue_button,
|
||||
new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog,
|
||||
int which) {
|
||||
((BaseActivity) getActivity())
|
||||
.rememberShownApps(apps, cb.isChecked());
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
if (cb.isChecked())
|
||||
((BaseActivity) getActivity()).rememberShownApps(apps);
|
||||
}
|
||||
});
|
||||
builder.setView(v);
|
||||
@@ -84,7 +84,8 @@ public class SplashScreenActivity extends BaseActivity {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void showNewScreenFilterWarning() {
|
||||
protected void showScreenFilterWarning() {
|
||||
// Ignore touches until the next activity is shown
|
||||
}
|
||||
|
||||
private void enableStrictMode() {
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
package org.briarproject.briar.android.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.AttrRes;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static android.view.MotionEvent.FLAG_WINDOW_IS_OBSCURED;
|
||||
|
||||
@NotNullByDefault
|
||||
public class TapSafeFrameLayout extends FrameLayout {
|
||||
|
||||
@Nullable
|
||||
private OnTapFilteredListener listener;
|
||||
|
||||
public TapSafeFrameLayout(Context context) {
|
||||
super(context);
|
||||
setFilterTouchesWhenObscured(false);
|
||||
}
|
||||
|
||||
public TapSafeFrameLayout(Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
setFilterTouchesWhenObscured(false);
|
||||
}
|
||||
|
||||
public TapSafeFrameLayout(Context context, @Nullable AttributeSet attrs,
|
||||
@AttrRes int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
setFilterTouchesWhenObscured(false);
|
||||
}
|
||||
|
||||
public void setOnTapFilteredListener(OnTapFilteredListener listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onFilterTouchEventForSecurity(MotionEvent e) {
|
||||
boolean filter = (e.getFlags() & FLAG_WINDOW_IS_OBSCURED) != 0;
|
||||
if (filter && listener != null) listener.onTapFiltered();
|
||||
return !filter;
|
||||
}
|
||||
|
||||
public interface OnTapFilteredListener {
|
||||
void onTapFiltered();
|
||||
}
|
||||
}
|
||||
@@ -11,5 +11,5 @@ public interface ScreenFilterMonitor {
|
||||
Set<String> getApps();
|
||||
|
||||
@UiThread
|
||||
void storeAppsAsShown(Collection<String> s, boolean persistent);
|
||||
void storeAppsAsShown(Collection<String> shown);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user