[Android]アプリでスクリーンショットを無効にする

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

Android 4.0 から(Volume down + Power)でスクリーンキャプチャが取れるようになりましたが、この機能を無効にすることができます。 現状スクリーンショットを撮れるものを、わざわざ撮れないようにすることはあまりないかもしれませんが、業務で調べた時に情報が少なく苦労したのでご紹介します。

スクリーンショットを無効にする

無効にしたいActivityで

Window window = getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_SECURE);

とすればスクリーンショットは無効にできます。 (無効な箇所でスクリーンショットを撮ろうとした時の挙動は異なります。Toastにエラーメッセージが表示されたり、ステータスバーに表示されたりします。)

指定のFragmentのみ無効にする

Fragment毎に、このFragmentでは無効にして、こっちのFragmentでは有効にしたいといった仕様になると少し工夫が必要になります。 Fragment内で

getActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE)

とすればLayoutParamsの値は変更できるのですが、変更が反映されるのがActivityのライフサイクルに依存しているので即時反映はされません。

そこで

WindowManager mWindowManager; 
FrameLayout mOverlapView;
WindowManager.LayoutParams mParams;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    mParams = new WindowManager.LayoutParams(
            WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
            WindowManager.LayoutParams.FLAG_SECURE,
            PixelFormat.TRANSLUCENT);
    mWindowManager = (WindowManager) getActivity().getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
    mOverlapView = new FrameLayout(getActivity());
    mWindowManager.addView(mOverlapView, mParams);
}
@Override
    public void onHiddenChanged(boolean hidden) {
        super.onHiddenChanged(hidden);
        if (hidden) {
            mWindowManager.removeView(mOverlapView);
        } else {
            mWindowManager.addView(mOverlapView, mParams);
        }
    }

このように書くと、Fragmentの生成時にonCreateでスクリーンショットを無効にします。 そして,onHiddenChangedでFragmentが表示・非表示の切り替えのタイミングでスクリーンショットを無効にするwindowをadd・ removeと切り替えをすれば、Fragmentの切り替えと同時にスクリーンショットの無効・有効の切り替えができます。

最後に

あまり使い所は思い浮かびませんが、今後何かスクリーンショットを悪用されるようなケースがあれば必要になる技術だと思います。