Android: Overlay TextView on LockScreen
Asked Answered
H

2

15

Concept

Im trying to overlay a TextView on top of the LockScreen (Similar to how Android Overlays the time).

Note: I dont want to by-pass the lockscreen, but just draw on top of it (without interfering with any of the touch events).

I've tried using the following flags (in onCreate):

getWindow().addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
    getWindow().addFlags(WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY);
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH);
    getWindow().addFlags(PixelFormat.TRANSLUCENT);

And applying the following Theme (to the specific activity):

   <style name="Transparent">
    <item name="android:windowNoTitle">true</item>
    <item name="android:windowContentOverlay">@null</item>
    <item name="android:windowIsTranslucent">true</item>
    <item name="android:windowBackground">@android:color/transparent</item>
    <item name="android:windowActionBar">false</item>
    <item name="android:backgroundDimEnabled">false</item>
 <item name="android:windowIsFloating">true</item>   
</style>

But this draws on TOP of the lockscreen hiding the lockscreen and disabling all touch events.

Edit: activity_overlay.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.coco.MainActivity" >

<TextView
    android:id="@+id/textView1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:textColor="@android:color/white"
    android:layout_alignParentBottom="true"
    android:text="TextView" />

</RelativeLayout>

Manifest declaration of Activity (which inflates overlay_activity.xml)

      <activity
        android:name=".DisplayActivity"
        android:label="@string/app_name"
        android:theme="@style/Transparent" />
Holbrooke answered 10/2, 2016 at 22:33 Comment(6)
Can you show your actual layout file?Outmaneuver
@mcwise Added the layout file. activity_overlay.xml . Also added the manifest declarationHolbrooke
Ive tried all combinations of Theme & Flags but none give the desired overlay. Also tried using the Flags from onCreate and onWindowFocusChangedHolbrooke
perhaps you need a lock screen widget?Franek
Any code that you can share by using what Ive provided?Holbrooke
look into this link #27035702Drobman
M
25

Since you want to display things out of your app activity, you can use a Service and WindowManager for that, the same way how Facebook Messenger and other floating windows apps works ;)

LockScreenTextService.class

import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.PixelFormat;
import android.os.IBinder;
import android.support.v4.content.ContextCompat;
import android.view.Gravity;
import android.view.WindowManager;
import android.widget.TextView;

/**
 * Created on 2/20/2016.
 */
public class LockScreenTextService extends Service {

    private BroadcastReceiver mReceiver;
    private boolean isShowing = false;

    @Override
    public IBinder onBind(Intent intent) {
        // TODO Auto-generated method stub
        return null;
    }

    private WindowManager windowManager;
    private TextView textview;
    WindowManager.LayoutParams params;

    @Override
    public void onCreate() {
        super.onCreate();

        windowManager = (WindowManager)getSystemService(WINDOW_SERVICE);

        //add textview and its properties
        textview = new TextView(this);
        textview.setText("Hello There!");
        textview.setTextColor(ContextCompat.getColor(this, android.R.color.white));
        textview.setTextSize(32f);

        //set parameters for the textview
        params = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                        | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                        | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
                        | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
                PixelFormat.TRANSLUCENT);
        params.gravity = Gravity.BOTTOM;

        //Register receiver for determining screen off and if user is present
        mReceiver = new LockScreenStateReceiver();
        IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
        filter.addAction(Intent.ACTION_USER_PRESENT);

        registerReceiver(mReceiver, filter);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return START_STICKY;
    }

    public class LockScreenStateReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
                //if screen is turn off show the textview
                if (!isShowing) {
                    windowManager.addView(textview, params);
                    isShowing = true;
                }
            }

            else if(intent.getAction().equals(Intent.ACTION_USER_PRESENT)) {
                //Handle resuming events if user is present/screen is unlocked remove the textview immediately
                if (isShowing) {
                    windowManager.removeViewImmediate(textview);
                    isShowing = false;
                }
            }
        }
    }

    @Override
    public void onDestroy() {
        //unregister receiver when the service is destroy
        if (mReceiver != null) {
            unregisterReceiver(mReceiver);
        }

        //remove view if it is showing and the service is destroy
        if (isShowing) {
            windowManager.removeViewImmediate(textview);
            isShowing = false;
        }
        super.onDestroy();
    }

}

and add the necessary permission on AndroidManifest.xml and add the service

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.textonlockscreenusingservice">

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

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name"
            android:theme="@style/AppTheme.NoActionBar">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <service android:name=".LockScreenTextService" /> //this

    </application>

</manifest>

Don't forget to start the service on onCreate() of your activity

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    Intent intent = new Intent(this, LockScreenTextService.class);
    startService(intent);

}

TextView showing on lockscreen TextView showing on lockscreen

TextView removed when unlocked TextView removed when unlocked

Mantel answered 19/2, 2016 at 17:46 Comment(11)
I wasnt active for a few days. Did you get the bounty? This answer is correctHolbrooke
was able to get half of the bounty haha ;) don't worryMantel
I've got this warning "Unable to add window android.view.ViewRootImpl -- permission denied for this window type" while executing windowManager.addView(textview, params);, and so nothing was attached to the lock screen. Pls help..Wastepaper
Did you put necessary permission on manifest? "<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>"Mantel
It appears that some kind of phones dose not work yet in Genymotion it works fine. Anyway thank you!Wastepaper
How to add margins or how can I change the position of this overlay view?Wastepaper
Is it possible to add a click event on the text ?Phillisphilly
textview.setOnClickListener(); or such if it will work goodluck ;)Mantel
sorry as you can see this post is 2 years old already will update if I have time and be able to run it up on emulator ;)Mantel
Have anyone find solution for Orio? Somehow Truecaller did it.Gnawing
If you wonder how to do the same on Oreo and don't want to waste days digging (Unlike me) here is the solution: 1. Use AccessibilityService Instead of the regular Service There the user has to enable your service in the Settings! 2. Replace the TYPE_SYSTEM_OVERLAY with TYPE_ACCESSIBILITY_OVERLAY Other places you will see the suggestion to use TYPE_APPLICATION_OVERLAY but it won't draw over the System UI!Piccadilly
O
4

Starting with Android Lollipop (5.0), support for lockscreen widgets has been removed (see the very bottom). Instead, you should be using Notifications, which can now appear on the lockscreen.

Orethaorferd answered 14/2, 2016 at 9:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.