You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android平台下如何防范部分Tapjacking(界面劫持)?

Handling Partial Obscuration for Tapjacking Protection in Android

Hey there, I’ve run into this exact issue before when hardening apps against tapjacking—filterTouchesWhenObscured="true" works great for full window obscuration, but it leaves partial overlaps unaddressed. Here are some practical, actionable solutions I’ve implemented successfully:

1. Listen for WindowInsets to Detect Partial Obscuration (API 30+)

Starting with Android 11 (API level 30), the system exposes FLAG_WINDOW_IS_PARTIALLY_OBSCURED to signal when your app’s window is covered by another element (like a floating overlay or permission dialog). You can leverage this by registering a WindowInsetsListener on your root view or specific sensitive components:

// In your Activity or Fragment
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    val rootView = findViewById<View>(android.R.id.content)
    
    rootView.setOnApplyWindowInsetsListener { view, insets ->
        val window = (view.context as Activity).window
        val isPartiallyObscured = window.attributes.flags and WindowManager.LayoutParams.FLAG_WINDOW_IS_PARTIALLY_OBSCURED != 0
        
        if (isPartiallyObscured) {
            // Disable touch for high-risk views
            findViewById<Button>(R.id.payment_button).isEnabled = false
            // Or intercept all touches at the root level
            rootView.setOnTouchListener { _, _ -> true }
        } else {
            // Restore normal functionality
            findViewById<Button>(R.id.payment_button).isEnabled = true
            rootView.setOnTouchListener(null)
        }
        
        insets
    }
}

This lets you dynamically toggle interactivity based on whether any part of your window is obscured.

2. Build a Reusable Tapjack-Safe Layout

For a modular solution, wrap sensitive UI in a custom ViewGroup that automatically intercepts touches when partial obscuration is detected:

public class TapjackProtectedLayout extends LinearLayout {

    public TapjackProtectedLayout(Context context) {
        super(context);
    }

    public TapjackProtectedLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        // Check partial obscuration status (API 30+)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            Window window = ((Activity) getContext()).getWindow();
            if ((window.getAttributes().flags & WindowManager.LayoutParams.FLAG_WINDOW_IS_PARTIALLY_OBSCURED) != 0) {
                // Block all touches to prevent tapjacking
                return true;
            }
        }
        // Fall back to default behavior for older versions or no obscuration
        return super.onInterceptTouchEvent(ev);
    }
}

Use it in your layout XML like any standard container:

<com.yourpackage.TapjackProtectedLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <!-- Sensitive elements (payment buttons, login forms, etc.) -->
    <Button
        android:id="@+id/sensitive_action_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Complete Transaction"/>

</com.yourpackage.TapjackProtectedLayout>

3. Global Protection via a Base Activity

To apply this safeguard across your entire app, add the obscuration check to a base activity that all your activities extend:

open class BaseTapjackSafeActivity : AppCompatActivity() {

    override fun onResume() {
        super.onResume()
        checkPartialObscuration()
        // Re-check when the activity regains focus (overlays might be added/removed)
        window.decorView.viewTreeObserver.addOnWindowFocusChangeListener { hasFocus ->
            if (hasFocus) checkPartialObscuration()
        }
    }

    private fun checkPartialObscuration() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            val isPartiallyObscured = window.attributes.flags and WindowManager.LayoutParams.FLAG_WINDOW_IS_PARTIALLY_OBSCURED != 0
            val rootView = window.decorView.rootView
            rootView.isEnabled = !isPartiallyObscured
        }
    }
}

A quick note: Google doesn’t provide a built-in XML attribute for partial obscuration (unlike filterTouchesWhenObscured), so these manual checks are the standard approach. For devices running Android 10 or lower, you’ll have to rely on filterTouchesWhenObscured for full obscuration protection, since partial obscuration flags weren’t available yet.

内容的提问来源于stack exchange,提问作者Jaime Alcántara Arnela

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 07:00:44