Android悬浮框,在Service中打开悬浮窗;在Service中打开Dialog;

文章介绍了如何在Service中显示悬浮框,在Service中弹出Dialog,在Service中做耗时的轮询操作;
背景需求:

公司的项目现在的逻辑是这样的:发送一个指令,然后3秒一次轮询去查询这个指令是否成功,在这期间界面有遮盖不可操作;

然后需求改了,因为遮盖界面不让用户操作体验不好;现在的需求是:这个轮询查询指令是否成功的操作在后端进行,界面有一个悬浮框用来提示用户正在查询指令;

嗯,在后端查询指令让用户无感,可以用Service实现,然后悬浮框使用WindowMessage实现,轮询查询指令使用Handler或IntentService实现;大致就是这样,先来个Demo;
1、开启服务:需要的信息由Activity使用Intent传递给Service;

    Intent intent = new Intent(this,MyService.class);
            intent.putExtra("args","晨");
            startService(intent);

    public class MyService extends Service {
     
     
        public MyService() {
        }
     
        @Override
        public IBinder onBind(Intent intent) {
            throw new UnsupportedOperationException("Not yet implemented");
        }
     
        @Override
        public void onCreate() {
            super.onCreate();
     
        }
     
     
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
           args = intent.getStringExtra("args");
            return super.onStartCommand(intent, flags, startId);
        }
     
        @Override
        public void onDestroy() {
            super.onDestroy();
        }
    }

Service中的onCreate只在创建的时候执行一次,onStartCommand()每次开启这个Service都会执行;同时别忘记这个注册:

      <service
                android:name=".MyService"
                android:enabled="true"
                android:exported="true" />

2、在Service开启成功后创建悬浮框,

        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
           args = intent.getStringExtra("args");
           initView();
            return super.onStartCommand(intent, flags, startId);
        }
     
     /**
         * 使用系统级别的WindowManager展示悬浮框,需要6.0以上的权限;
         */
        private void initView() {
            if (Build.VERSION.SDK_INT >= 23) {
                if (!Settings.canDrawOverlays(this)) {
                    Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
                    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    intent.setData(Uri.parse( "package:"+"com.example.administrator.xuanfudemo"));  //应用的包名,可直接跳转到这个应用的悬浮窗设置;
                    startActivity(intent);
                } else {
                    openWindow();
                }
            }else {
                openWindow();
            }
        }
     
        private void openWindow(){
            windowManager = (WindowManager) this.getSystemService(WINDOW_SERVICE);
            WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();
            layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT;
            layoutParams.width = ViewGroup.LayoutParams.WRAP_CONTENT;
            layoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
    //        layoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
    //        layoutParams.token = this.getWindow().getDecorView().getWindowToken();  //这样设置,在activity中打开悬浮框可绕过权限;
            layoutParams.flags =  WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
            layoutParams.format = PixelFormat.TRANSLUCENT;  //透明
            layoutParams.gravity = Gravity.TOP | Gravity.RIGHT;  //右上角显示
            view = LayoutInflater.from(this).inflate(R.layout.view_win,null);
            windowManager.addView(view,layoutParams);
        }

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

悬浮框需要权限,而且这个权限属于危险级权限,API23以上需要用户手动开启;
3、使用Handler轮询查询指令;

查询到指令后弹框提示,弹出Dialog。在Service中弹出Dialog需要设置下方代码,同时还要有弹窗权限;

dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);

     private Handler mHandler = new Handler(){
            @Override
            public void dispatchMessage(Message msg) {
                super.dispatchMessage(msg);
                switch (msg.what){
                    case HANDLERSIGN:
                        Log.i(TAG, "dispatchMessage: "+args+(++num));
                        mHandler.sendEmptyMessageDelayed(HANDLERSIGN,HANDLERTIME);
                        if (num == 5){
                            AlertDialog.Builder builder = new AlertDialog.Builder(MyService.this);
                            builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialogInterface, int i) {
                                    MyService.this.stopSelf();
                                }
                            });
                            AlertDialog dialog = builder.create();
                            dialog.setMessage("我的计数"+num);
                            dialog.setTitle("提示");
                            dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
                            dialog.show();
                        }
                        break;
                }
            }
        };
     
        private final String TAG = "ccb";
        private String args;
        private int num;
        private final int HANDLERSIGN = 10;
        private final int HANDLERTIME = 2010;
     
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
           args = intent.getStringExtra("args");
           initView();
            initData();
            return super.onStartCommand(intent, flags, startId);
        }
     
      private void initData() {
            mHandler.sendEmptyMessageDelayed(HANDLERSIGN,HANDLERTIME);
        }

4、在服务销毁时,清空Handler信息关闭悬浮框;

        @Override
        public void onDestroy() {
            super.onDestroy();
            Log.i(TAG, "onDestroy: 啊,ByKill");
            mHandler.removeCallbacksAndMessages(null);
            if (windowManager != null) windowManager.removeView(view);
        }

全部的Service代码:

悬浮框我使用了两种,另外一种是FloatWindow,有兴趣的可以去GitHub查一下;

    package com.example.administrator.xuanfudemo;
     
    import android.Manifest;
    import android.app.AlertDialog;
    import android.app.Service;
    import android.content.DialogInterface;
    import android.content.Intent;
    import android.graphics.PixelFormat;
    import android.net.Uri;
    import android.os.Build;
    import android.os.Handler;
    import android.os.IBinder;
    import android.os.Message;
    import android.provider.Settings;
    import android.support.v4.app.ActivityCompat;
    import android.util.Log;
    import android.view.Gravity;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.view.WindowManager;
     
    import com.yhao.floatwindow.FloatWindow;
    import com.yhao.floatwindow.PermissionListener;
    import com.yhao.floatwindow.Screen;
    import com.yhao.floatwindow.ViewStateListener;
     
    public class MyService extends Service {
     
        private WindowManager windowManager;
        private View view;
     
        public MyService() {
        }
     
        @Override
        public IBinder onBind(Intent intent) {
            throw new UnsupportedOperationException("Not yet implemented");
        }
     
        @Override
        public void onCreate() {
            super.onCreate();
     
        }
     
        private Handler mHandler = new Handler(){
            @Override
            public void dispatchMessage(Message msg) {
                super.dispatchMessage(msg);
                switch (msg.what){
                    case HANDLERSIGN:
                        Log.i(TAG, "dispatchMessage: "+args+(++num));
                        mHandler.sendEmptyMessageDelayed(HANDLERSIGN,HANDLERTIME);
                        if (num == 5){
                            AlertDialog.Builder builder = new AlertDialog.Builder(MyService.this);
                            builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialogInterface, int i) {
                                    MyService.this.stopSelf();
    //                                if (windowManager != null) windowManager.removeView(view);
                                }
                            });
                            AlertDialog dialog = builder.create();
                            dialog.setMessage("我的计数"+num);
                            dialog.setTitle("提示");
                            dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
                            dialog.show();
                        }
                        break;
                }
            }
        };
     
        private final String TAG = "ccb";
        private String args;
        private int num;
        private final int HANDLERSIGN = 10;
        private final int HANDLERTIME = 2010;
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
           args = intent.getStringExtra("args");
    //       initView();
           initView2();
            initData();
            return super.onStartCommand(intent, flags, startId);
        }
     
        /**
         * FloatWindow使用FloatWindow库展示悬浮框;可拖拽
         */
        private void initView2() {
            FloatWindow
                    .with(getApplicationContext())
                    .setView(LayoutInflater.from(this).inflate(R.layout.view_win,null))
                    .setWidth(100)                               //设置控件宽高
                    .setHeight(Screen.height,0.2f)
                    .setX(100)                                   //设置控件初始位置
                    .setY(Screen.height,0.3f)
                    .setDesktopShow(true)                        //桌面显示
                    .setViewStateListener(new ViewStateListener() {
                        @Override
                        public void onPositionUpdate(int i, int i1) {
     
                        }
     
                        @Override
                        public void onShow() {
     
                        }
     
                        @Override
                        public void onHide() {
     
                        }
     
                        @Override
                        public void onDismiss() {
     
                        }
     
                        @Override
                        public void onMoveAnimStart() {
     
                        }
     
                        @Override
                        public void onMoveAnimEnd() {
     
                        }
     
                        @Override
                        public void onBackToDesktop() {
     
                        }
                    })
                    .setPermissionListener(new PermissionListener() {
                        @Override
                        public void onSuccess() {
     
                        }
     
                        @Override
                        public void onFail() {
     
                        }
                    })
                    .build();
            FloatWindow.get().show();
        }
     
        /**
         * 使用系统级别的WindowManager展示悬浮框,需要6.0以上的权限;
         */
        private void initView() {
            if (Build.VERSION.SDK_INT >= 23) {
                if (!Settings.canDrawOverlays(this)) {
                    Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
                    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    intent.setData(Uri.parse( "package:"+"com.example.administrator.xuanfudemo"));
                    startActivity(intent);
                } else {
                    openWindow();
                }
            }else {
                openWindow();
            }
        }
     
        private void openWindow(){
            windowManager = (WindowManager) this.getSystemService(WINDOW_SERVICE);
            WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();
            layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT;
            layoutParams.width = ViewGroup.LayoutParams.WRAP_CONTENT;
            layoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
    //        layoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
    //        layoutParams.token = this.getWindow().getDecorView().getWindowToken();
            layoutParams.flags =  WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
            layoutParams.format = PixelFormat.TRANSLUCENT;
            layoutParams.gravity = Gravity.TOP | Gravity.RIGHT;
            view = LayoutInflater.from(this).inflate(R.layout.view_win,null);
            windowManager.addView(view,layoutParams);
        }
     
        private void initData() {
            mHandler.sendEmptyMessageDelayed(HANDLERSIGN,HANDLERTIME);
        }
     
        @Override
        public void onDestroy() {
            super.onDestroy();
            Log.i(TAG, "onDestroy: 啊,ByKill");
            mHandler.removeCallbacksAndMessages(null);
            if (windowManager != null) windowManager.removeView(view);
            FloatWindow.destroy();
        }
    }

 
---------------------
作者:Choi晨
来源:CSDN
原文:https://blog.csdn.net/qq_35605213/article/details/81510917
版权声明:本文为博主原创文章,转载请附上博文链接!

posted @ 2019-03-07 15:47  天涯海角路  阅读(1587)  评论(0)    收藏  举报