论恶搞带来的思考,android如何检测被分屏?
啊
一、故事起因
在一个伸手不见五指的早晨,我向宿舍群发了一张分屏图,如下。
结果,到了阳光明媚的晚上,我收到了一条短信。在这没有隐私的生活下,我居然相信了!!,相信了!!
但是想想又不对,这怎么是个锡盟号呢?怎么不是钉钉官方号呢?于是作为一个android的学习者,开始深刻的思考一个问题,android如何检测app处于分屏状态呢?
二、如何检测处于分屏状态?
由于每个版本的android都新增了不同功能,在android7.0中,引入了多窗口的功能。也就是下图。这样就可以实现一边看直播,一边干其他事。
但是!!! 对于学习类软件,对于学生是“好”的,但是对于教学者设不好的,所以,有必要警告他处于分屏状态。
判断分屏状态非常简单,在activity中重写onMultiWindowModeChanged,当切换到分屏下,会进行回调,参数isInMultiWindowMode为true则表示进入了分屏模式,(官方话是多窗口模式)。这时候就可警告了。
@Override
public void onMultiWindowModeChanged(boolean isInMultiWindowMode) {
super.onMultiWindowModeChanged(isInMultiWindowMode);
Log.i(TAG, "onMultiWindowModeChanged: "+isInMultiWindowMode);
}
但是,当进入分屏时,activity会重新创建,生命周期如下,但是有些小伙伴说,在onMultiWindowModeChanged回调后,onSaveInstanceState会执行,但是经过我两部真实手机测试,并不会进行回调。反而在之前回调。
onCreate: 第一次创建
onStart:
onResume:
onPause:
onStop:
onSaveInstanceState: 保存转台
onMultiWindowModeChanged: true 点击多窗口按钮,进入分屏模式回调
onDestroy: 销毁
onCreate: 二次重建
onStart:
onResume:
退出分屏生命周期,首先activity销毁重建后在回调onMultiWindowModeChanged。
onPause:
onStop:
onSaveInstanceState: 保存状态
onDestroy: 销毁
onCreate: 第三次重建
onStart:
onResume:
onMultiWindowModeChanged: false 重建后回调
也就是在进入分屏前,先回调onMultiWindowModeChanged,然后activity销毁重建,退出分屏时,先销毁重建后在回调onMultiWindowModeChanged(至少在我两部手机上是这样的)。
有些APP为了减少出错率,或者因为自己懒惰,将app禁用分屏,如职教x。
显然在这个方法由于activity的重建原因判断优点麻烦,所以还可以使用另一个activity中的方法isInMultiWindowMode();返回true则表示处于多屏状态。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.i(TAG, "onCreate: "+isInMultiWindowMode());
}
onCreate: false 第一次进入,false
onStart:
onResume:
onStop:
onSaveInstanceState:
onMultiWindowModeChanged: true
onDestroy:
onCreate: true 进入分屏返回true,
onStart:
onResume:
onPause:
onStop:
onSaveInstanceState:
这时候可以启动一个定时器,超过指定秒后,则认定他在干其他事,进行处理(而我屏幕太大,想分屏缩小看怎么办?)。
完整实例如下,相对简单,或者进行自己逻辑上传到服务器进行统计。
public class MainActivity extends AppCompatActivity {
private Handler mHandler =new Handler();
private static final int MAX_SECOND = 5;
private static final String TAG = MainActivity.class.getSimpleName();
private Timer mTimer;
private int mCurrentMulitWindowSecond = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mCurrentMulitWindowSecond=0;
Log.i(TAG, "onCreate: "+isInMultiWindowMode());
if (isInMultiWindowMode()){
startTimer();
}
}
private void startTimer() {
if (mTimer == null) {
mTimer = new Timer();
}
mTimer.schedule(new TimerTask() {
@Override
public void run() {
mCurrentMulitWindowSecond++;
if (mCurrentMulitWindowSecond > MAX_SECOND) {
this.cancel();
showDialog();
Log.i(TAG, "run: "+mCurrentMulitWindowSecond);
}
}
}, 0, 1000);
}
private void showDialog(){
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
new AlertDialog.Builder(MainActivity.this)
.setTitle("警告")
.setMessage("你处于分屏模式")
.show();
}
},0);
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.i(TAG, "onDestroy: ");
if (mTimer != null) {
mTimer.cancel();
mTimer=null;
}
}
}
三、屏幕高度
为什么要说屏幕高度呢?且往下看。
android适配地点较多,就算简简单单获取屏幕高度都得十分注意。可能常用如下代码获取。
DisplayMetrics outMetrics1 = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(outMetrics1);
Log.i(TAG, "getScreenHeight: "+outMetrics1.heightPixels);
这段代码看似没有问题,实在不然,最终可能会发现比真实高度小了十几个像素,我测试了三台手机,分别是:
小米8 :像素为2248x1080,上述代码获取到是2029。
模拟器:像素为1920x1080,上述代码获取为1776。
华为: 像素为2340x1080,上述代码获取为2255。
这是因为getDisplayMetrics().heightPixels会将虚拟按键的高度忽略掉。所以导致上述情况,还有一个坑。那就是在分屏情况下会更具实际而定,比如下图,会更具当前被用户分配的大小来决定,比如会获取到593,其实这也不是坑,假如一个View想获取屏幕高度,并做一些位置显示逻辑,如果用此方法返回真实的手机像素,并把View显示到那个地方,结果肯定是我们不想要的。
其他方法也是一样,如下面,有些方法过时了,我们就不要去使用他了。
//1
int height1 = getResources().getDisplayMetrics().heightPixels;
//2
Point point = new Point();
getWindowManager().getDefaultDisplay().getSize(point);
int height2=point.y;
//3
int height3 = getWindowManager().getDefaultDisplay().getHeight();
上述情况在分屏情况下会根据被分配大小来计算,不在分屏下会忽略虚拟按键高度。
但是如果用getRealMetrics来获取,不管分不分屏,都返回实际的大小,也就是如2248、1920。所以这两个要使用注意
DisplayMetrics outMetrics1 = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getRealMetrics(outMetrics1);
Log.i(TAG, "getScreenHeight: "+outMetrics1.heightPixels);
四、如何禁止分屏?
在AndroidManifest的application下加入 android:resizeableActivity="false"即可
五、幕后凶手是谁?
知道了如何android如何检测分屏以一些注意事项后,我才开始怀疑这是谁在恶搞我
最后这崽子终于招了,提醒广大小伙伴,见到这种队友往冒烟的扁。
更多推荐
所有评论(0)