Android利用WindowsManager悬浮窗播放视频广告开发分屏应用
2018-01-20 14:07
661 查看
由于项目要求需要做一款分屏显示的App。首先拿到这个项目需求的时候第一反应相信大家跟我一样都会想到利用fragment去做。其实之前做过一版demo给另外一个项目的客户体验,就是用fragment去实现分屏显示。其实用fragment去实现分屏也是很容易的事情,但是我总感觉操作体验上给人不是很舒服的,而且需要开发者对很多事件进行重写来确保在体验上与Activity的体验相差无异。
在这次项目开始之前就开始查阅相关资料,寻找能实现分屏显示的另外一种途径,当时一个朋友跟我提出可以使用WindowsManager来做一个悬浮窗应用来遮罩在主APP上,这样既可以实现分屏显示还减少了开发量。并且由于我的项目是由横屏项目改成一个竖屏的项目来做分屏,也大大降低了我的工作量。因为我只需要在原有项目上添加一块被遮罩的空布局放在BaseActivity中并微调我的界面适配即可。
首先我们来说WindowsManager,我做了个简易的demo来实现WindowsManager悬浮窗播放广告视频。
1.必要的权限
2.视频播放控件(VideoView系统控件,需要做自定义,涉及到适配屏幕无法充满的问题)
3.悬浮窗布局float_window_big
4.承载悬浮窗布局的自定义view
5.悬浮窗布局管理器
6.后台常住执行视频播放的service
7.MainActivity
其实整个项目比较简单,实现起来也比较容易。但是在开发中发现一个问题,就是这个videoView需要传递Activity的token,但是看了几篇博客还是比较懵,所以我选择了在启动悬浮窗的时候并没有销毁当前的Activity,而是需要手动点击home键来退出主页面。
demo: http://download.csdn.net/download/d38825/10215427
在这次项目开始之前就开始查阅相关资料,寻找能实现分屏显示的另外一种途径,当时一个朋友跟我提出可以使用WindowsManager来做一个悬浮窗应用来遮罩在主APP上,这样既可以实现分屏显示还减少了开发量。并且由于我的项目是由横屏项目改成一个竖屏的项目来做分屏,也大大降低了我的工作量。因为我只需要在原有项目上添加一块被遮罩的空布局放在BaseActivity中并微调我的界面适配即可。
首先我们来说WindowsManager,我做了个简易的demo来实现WindowsManager悬浮窗播放广告视频。
1.必要的权限
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.BROADCAST_STICKY" /> <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> <uses-permission android:name="android.permission.GET_TASKS" /> <!-- SDCard中创建与删除文件权限 --> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> <!-- 向SDCard写入数据权限 --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
2.视频播放控件(VideoView系统控件,需要做自定义,涉及到适配屏幕无法充满的问题)
public class CosVideoView extends VideoView{ public CosVideoView (Context context) { super(context); } public CosVideoView (Context context, AttributeSet attrs) { super(context, attrs); } public CosVideoView (Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { //主要方法在这里 int width = getDefaultSize(0, widthMeasureSpec); int height = getDefaultSize(0, heightMeasureSpec); setMeasuredDimension(width, height); } @Override public void setOnPreparedListener(MediaPlayer.OnPreparedListener l) { super.setOnPreparedListener(l); } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { return super.onKeyDown(keyCode, event); } }
3.悬浮窗布局float_window_big
<?xml version="1.0" encoding="UTF-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/big_window_layout" android:layout_width="match_parent" android:layout_height="300dip" android:background="@color/colorAccent" android:orientation="vertical"> <com.example.zhawe.windowsmanagerdemo.CosVideoView android:id="@+id/video_view" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" /> </LinearLayout>
4.承载悬浮窗布局的自定义view
public class FloatWindowBigView extends LinearLayout { /** * 记录大悬浮窗的宽度 */ public static int viewWidth; /** * 记录大悬浮窗的高度 */ public static int viewHeight; private final CosVideoView videoView; public FloatWindowBigView(final Context context) { super(context); LayoutInflater.from(context).inflate(R.layout.float_window_big, this); View view = findViewById(R.id.big_window_layout); viewWidth = view.getLayoutParams().width; viewHeight = view.getLayoutParams().height; videoView = this.findViewById(R.id.video_view); videoView.setVideoPath("/mnt/sdcard/video.3gp"); videoView.setZOrderOnTop(true); videoView.setZOrderMediaOverlay(true); videoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { @Override public void onCompletion(MediaPlayer mediaPlayer) { videoView.start(); } }); videoView.start(); } }
5.悬浮窗布局管理器
public class MyWindowManager { /** * 大悬浮窗View的实例 */ private static FloatWindowBigView bigWindow; /** * 大悬浮窗View的参数 */ private static WindowManager.LayoutParams bigWindowParams; /** * 用于控制在屏幕上添加或移除悬浮窗 */ private static WindowManager mWindowManager; /** * 创建一个大悬浮窗。位置为屏幕正中间。 * * @param context 必须为应用程序的Context. */ public static void createBigWindow(Context context) { WindowManager windowManager = (WindowManager) context.getApplicationContext().getSystemService("window"); int screenWidth = windowManager.getDefaultDisplay().getWidth(); int screenHeight = windowManager.getDefaultDisplay().getHeight(); if (bigWindow == null) { bigWindow = new FloatWindowBigView(context); if (bigWindowParams == null) { bigWindowParams = new WindowManager.LayoutParams(); bigWindowParams.x = 0; bigWindowParams.y = 0; bigWindowParams.type = WindowManager.LayoutParams.TYPE_PHONE; bigWindowParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; bigWindowParams.format = PixelFormat.RGBA_8888; bigWindowParams.gravity = Gravity.LEFT | Gravity.TOP; bigWindowParams.width = screenWidth; bigWindowParams.height = screenHeight / 2; } bigWindow.setFitsSystemWindows(true); bigWindow.getWindowToken(); windowManager.addView(bigWindow, bigWindowParams); } } /** * 将大悬浮窗从屏幕上移除。 * * @param context 必须为应用程序的Context. */ public static void removeBigWindow(Context context) { if (bigWindow != null) { WindowManager windowManager = getWindowManager(context); windowManager.removeView(bigWindow); bigWindow = null; } } /** * 是否有悬浮窗(包括小悬浮窗和大悬浮窗)显示在屏幕上。 * * @return 有悬浮窗显示在桌面上返回true,没有的话返回false。 */ public static boolean isWindowShowing() { return bigWindow != null; } /** * 如果WindowManager还未创建,则创建一个新的WindowManager返回。否则返回当前已创建的WindowManager。 * * @param context 必须为应用程序的Context. * @return WindowManager的实例,用于控制在屏幕上添加或移除悬浮窗。 */ private static WindowManager getWindowManager(Context context) { if (mWindowManager == null) { mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); } return mWindowManager; } }
6.后台常住执行视频播放的service
public class FloatWindowService extends Service { /** * 用于在线程中创建或移除悬浮窗。 */ private Handler handler = new Handler(); /** * 定时器,定时进行检测当前应该创建还是移除悬浮窗。 */ private Timer timer; @Override public IBinder onBind(Intent intent) { return null; } @Override public int onStartCommand(Intent intent, int flags, int startId) { // 开启定时器,每隔0.5秒刷新一次 if (timer == null) { timer = new Timer(); timer.scheduleAtFixedRate(new RefreshTask(), 0, 500); } return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { super.onDestroy(); // Service被终止的同时也停止定时器继续运行 timer.cancel(); timer = null; } class RefreshTask extends TimerTask { @Override public void run() { // 当前界面是桌面,且没有悬浮窗显示,则创建悬浮窗。 if (!MyWindowManager.isWindowShowing()) { handler.post(new Runnable() { @Override public void run() { MyWindowManager.createBigWindow(MainActivity.getInstance()); } }); } } } }
7.MainActivity
public class MainActivity extends Activity { private static MainActivity instance; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); instance = this; setContentView(R.layout.activity_main); Button startFloatWindow = (Button) findViewById(R.id.start_float_window); startFloatWindow.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View arg0) { Intent intent = new Intent(MainActivity.this, FloatWindowService.class); startService(intent); } }); } public static synchronized MainActivity getInstance() { return instance; }
其实整个项目比较简单,实现起来也比较容易。但是在开发中发现一个问题,就是这个videoView需要传递Activity的token,但是看了几篇博客还是比较懵,所以我选择了在启动悬浮窗的时候并没有销毁当前的Activity,而是需要手动点击home键来退出主页面。
demo: http://download.csdn.net/download/d38825/10215427
相关文章推荐
- cordova开发:android端用video.js播放视频,解决退出全屏后应用被状态栏遮挡
- 【Android开发】多媒体应用开发-使用VideoView播放视频
- Android应用开发学习笔记之播放视频
- Android应用开发学习笔记之播放视频
- 【iOS-Cocos2d游戏开发之十四】音频/音效/视频播放(利用Cocos2D-iPhone-Extensions嵌入Cocos2d进行视频播放!)
- 【iOS-Cocos2d游戏开发之十四】音频/音效/视频播放(利用Cocos2D-iPhone-Extensions嵌入Cocos2d进行视频播放!)
- 深入剖析Android应用开发--视频
- Android开发之初探视频的播放
- Android中除了利用VideoView、Mediaplayer播放视频文件外,还可以用发送Intent来调用视频播放模块。
- 3G手机Android应用开发视频教程_黎活明老师的视频(第一天课程)总共有八天课程
- Android应用开发之利用服务实现电话监听
- 3G手机Android应用开发视频教程_黎活明老师的视频(第二天课程)总共有八天课程
- Android多媒体开发(5)————利用Android AudioTrack播放mp3文件
- 【iOS-Cocos2d游戏开发之十四】音频/音效/视频播放(利用Cocos2D-iPhone-Extensions嵌入Cocos2d进行视频播放!)
- 深入剖析Android应用开发--视频
- 【iOS-Cocos2d游戏开发之十四】音频/音效/视频播放(利用Cocos2D-iPhone-Extensions嵌入Cocos2d进行视频播放!)
- Android利用WebView开发browser中flash无法播放的问题
- Android利用WebView开发browser中flash无法播放的问题
- Android游戏开发学习笔记(三):视频的播放
- android应用开发之利用SAX、DOM和Pull实现对XML文件的解析并进行单元测试