Optionally prevent taking screenshots

Maximilian Weiler created

- Add setting to prevent screenshots
- Enforce using FLAG_SECURE in onResume for each activity

Change summary

src/main/java/eu/siacs/conversations/ui/AboutActivity.java        |  8 
src/main/java/eu/siacs/conversations/ui/ConversationActivity.java |  9 
src/main/java/eu/siacs/conversations/ui/LocationActivity.java     |  3 
src/main/java/eu/siacs/conversations/ui/MemorizingActivity.java   |  4 
src/main/java/eu/siacs/conversations/ui/RecordingActivity.java    |  8 
src/main/java/eu/siacs/conversations/ui/ScanActivity.java         |  3 
src/main/java/eu/siacs/conversations/ui/SettingsActivity.java     | 10 
src/main/java/eu/siacs/conversations/ui/XmppActivity.java         |  4 
src/main/java/eu/siacs/conversations/ui/util/SettingsUtils.java   | 20 +
src/main/res/values/defaults.xml                                  |  1 
src/main/res/values/strings.xml                                   |  3 
src/main/res/xml/preferences.xml                                  |  7 
12 files changed, 79 insertions(+), 1 deletion(-)

Detailed changes

src/main/java/eu/siacs/conversations/ui/AboutActivity.java 🔗

@@ -1,16 +1,24 @@
 package eu.siacs.conversations.ui;
 
 import android.os.Bundle;
+import android.preference.PreferenceManager;
 
 import androidx.appcompat.app.AppCompatActivity;
 
 import eu.siacs.conversations.R;
+import eu.siacs.conversations.ui.util.SettingsUtils;
 import eu.siacs.conversations.utils.ThemeHelper;
 
 import static eu.siacs.conversations.ui.XmppActivity.configureActionBar;
 
 public class AboutActivity extends AppCompatActivity {
 
+    @Override
+    protected void onResume(){
+        super.onResume();
+        SettingsUtils.applyScreenshotPreventionSetting(this);
+    }
+
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);

src/main/java/eu/siacs/conversations/ui/ConversationActivity.java 🔗

@@ -2,10 +2,13 @@ package eu.siacs.conversations.ui;
 
 import android.content.Intent;
 import android.os.Bundle;
+import android.preference.PreferenceManager;
 
 import androidx.annotation.Nullable;
 import androidx.appcompat.app.AppCompatActivity;
 
+import eu.siacs.conversations.ui.util.SettingsUtils;
+
 public class ConversationActivity extends AppCompatActivity {
 
 	@Override
@@ -14,4 +17,10 @@ public class ConversationActivity extends AppCompatActivity {
 		startActivity(new Intent(this, ConversationsActivity.class));
 		finish();
 	}
+
+	@Override
+	protected void onResume(){
+		super.onResume();
+		SettingsUtils.applyScreenshotPreventionSetting(this);
+	}
 }

src/main/java/eu/siacs/conversations/ui/LocationActivity.java 🔗

@@ -39,6 +39,7 @@ import eu.siacs.conversations.services.QuickConversationsService;
 import eu.siacs.conversations.ui.util.LocationHelper;
 import eu.siacs.conversations.ui.widget.Marker;
 import eu.siacs.conversations.ui.widget.MyLocation;
+import eu.siacs.conversations.ui.util.SettingsUtils;
 import eu.siacs.conversations.utils.ThemeHelper;
 
 public abstract class LocationActivity extends ActionBarActivity implements LocationListener {
@@ -68,6 +69,7 @@ public abstract class LocationActivity extends ActionBarActivity implements Loca
 		}
 	}
 
+
 	protected void updateLocationMarkers() {
 		clearMarkers();
 	}
@@ -222,6 +224,7 @@ public abstract class LocationActivity extends ActionBarActivity implements Loca
 	@Override
 	protected void onResume() {
 		super.onResume();
+		SettingsUtils.applyScreenshotPreventionSetting(this);
 		Configuration.getInstance().load(this, getPreferences());
 		map.onResume();
 		this.setMyLoc(null);

src/main/java/eu/siacs/conversations/ui/MemorizingActivity.java 🔗

@@ -29,6 +29,7 @@ import android.content.DialogInterface.OnCancelListener;
 import android.content.DialogInterface.OnClickListener;
 import android.content.Intent;
 import android.os.Bundle;
+import android.preference.PreferenceManager;
 
 import androidx.appcompat.app.AlertDialog;
 import androidx.appcompat.app.AppCompatActivity;
@@ -39,6 +40,7 @@ import java.util.logging.Logger;
 import eu.siacs.conversations.R;
 import eu.siacs.conversations.entities.MTMDecision;
 import eu.siacs.conversations.services.MemorizingTrustManager;
+import eu.siacs.conversations.ui.util.SettingsUtils;
 import eu.siacs.conversations.utils.ThemeHelper;
 
 public class MemorizingActivity extends AppCompatActivity implements OnClickListener, OnCancelListener {
@@ -61,6 +63,8 @@ public class MemorizingActivity extends AppCompatActivity implements OnClickList
 	@Override
 	public void onResume() {
 		super.onResume();
+		SettingsUtils.applyScreenshotPreventionSetting(this);
+
 		Intent i = getIntent();
 		decisionId = i.getIntExtra(MemorizingTrustManager.DECISION_INTENT_ID, MTMDecision.DECISION_INVALID);
 		int titleId = i.getIntExtra(MemorizingTrustManager.DECISION_TITLE_ID, R.string.mtm_accept_cert);

src/main/java/eu/siacs/conversations/ui/RecordingActivity.java 🔗

@@ -9,6 +9,7 @@ import android.os.Bundle;
 import android.os.FileObserver;
 import android.os.Handler;
 import android.os.SystemClock;
+import android.preference.PreferenceManager;
 import android.util.Log;
 import android.view.View;
 import android.view.WindowManager;
@@ -28,6 +29,7 @@ import eu.siacs.conversations.Config;
 import eu.siacs.conversations.R;
 import eu.siacs.conversations.databinding.ActivityRecordingBinding;
 import eu.siacs.conversations.persistance.FileBackend;
+import eu.siacs.conversations.ui.util.SettingsUtils;
 import eu.siacs.conversations.utils.ThemeHelper;
 import eu.siacs.conversations.utils.TimeFrameUtils;
 
@@ -66,6 +68,12 @@ public class RecordingActivity extends Activity implements View.OnClickListener
         getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
     }
 
+    @Override
+    protected void onResume(){
+        super.onResume();
+        SettingsUtils.applyScreenshotPreventionSetting(this);
+    }
+
     @Override
     protected void onStart() {
         super.onStart();

src/main/java/eu/siacs/conversations/ui/ScanActivity.java 🔗

@@ -33,6 +33,7 @@ import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Process;
 import android.os.Vibrator;
+import android.preference.PreferenceManager;
 import android.util.Log;
 import android.view.KeyEvent;
 import android.view.Surface;
@@ -61,6 +62,7 @@ import eu.siacs.conversations.Config;
 import eu.siacs.conversations.R;
 import eu.siacs.conversations.ui.service.CameraManager;
 import eu.siacs.conversations.ui.widget.ScannerView;
+import eu.siacs.conversations.ui.util.SettingsUtils;
 
 /**
  * @author Andreas Schildbach
@@ -181,6 +183,7 @@ public final class ScanActivity extends Activity implements SurfaceTextureListen
 	@Override
 	protected void onResume() {
 		super.onResume();
+		SettingsUtils.applyScreenshotPreventionSetting(this);
 		maybeOpenCamera();
 	}
 

src/main/java/eu/siacs/conversations/ui/SettingsActivity.java 🔗

@@ -40,6 +40,7 @@ import eu.siacs.conversations.services.MemorizingTrustManager;
 import eu.siacs.conversations.services.QuickConversationsService;
 import eu.siacs.conversations.ui.util.StyledAttributes;
 import eu.siacs.conversations.utils.GeoHelper;
+import eu.siacs.conversations.ui.util.SettingsUtils;
 import eu.siacs.conversations.utils.TimeFrameUtils;
 import eu.siacs.conversations.xmpp.Jid;
 
@@ -57,8 +58,10 @@ public class SettingsActivity extends XmppActivity implements
 	public static final String THEME = "theme";
 	public static final String SHOW_DYNAMIC_TAGS = "show_dynamic_tags";
 	public static final String OMEMO_SETTING = "omemo";
+	public static final String PREVENT_SCREENSHOTS = "prevent_screenshots";
 
 	public static final int REQUEST_CREATE_BACKUP = 0xbf8701;
+
 	private SettingsFragment mSettingsFragment;
 
 	@Override
@@ -393,8 +396,15 @@ public class SettingsActivity extends XmppActivity implements
 			if (this.mTheme != theme) {
 				recreate();
 			}
+		} else if(name.equals(PREVENT_SCREENSHOTS)){
+			SettingsUtils.applyScreenshotPreventionSetting(this);
 		}
+	}
 
+	@Override
+	public void onResume(){
+		super.onResume();
+		SettingsUtils.applyScreenshotPreventionSetting(this);
 	}
 
 	@Override

src/main/java/eu/siacs/conversations/ui/XmppActivity.java 🔗

@@ -80,6 +80,7 @@ import eu.siacs.conversations.ui.util.PresenceSelector;
 import eu.siacs.conversations.ui.util.SoftKeyboardUtils;
 import eu.siacs.conversations.utils.AccountUtils;
 import eu.siacs.conversations.utils.ExceptionHelper;
+import eu.siacs.conversations.ui.util.SettingsUtils;
 import eu.siacs.conversations.utils.ThemeHelper;
 import eu.siacs.conversations.xmpp.Jid;
 import eu.siacs.conversations.xmpp.OnKeyStatusUpdated;
@@ -819,8 +820,9 @@ public abstract class XmppActivity extends ActionBarActivity {
     }
 
     @Override
-    public void onResume() {
+    protected void onResume(){
         super.onResume();
+        SettingsUtils.applyScreenshotPreventionSetting(this);
     }
 
     protected int findTheme() {

src/main/java/eu/siacs/conversations/ui/util/SettingsUtils.java 🔗

@@ -0,0 +1,20 @@
+package eu.siacs.conversations.ui.util;
+
+import android.app.Activity;
+import android.content.SharedPreferences;
+import android.preference.PreferenceManager;
+import android.view.Window;
+import android.view.WindowManager;
+
+public class SettingsUtils {
+    public static void applyScreenshotPreventionSetting(Activity activity){
+        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(activity);
+        boolean preventScreenshots = preferences.getBoolean("prevent_screenshots", false);
+        Window activityWindow = activity.getWindow();
+        if(preventScreenshots){
+            activityWindow.addFlags(WindowManager.LayoutParams.FLAG_SECURE);
+        } else {
+            activityWindow.clearFlags(WindowManager.LayoutParams.FLAG_SECURE);
+        }
+    }
+}

src/main/res/values/defaults.xml 🔗

@@ -44,4 +44,5 @@
     <bool name="start_searching">false</bool>
     <string name="video_compression">360</string>
     <string name="default_channel_discovery">JABBER_NETWORK</string>
+    <bool name="prevent_screenshots">false</bool>
 </resources>

src/main/res/values/strings.xml 🔗

@@ -130,6 +130,8 @@
     <string name="pref_never_send_crash_summary">By sending in stack traces you are helping the development</string>
     <string name="pref_confirm_messages">Confirm Messages</string>
     <string name="pref_confirm_messages_summary">Let your contacts know when you have received and read their messages</string>
+    <string name="pref_prevent_screenshots">Prevent Screenshots</string>
+    <string name="pref_prevent_screenshots_summary">Prevent taking screenshots of this app and hide its content in the app switcher</string>
     <string name="pref_ui_options">UI</string>
     <string name="openpgp_error">OpenKeychain produced an error.</string>
     <string name="bad_key_for_encryption">Bad key for encryption.</string>
@@ -966,4 +968,5 @@
     <string name="backup_started_message">The backup has been started. You’ll get a notification once it has been completed.</string>
     <string name="unable_to_enable_video">Unable to enable video.</string>
     <string name="plain_text_document">Plain text document</string>
+
 </resources>

src/main/res/xml/preferences.xml 🔗

@@ -32,6 +32,13 @@
             android:key="last_activity"
             android:summary="@string/pref_broadcast_last_activity_summary"
             android:title="@string/pref_broadcast_last_activity" />
+
+        <CheckBoxPreference
+            android:defaultValue="@bool/prevent_screenshots"
+            android:key="prevent_screenshots"
+            android:summary="@string/pref_prevent_screenshots_summary"
+            android:title="@string/pref_prevent_screenshots" />
+
         <ListPreference
             android:defaultValue="@string/omemo_setting_default"
             android:entries="@array/omemo_setting_entries"