在活动被破坏之前检测旋转(方向改变)

Dav*_*vid 5 android screen-orientation android-activity

目标

我正在研究简化的音频播放器,如果用户离开应用程序(主页按钮,任务切换,任务中断,屏幕关闭等),则需要停止播放.我可以让音频继续在后台播放并打开一个带有暂停/停止选项的通知栏,但我的用户几乎没有计算机知识,有些人可能无法在没有帮助的情况下停止音频.

问题

为了停止音频,我需要知道在活动被销毁之前应用程序何时移出焦点.Android提供了两种方法onStop和onPause,它们表明正在发生的事情,但不是什么.如果可能,我如何知道活动何时因方向改变而被销毁?

解决方案失败

我可以在onPause(或onStop/onDestroy)中使用isFinishing()来检查应用程序是否正在关闭并停止音频.但这只会告诉我们申请何时结束.它不区分移动到背景和旋转.

IsChangingConfigurations是一个有趣的函数,可以解决我的问题,但这需要API 11,我有兴趣支持API 10.

另一个解决方案似乎是一个糟糕的黑客.与此解决方案一样,OrientationChangeListener 看起来很理想,但它只注意到活动关闭并重新启动后方向已更改.

与上述选项类似,onConfigurationChanged仅在完成方向更改后报告方向更改.

有缺陷但可能的解决方案

一种解决方案是当媒体播放器失去与活动的连接时通知媒体播放器服务,然后在一段时间后自动暂停.这绝对是一个可行的解决方案,但它并不理想.多少时间合适?如果平板电脑运行缓慢且旋转时间比平时长,会发生什么?如果没有更好的选择,我会回到这个解决方案.这似乎是一个黑客,容易出错.

j2e*_*esu 8

我在我的片段中使用它(api 11+,但您可以手动决定如何处理旧版本):

@Override
public void onPause() {
    super.onPause();
    if (isRecreating()) {
        //do smth
    }
}

public boolean isRecreating() {
    //consider pre honeycomb not recreating
    return Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB &&
            getActivity().isChangingConfigurations();
}
Run Code Online (Sandbox Code Playgroud)


Dav*_*vid 2

在发布我的问题之前经过大量搜索,我终于根据这篇文章提出了一个解决方案。我非常简单地检查当前方向并将其与之前的状态进行比较。

getResources().getConfiguration().orientation
Run Code Online (Sandbox Code Playgroud)

如果不同,则活动由于轮换而重新启动。

示例解决方案

我首先使用两个成员变量来跟踪先前的配置并标记旋转:

private int previousOrientation = Configuration.ORIENTATION_UNDEFINED;
private boolean rotating = false;
Run Code Online (Sandbox Code Playgroud)

当活动启动时,在 onCreate 中,我调用 checkAndSetOrientationInfo() ,其定义为:

private void checkAndSetOrientationInfo() {
    int currentOrientation = getResources().getConfiguration().orientation;
    debugDescribeOrientations(currentOrientation);
    if(previousOrientation != Configuration.ORIENTATION_UNDEFINED // starts undefined
            && previousOrientation != currentOrientation) rotating = true;

    previousOrientation = currentOrientation;
}
Run Code Online (Sandbox Code Playgroud)

支持的功能有:

private String getOrientationAsString(final int orientation) {
    if(orientation == Configuration.ORIENTATION_LANDSCAPE) {
        return "Landscape";
    } else if(orientation == Configuration.ORIENTATION_PORTRAIT) {
        return "Portrait";
    } else return "Undefined";
}

private void debugDescribeOrientations(final int currentOrientation) {
    Log.v("Orientation", "previousOrientation: " + getOrientationAsString(previousOrientation));
    Log.v("Orientation", "currentOrientation: " + getOrientationAsString(currentOrientation));
}
Run Code Online (Sandbox Code Playgroud)

最后,对于 onPause:

@Override
protected void onPause() {
    super.onPause();
    if (isFinishing()) {
        Log.v("onPause", "Finishing");
    } else {
        checkAndSetOrientationInfo();
        if (rotating) {
            Log.v("onPause", "Rotating");
        } else {
           Log.v("onPause", "Not rotating (task switch / home etc)");
           // TODO put code here to pause mediaPlayer etc...
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我提出并回答这个问题是为了帮助其他有同样问题的人。我也有兴趣查看有关此代码可能失败的情况或其他更好的解决方案的任何评论。