1、需求
视频通话Activity可切换小窗(悬浮窗)显示。不懂的话就是和微信的视频通话差不多。
2、实现
视频通话Activity全局只能存在一个实例,遂用SingleInstance启动模式。切换到悬浮窗,因为要保存视频通话Activity的状态信息,所以不能销毁Activity,那要怎么样才能返回到上一个页面呢?这里我们利用SingleInstance启动模式的特性:新建一个Activity Task单独用于存放视频通话Activity的实例。我们应该知道Android系统有且仅有一个Activity Task会处于前台,当一个新的Task开启后,原来的Task就会默认退到后台(不可见),一般情况下,新的Task中的Activity销毁后,会返回到上一个Task中的TopActivity页面,但是悬浮窗显示的需求不允许我们销毁这个Task中的Activity,那要用什么方法才能返回到上一个页面而不销毁视频通话Activity呢?
/**
* 把当前Activity示例所在的Task移动到后台
* {@link android.app.Activity#moveTaskToBack(boolean nonRoot)}
* @param nonRoot If false then this only works if the activity is the root
* of a task; if true it will work for any activity in
* a task.
*/
moveTaskToBack(true);
这样当前就达到了视频通话Activity在不销毁情况下隐藏的需求了。
关于悬浮窗如何实现这里不再赘述了,给大家贴几条链接看下吧。
Android悬浮窗操作使用总结
Andorid 应用内悬浮控件实践方案总结
EasyFloat:浮窗从未如此简单
3、问题
到现在基本实现了此需求的大致逻辑。
点击悬浮窗回到视频通话Activity很简单,调用startActivity重新打开视频通话Activity就好了。
自测没问题,提测后问题来了。。。
荣耀和小米5返回不了视频通话Activity,startActivity丝毫反应都没有,日志也什么也没有,我到最后也没查出个所以然来。所以索性另寻重启视频通话Activity的方法了。
private void moveToFront() {
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
if (manager != null) {
List<ActivityManager.RunningTaskInfo> recentTasks = manager.getRunningTasks(Integer.MAX_VALUE);
if (recentTasks != null && !recentTasks.isEmpty()) {
for (ActivityManager.RunningTaskInfo taskInfo : recentTasks) {
ComponentName cpn = taskInfo.baseActivity;
if (null != cpn && TextUtils.equals(VideoChatActivity.class.getName(), cpn.getClassName())) {
manager.moveTaskToFront(taskInfo.id, ActivityManager.MOVE_TASK_NO_USER_ACTION);
break;
}
}
}
}
}
moveTaskToFront方法具体详情查看下方源码:
/**
* Flag for {@link #moveTaskToFront(int, int)}: also move the "home"
* activity along with the task, so it is positioned immediately behind
* the task.
*/
public static final int MOVE_TASK_WITH_HOME = 0x00000001;
/**
* Flag for {@link #moveTaskToFront(int, int)}: don't count this as a
* user-instigated action, so the current activity will not receive a
* hint that the user is leaving.
*/
public static final int MOVE_TASK_NO_USER_ACTION = 0x00000002;
/**
* Equivalent to calling {@link #moveTaskToFront(int, int, Bundle)}
* with a null options argument.
*
* @param taskId The identifier of the task to be moved, as found in
* {@link RunningTaskInfo} or {@link RecentTaskInfo}.
* @param flags Additional operational flags.
*/
@RequiresPermission(android.Manifest.permission.REORDER_TASKS)
public void moveTaskToFront(int taskId, @MoveTaskFlags int flags) {
moveTaskToFront(taskId, flags, null);
}
/**
* Ask that the task associated with a given task ID be moved to the
* front of the stack, so it is now visible to the user.
*
* @param taskId The identifier of the task to be moved, as found in
* {@link RunningTaskInfo} or {@link RecentTaskInfo}.
* @param flags Additional operational flags.
* @param options Additional options for the operation, either null or
* as per {@link Context#startActivity(Intent, android.os.Bundle)
* Context.startActivity(Intent, Bundle)}.
*/
@RequiresPermission(android.Manifest.permission.REORDER_TASKS)
public void moveTaskToFront(int taskId, @MoveTaskFlags int flags, Bundle options) {
try {
ActivityThread thread = ActivityThread.currentActivityThread();
IApplicationThread appThread = thread.getApplicationThread();
String packageName = mContext.getPackageName();
getTaskService().moveTaskToFront(appThread, packageName, taskId, flags, options);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
4、总结
没问题的方法就是好方法,希望你能用上。