Android:通过锁定屏幕显示视图(如Google Maps)

问题描述 投票:1回答:1

我想在锁定屏幕上显示个性化视图(实时显示一些数据)(之后用户将手机锁定在活动上)。Google Maps and Baidu Maps(以及其他一些我忘记了名称的应用程序)已经完全实现了我想要的功能。

所以我正在尝试在我的BroadcastReceiver触发时添加视图。我从this answerthis one中尝试了一些要点。我也尝试过this one。在我根据权限得到一些错误之前:

窗口类型2XXX的权限被拒绝

现在,我没有任何错误,但未显示我的视图。我的情况是:MainActivity.kt:

import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.provider.Settings
import androidx.appcompat.app.AppCompatActivity


class MainActivity : AppCompatActivity() {
    private val REQUEST_CODE = 10001

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        checkDrawOverlayPermission()
    }
    fun checkDrawOverlayPermission() {
        /** check if we already  have permission to draw over other apps */
        if (!Settings.canDrawOverlays(this)) {
            /** if not construct intent to request permission */
            val intent = Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
                Uri.parse("package:" + getPackageName()));
            /** request permission via start activity for result */
            startActivityForResult(intent, REQUEST_CODE);
        }
        else {
            startService(Intent(this, LockScreenService::class.java))
        }
    }

    override fun onActivityResult(
        requestCode: Int,
        resultCode: Int,
        data: Intent?
    ) {
        super.onActivityResult(requestCode, resultCode, data)
        if (requestCode == REQUEST_CODE) {
            if (Settings.canDrawOverlays(this)) {
                startService(Intent(this, LockScreenService::class.java))
            }
        }
    }
}

LockSceenService.kt:

class LockScreenService : Service() {
    private var mReceiver: BroadcastReceiver? = null
    private var isShowing = false
    override fun onBind(intent: Intent): IBinder? {
        // TODO Auto-generated method stub
        return null
    }

    private var windowManager: WindowManager? = null
    private var textview: TextView? = null
    private var mView: View? = null
    var params: WindowManager.LayoutParams? = null
    override fun onCreate() {
        super.onCreate()
        windowManager = getSystemService(Context.WINDOW_SERVICE) as WindowManager

        mView = View.inflate(baseContext, R.layout.lockscreen_view, null)
        mView!!.systemUiVisibility = (View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                or View.SYSTEM_UI_FLAG_FULLSCREEN
                or View.SYSTEM_UI_FLAG_VISIBLE
                or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)
        mView!!.visibility = View.VISIBLE
        //set parameters for the textview

        val flag: Int = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
        } else {
            WindowManager.LayoutParams.TYPE_PHONE
        }
        params = WindowManager.LayoutParams(
            WindowManager.LayoutParams.WRAP_CONTENT,
            WindowManager.LayoutParams.WRAP_CONTENT,
            flag,
            WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
                    or WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
                    or WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
                    or WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                    or WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
                    or WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
            PixelFormat.TRANSLUCENT
        )
        params!!.gravity = Gravity.BOTTOM

        //Register receiver for determining screen off and if user is present
        mReceiver = LockScreenStateReceiver()
        val filter = IntentFilter(Intent.ACTION_SCREEN_ON)
        filter.addAction(Intent.ACTION_USER_PRESENT)
        registerReceiver(mReceiver, filter)
    }

    override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
        return START_STICKY
    }

    inner class LockScreenStateReceiver : BroadcastReceiver() {
        override fun onReceive(
            context: Context,
            intent: Intent
        ) {
            if (intent.action == Intent.ACTION_SCREEN_ON) {
                //if screen is turn off show the textview
                if (!isShowing) {
                    windowManager!!.addView(mView, params)
                    isShowing = true
                }
            } else if (intent.action == 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 fun 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()
    }
}

Manifest.xml:

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

[如果您有任何建议或其他方式,例如“锁定屏幕上的透明活动”(?)或仅是投票,可能会有用。

感谢您的时间!

编辑:我想要的是video

android android-view android-permissions lockscreen android-windowmanager
1个回答
1
投票

您可以在使用前台通知服务锁定设备时在锁定屏幕上显示视图,您可以使用自定义XML通知布局自定义默认通知视图,并且前台服务可以实时更改视图的内容。时间。

来自Google Maps的示例通知和我们的自定义通知警报

Google Maps SampleCustom Sample

您可以按照以下要点来创建具有前台服务的自定义通知布局。

权限

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

清单

<service
    android:name=".MyForegroundService"
    android:icon="@drawable/ic_notification"
    android:label="MFS" />

服务

import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Binder;
import android.os.Build;
import android.os.IBinder;
import android.util.Log;
import android.widget.RemoteViews;
import android.widget.Toast;

import androidx.core.app.NotificationCompat;

public class MyForegroundService extends Service {

    private static final String TAG = "MyForegroundService";

    private static final int NOTIFICATION_ID = 2999;
    private static final String CHANNEL_ID = "MyForegroundService_ID";
    private static final CharSequence CHANNEL_NAME = "MyForegroundService Channel";
    private final IBinder mBinder = new LocalBinder();

    public class LocalBinder extends Binder {
        public MyForegroundService getService() {
            return MyForegroundService.this;
        }
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "onCreate ");
        Toast.makeText(this, "The service is running", Toast.LENGTH_SHORT).show();
        startForeground(NOTIFICATION_ID, createNotification("The service is running"));
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d(TAG, "onStartCommand");
        return Service.START_STICKY;
    }

    private Notification createNotification(String message) {

        // Get the layouts to use in the custom notification
        RemoteViews notificationLayout = new RemoteViews(getPackageName(), R.layout.notification_main);
        notificationLayout.setTextViewText(R.id.txtTitle, message);

        NotificationManager mNotificationManager;
        NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this, CHANNEL_ID);

        Intent notificationIntent = new Intent(this, MainActivity.class);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 125, notificationIntent, 0);

        Bitmap payableLogo = BitmapFactory.decodeResource(getResources(), R.drawable.ic_notification);

        mBuilder.setContentTitle("My Service")
                .setContentText(message)
                .setPriority(Notification.PRIORITY_HIGH)
                .setLargeIcon(payableLogo)
                .setSmallIcon(R.drawable.ic_notification)
                .setContentIntent(pendingIntent)
                .setAutoCancel(false)

                .setCustomBigContentView(notificationLayout);

        mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            String channelId = CHANNEL_ID;
            NotificationChannel channel = new NotificationChannel(channelId, CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT);
            mNotificationManager.createNotificationChannel(channel);
            mBuilder.setChannelId(channelId);
        }

        return mBuilder.build();
    }

    private void showNotification(String message) {
        NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        mNotificationManager.notify(NOTIFICATION_ID, createNotification(message));
    }

    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy");
    }
}

通知布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/colorPrimaryDark"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:paddingHorizontal="20dp"
        android:paddingVertical="15dp">

        <TextView
            android:id="@+id/txtTitle"
            style="@style/TextAppearance.Compat.Notification.Info.Media"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="This is from my service"
            android:textColor="#fff" />

        <TextView
            android:id="@+id/txtResult"
            style="@style/TextAppearance.Compat.Notification.Title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="5dp"
            android:text="Any text goes here"
            android:textColor="#fff" />

    </LinearLayout>

</LinearLayout>

参考:https://gist.github.com/aslamanver/f32a0bb8461c250d4a945e11f6771456

© www.soinside.com 2019 - 2024. All rights reserved.