需要从 Android“概览屏幕”中隐藏程序内容
Posted
技术标签:
【中文标题】需要从 Android“概览屏幕”中隐藏程序内容【英文标题】:Need to hide content of program from Android "Overview Screen" 【发布时间】:2014-12-04 01:33:33 【问题描述】:我正在为一位注重安全的雇主开发一款 android 应用。他担心出现在Overview Screen(又名最近任务列表)上的屏幕快照泄露敏感信息,并希望我在系统拍摄该照片之前放置程序的启动屏幕。不幸的是,我还没有找到任何方法。
我尝试过的事情:
在onPause
函数中增加启动画面的视图。 (无效,即使使用 bringToFront
和 setVisibility(View.VISIBLE)
。)
在onCreate
中膨胀启动屏幕的视图并在onPause
中使用bringToFront
。 (同样,没有效果。)
在onPause
中调用setVisible(false)
。 (似乎几乎可以工作,因为当从程序切换时屏幕会瞬间闪烁到黑色,但显然在快照之前系统再次使其可见。)
在onPause
中视图的最顶部项目上调用setVisibility(View.INVISIBLE)
。 (好像可以,但快照显然是在它生效之前拍摄的。)
我是一名中等成就的 Android 开发人员,但我不禁觉得我缺少一个简单的解决方案。
【问题讨论】:
试试onCreateThumbnail()
,因为我认为这就是这里使用的。或者,use FLAG_SECURE
简单地阻止所有内容(相对于启动屏幕)。
@CommonsWare,完美!如果你能把它变成答案,我会很乐意接受。
【参考方案1】:
就我个人而言,我会go with FLAG_SECURE
,并简单地阻止在任何地方显示这些东西:
public class FlagSecureTestActivity extends Activity
@Override
public void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
getWindow().setFlags(LayoutParams.FLAG_SECURE,
LayoutParams.FLAG_SECURE);
setContentView(R.layout.main);
但是,IIRC,您可以覆盖 onCreateThumbnail()
以提供您自己的图像以用于最近的任务列表。请注意,这可能在 Android 5.0 中发生了变化,因为他们已经彻底检查了最近的任务列表,因此请务必在 5.0 设备或模拟器上测试您的代码。
【讨论】:
不幸的是,onCreateThumbnail
似乎不起作用。它从来没有在这里调用过(Android 4.4 和 5.0),我发现了这个:code.google.com/p/android/issues/detail?id=29370>。 FLAG_SECURE
也有其自身的问题,部分描述如下:***.com/a/11121897/12193>。嗯,保持冷静,继续前进。 ;-)
添加 FLAG_SECURE 并且我的用户无法截屏应用程序。我只想隐藏内容应用程序,我该怎么做。谢谢。
@JackHuynh:抱歉,我不知道“隐藏内容应用”是什么意思。
@CommonsWare,它的脸书信使,当应用程序进入后台时,它有一个掩码来保护应用程序。
@JackHuynh:抱歉,我不知道有什么可靠的方法来实现。【参考方案2】:
这是一个隐藏应用程序内容的解决方案,当应用程序进入后台时,它会用启动屏幕覆盖它。 这不是使用 FLAG_SECURE 技术,我只是覆盖屏幕的 onPause 和 onResume 方法,并修改视图以显示覆盖所有内容的视图。
首先我在一个单独的文件中创建我的初始屏幕作为一个名为 splash_screen_custom 的相对布局,我还在文件中为该相对布局指定了一个 id customSplash。请注意高度设置,我遇到了按钮具有预设高度的问题,因此通过将此封面屏幕设置为高高度,它将覆盖所有按钮(当然,如果您不覆盖按钮,则不需要此设置)。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
android:id="@+id/customSplash"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_
android:layout_
android:background="@color/backgroundColor"
android:elevation="5dp"
>
<ImageView
android:id="@+id/imageView"
android:layout_
android:layout_
android:layout_centerInParent="true"
app:srcCompat="@drawable/yourImage" />
</RelativeLayout>
在这个例子中,我试图覆盖的屏幕是一个相对布局,因此我可以通过我试图覆盖的视图的 addView 和 removeView 方法简单地添加和删除我的启动屏幕。
override fun onPause()
var parentView = findViewById<RelativeLayout>(R.id.parentView)
var splashScreen = layoutInflater.inflate(R.layout.splash_screen_custom, null)
parentView.addView(splashScreen, parentView.width, parentView.height)
super.onPause()
override fun onResume()
var parentView = findViewById<RelativeLayout>(R.id.parentView)
parentView.removeView(findViewById<RelativeLayout>(R.id.customSplash))
super.onResume()
【讨论】:
我后来意识到的小错误......这将导致屏幕转换在转换之间也显示启动屏幕(显然因为 onPause 将被调用)。您可以简单地创建一个标志来禁用特定意图。这不像我希望的那样干净。但是,如果您在将应用程序置于后台时确实需要启动画面,这是我找到的最干净的方式。【参考方案3】:我只想根据@D.Maul 的回答为 react-native android 提供另一个版本:
一些边缘情况的错误:
[1] 对话框正在显示 [2] 打开相机时会显示一个非常快速的 SplashScreen代码
@Override
protected void onPause()
try
// Hide app preview with SplahScreen
FrameLayout parentView = findViewById(android.R.id.content);
if (parentView != null && parentView.findViewById(R.id.splash_activity) == null)
View splashScene = this.getLayoutInflater().inflate(R.layout.splash_activity, null);
parentView.addView(splashScene, parentView.getWidth(), parentView.getHeight());
catch (Exception e)
// do nothing
super.onPause();
@Override
protected void onResume()
try
// Remove SplashScreen
FrameLayout parentView = findViewById(android.R.id.content);
if (parentView != null)
parentView.removeView(this.findViewById(R.id.splash_activity));
catch (Exception e)
// do nothing
super.onResume();
【讨论】:
嗨@tran 这似乎在我的模拟器上大部分时间都可以工作,但在我的物理 OnePlus 8 Pro 上它永远不会工作。我试图删除 onResume 调用以验证启动屏幕是否正在实际呈现,它就是这样。那么这可能是一个时间/性能问题,是在截取屏幕截图和渲染叠加层之间的竞赛。我发现 Android 删除了用于设置缩略图的 API (onCreateThumbnail) 并且没有为它提供其他解决方案,这让我感到沮丧。以上真的对你在物理设备上也有用吗? 嗨,是的,上次我测试它在我的像素 2 上工作。但由于上述边缘情况,我不使用它。我现在使用 FLAG_SECURE 以获得更好的安全性,因为它是由操作系统处理的。例如:getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);
是的,我们目前正在这样做,但我们的用户抱怨无法截屏(我理解他们),我们只是被允许启用此功能,但现在这可能是显示塞子。【参考方案4】:
基于@D.Maul 的回答,但Java 版本,我没有添加视图,而是尝试了这个。它运行良好,但有时最近的快照显示应用内容不知道如何处理它。
private Dialog dialog = null;
@Override
public void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
dialog = new Dialog(this, android.R.style.Theme_Light);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(R.layout.customlaunch);
@Override
protected void onPause()
dialog.show();
super.onPause();
@Override
protected void onResume()
dialog.hide();
super.onResume();
【讨论】:
【参考方案5】:您可以考虑使用ActivityManager.addAppTask(Activity, Intent, ActivityManager.TaskDescription, Bitmap)
启动应用程序任务,而不是启动一个活动,您传入的位图将用作概览/最近屏幕中的缩略图。
此 api 上的文档是 here,但是,它仅在 Lollipop 中可用。
【讨论】:
以上是关于需要从 Android“概览屏幕”中隐藏程序内容的主要内容,如果未能解决你的问题,请参考以下文章
Android 屏幕适配屏幕适配通用解决方案 ② ( 自定义组件解决方案 | 需要解决的问题 : 设计稿坐标数据转为屏幕真实坐标数据 | 实现步骤 )
Android 屏幕适配屏幕适配通用解决方案 ② ( 自定义组件解决方案 | 需要解决的问题 : 设计稿坐标数据转为屏幕真实坐标数据 | 实现步骤 )
Android 屏幕适配屏幕适配基础概念 ① ( Android 与 iOS 屏幕宽高比种类 | 屏幕像素密度 DPI )
Android 屏幕适配屏幕适配通用解决方案 ③ ( 自定义组件解决方案 | 获取设备状态栏高度 | 获取设备屏幕数据 )
Android 屏幕适配屏幕适配通用解决方案 ③ ( 自定义组件解决方案 | 获取设备状态栏高度 | 获取设备屏幕数据 )