Mobile Development 24 min read

How to Build a Custom Android Lock Screen with Swipe, Immersive Mode, and Fingerprint Unlock

This article explains why a custom lock screen is useful, describes the core principles of implementing one on Android, and provides step‑by‑step code for broadcast registration, activity configuration, key event blocking, swipe‑to‑unlock logic, immersive and translucent UI flags, and fingerprint integration.

Tencent TDS Service
Tencent TDS Service
Tencent TDS Service
How to Build a Custom Android Lock Screen with Swipe, Immersive Mode, and Fingerprint Unlock

1. Why a Custom Lock Screen Is Needed

Lock screens have existed since the monochrome‑screen era and remain important today, especially with touch devices. Their core purposes are privacy protection, preventing accidental actions, and saving power without closing system apps. While stock lock screens satisfy these needs, a custom lock screen can streamline user interactions, such as changing music tracks with fewer steps and displaying lyrics.

2. Basic Principles of a Custom Lock Screen

Implementing a custom lock screen is complex because Android provides many ways to prevent non‑system lock screens. The typical approach is to start a Service when the app launches, listen for the Intent.ACTION_SCREEN_OFF broadcast, and launch a lock‑screen Activity on top of the system UI when the screen turns off. The activity can hide the system lock screen (except when a password is set).

Custom lock screen flow diagram
Custom lock screen flow diagram

1. Broadcast Registration

The service must register the SCREEN_OFF broadcast dynamically; static registration in AndroidManifest.xml will not receive it. Example registration code:

IntentFilter mScreenOffFilter = new IntentFilter();
mScreenOffFilter.addAction(Intent.ACTION_SCREEN_OFF);
registerReceiver(mScreenOffReceiver, mScreenOffFilter);

private BroadcastReceiver mScreenOffReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
            Intent lockIntent = new Intent(context, LockScreenActivity.class);
            lockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
            startActivity(lockIntent);
        }
    }
};

When starting the activity from a service, FLAG_ACTIVITY_NEW_TASK is required to avoid the "Calling startActivity() from outside of an Activity" exception. Adding FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS is optional.

2. Activity Configuration

The lock‑screen activity must be configured to appear over the system lock screen. The older KeyguardManager method is deprecated; the modern approach uses window flags:

getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);

Declare the permission in the manifest:

<uses-permission android:name="android.permission.DISABLE_KEYGUARD"/>

3. Blocking Physical Keys

To make the custom lock screen robust, block Back and Menu keys by overriding onKeyDown:

public boolean onKeyDown(int keyCode, KeyEvent event) {
    switch (keyCode) {
        case KeyEvent.KEYCODE_BACK:
        case KeyEvent.KEYCODE_MENU:
            return true; // consume the event
    }
    return super.onKeyDown(keyCode, event);
}

Home and Recent keys are handled at the framework level and are generally left untouched.

4. Swipe‑to‑Unlock Logic

A custom UnderView placed beneath the main lock‑screen view intercepts touch events. When the user swipes horizontally, the view follows the finger; releasing the finger triggers an animation that either slides the view off‑screen (unlock) or returns it to the start position.

UnderView swipe handling
UnderView swipe handling
public boolean onTouchEvent(MotionEvent event) {
    final int action = event.getAction();
    final float x = event.getX();
    switch (action) {
        case MotionEvent.ACTION_DOWN:
            mStartX = x;
            onAnimationEnd();
            break;
        case MotionEvent.ACTION_MOVE:
            handleMoveView(x);
            break;
        case MotionEvent.ACTION_UP:
        case MotionEvent.ACTION_CANCEL:
            doTriggerEvent(x);
            break;
    }
    return true;
}

private void handleMoveView(float x) {
    float moveX = x - mStartX;
    if (moveX < 0) moveX = 0;
    mMoveView.setTranslationX(moveX);
    float width = (float) mWidth;
    if (getBackground() != null) {
        getBackground().setAlpha((int) ((width - mMoveView.getTranslationX()) / width * 200));
    }
}

private void doTriggerEvent(float x) {
    float moveX = x - mStartX;
    if (moveX > mWidth * 0.4f) {
        moveMoveView(mWidth - mMoveView.getLeft(), true);
    } else {
        moveMoveView(-mMoveView.getLeft(), false);
    }
}

private void moveMoveView(float to, boolean exit) {
    ObjectAnimator animator = ObjectAnimator.ofFloat(mMoveView, "translationX", to);
    animator.addUpdateListener(animation -> {
        if (getBackground() != null) {
            getBackground().setAlpha((int) (((float) mWidth - mMoveView.getTranslationX()) / mWidth * 200));
        }
    });
    animator.setDuration(250).start();
    if (exit) {
        animator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                mainHandler.obtainMessage(LockScreenActivity.MSG_LAUNCH_HOME).sendToTarget();
                super.onAnimationEnd(animation);
            }
        });
    }
}

3. Transparent Bars and Immersive Mode

Immersive mode hides both the status bar and navigation bar while allowing a short swipe to reveal them temporarily. The relevant flags (available from Android 4.4) are:

View.SYSTEM_UI_FLAG_IMMERSIVE
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
View.SYSTEM_UI_FLAG_FULLSCREEN
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION

Apply them in onCreate and again in onWindowFocusChanged to ensure they stay active:

getWindow().getDecorView().setSystemUiVisibility(
    View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
    View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
    View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY |
    View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
    View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);

@Override
public void onWindowFocusChanged(boolean hasFocus) {
    super.onWindowFocusChanged(hasFocus);
    if (hasFocus) {
        getWindow().getDecorView().setSystemUiVisibility(
            View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
            View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
            View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY |
            View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
            View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
    }
}

For transparent status and navigation bars, use the following code depending on the Android version:

// Android 4.4 (KitKat) – translucent status bar
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
    Window window = getWindow();
    window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}

// Android 5.0 (Lollipop) and above – fully transparent status bar
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    Window window = getWindow();
    window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
    window.getDecorView().setSystemUiVisibility(
        View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
    window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
    window.setStatusBarColor(0); // transparent
}
Immersive mode states
Immersive mode states

4. Fingerprint Unlock Integration

When a device with fingerprint authentication unlocks the system lock screen, the custom lock screen may remain visible. To handle this, listen for Intent.ACTION_USER_PRESENT and finish the custom lock‑screen activity only when a lock‑screen password is set.

if (intent.getAction().equals(Intent.ACTION_USER_PRESENT)) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
        if (km.isKeyguardSecure()) {
            Intent i = new Intent(NOTIFY_USER_PRESENT);
            context.sendBroadcast(i);
        }
    }
}

Additionally, embed fingerprint authentication directly in the lock‑screen activity for devices where the system fingerprint UI is unavailable:

private void startFingerPrintListening() {
    if (!isFingerprintAuthAvailable()) return;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        if (checkSelfPermission(Manifest.permission.USE_FINGERPRINT) == PackageManager.PERMISSION_GRANTED) {
            mFingerprintManager.authenticate(null, mCancellationSignal, 0, new FingerprintManager.AuthenticationCallback() {
                @Override public void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result) { finish(); }
                @Override public void onAuthenticationError(int errorCode, CharSequence errString) { super.onAuthenticationError(errorCode, errString); }
                @Override public void onAuthenticationFailed() { super.onAuthenticationFailed(); }
            }, null);
        }
    }
}

public boolean isFingerprintAuthAvailable() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        mKeyguardManager = (KeyguardManager) getSystemService(Activity.KEYGUARD_SERVICE);
        if (!mKeyguardManager.isKeyguardSecure()) return false;
        if (checkSelfPermission(Manifest.permission.USE_FINGERPRINT) == PackageManager.PERMISSION_GRANTED) {
            mFingerprintManager = (FingerprintManager) getSystemService(Activity.FINGERPRINT_SERVICE);
            mCancellationSignal = new CancellationSignal();
            return mFingerprintManager.isHardwareDetected() && mFingerprintManager.hasEnrolledFingerprints();
        }
    }
    return false;
}

Declare the fingerprint permission in the manifest:

<uses-permission android:name="android.permission.USE_FINGERPRINT"/>

5. Summary

Creating a custom Android lock screen involves starting a service that reacts to screen‑off events, launching an activity with appropriate window flags, handling key events, implementing swipe‑to‑unlock logic, combining immersive and translucent UI modes, and optionally integrating fingerprint authentication. Paying attention to these technical details results in a smooth, user‑friendly lock‑screen experience.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

AndroidServiceFingerprintImmersive ModeLock ScreenCustom UI
Tencent TDS Service
Written by

Tencent TDS Service

TDS Service offers client and web front‑end developers and operators an intelligent low‑code platform, cross‑platform development framework, universal release platform, runtime container engine, monitoring and analysis platform, and a security‑privacy compliance suite.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.