安卓收银机开发笔记

作者: aJIEw | 来源:发表于2018-07-29 12:30 被阅读173次
    Summer Wind

    前言:记录下自己在收银机开发过程中的一些心得笔记,此博客长期更新。

    00 收银机开发和普通安卓手机应用开发的区别

    个人觉得,最大的区别就是,屏幕空间变大了,一屏之内可展示的内容变多了。其实不仅仅是屏幕空间变大了,也由原来的习惯看竖屏到习惯看横屏了。另外需要做的适配工作也简单很多,因为收银机屏幕分辨率和屏幕大小都差不多,几乎不需要做特殊的适配,而且你甚至可以更改屏幕密度!下面会说到。

    还有一点就是,不再需要担心应用保活的问题了,因为基本上安装到商家的收银机上之后,我们的应用就是主角,所以可供我们发挥的空间就大了。另外诸如开机自启、系统敏感权限等,这些都不是事儿~

    虽然少了很多限制,但还是想说,安全对一款收银机应用来说还是非常重要的,比如怎样保证应用的数据安全以及网络安全,这些都是目前还没来得及做、未来需要完善的。

    01 应用全屏

    PART 1

    一般来说,我们的收银机应用大多数时候都应该占满屏幕,所以需要用到全屏模式:

    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
        <item name="android:windowAnimationStyle">@style/notAnimation</item>
        <item name="android:windowFullscreen">true</item>
        <item name="android:windowContentOverlay">@null</item>
    </style>
    

    可以看到我们使用了 Theme.AppCompat.Light.NoActionBar 作为父主题,然后覆盖了 android:windowFullscreenandroid:windowContentOverlay 属性,前者用于隐藏状态栏,后者用于消除包裹应用 content 的 drawable(通常是标题下的阴影),参考 windowContentOverlay

    PART 2

    当然,这些只是最基本的,我们还需要处理 activity 配置发生改变的情况,在 activity 下添加:

    android:configChanges="orientation|screenSize|keyboardHidden"
    

    这样,我们就告诉系统当 activity 屏幕方向或者键盘可见性发生变化后不要退出重启 activity,因为收银机应用几乎所有 activity 屏幕方向都应该是水平的。

    另外关于键盘,还需要在 activity 中加上 android:windowSoftInputMode="stateHidden|adjustPan" 属性,stateHidden 表明当用户初次进入 activity 的时候,键盘不会显示出来(一般只有在登录界面才会需要键盘一开始就显示),而 adjustPan 则会在键盘显示出来的时候自动调整 UI 内容,让用户始终可以看到他们输入的内容而不是被键盘覆盖掉。

    所以 AndroidManifest 中我们的 activity 大多数是这样配置的:

    <activity
        android:configChanges="orientation|keyboardHidden|screenSize"
        android:screenOrientation="landscape"
        android:windowSoftInputMode="stateHidden|adjustPan" />
    

    具体参数介绍请看 <activity>

    PART 3

    这些就够了吗?当然不是!通常,我们还需要在我们的 BaseActivity 中做如下配置:

    //开启全屏
    final int fullScreenFlags = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
            | View.SYSTEM_UI_FLAG_FULLSCREEN //hide statusBar
            | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
            | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION //hide navigationBar
            | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
            | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
    
    final Window window = getWindow();
    window.getDecorView().setSystemUiVisibility(fullScreenFlags);
    window.getDecorView().setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener() {
        @Override
        public void onSystemUiVisibilityChange(int visibility) {
            window.getDecorView().setSystemUiVisibility(fullScreenFlags);
        }
    });
    

    可以看到我们给 DecorView 设置了一些 Visibility 的 Flag, 首先是隐藏状态栏和导航栏,然后是 View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY 用于沉浸模式,也就是使状态栏变得半透明,同时接受屏幕边缘的滑动事件(通常这类事件是由系统处理掉的)。文档上是这么写的:

    While in sticky immersive mode, if the user swipes from an edge with a system bar, system bars appear but they're semi-transparent, and the touch gesture is passed to your app so it app can also respond to the gesture.

    然后是 View.SYSTEM_UI_FLAG_LAYOUT_STABLE 用于保证你的布局全屏,不会因为系统栏的显示而重新调整大小。具体请参考文档:Enable fullscreen mode

    PART 4

    除此之外,我们还应该考虑到一些特殊情况,比如显示 dialog 或者用户输入的情况下,这些时候导航栏都会显示出来,所以通常我们还会写这么一个方法:

    public void enterFullScreen(Window window) {
        window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
        window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE | WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
        int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
            | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
            | View.SYSTEM_UI_FLAG_LAYOUT_STABLE
            | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
            | View.SYSTEM_UI_FLAG_FULLSCREEN;
        window.getDecorView().setSystemUiVisibility(uiOptions);
    }
    

    然后在显示 dialog 或者其他一些有可能触发导航栏显示的地方调用下这个方法,这样就能保证始终全屏啦。另外对于监听键盘输入,推荐一个三方库:KeyboardVisibilityEvent,使用起来非常方便,只要在 activity 初始化的地方调用:

    KeyboardVisibilityEvent.setEventListener(this,
        new KeyboardVisibilityEventListener() {
            @Override
            public void onVisibilityChanged(boolean isOpen) {
                UIHelper.create().enterFullScreen(getWindow());
            }
    });
    

    这样当用户使用键盘输入的时候,我们可以保证始终全屏显示。

    最后,也许有人会有疑问,如果我们的应用开机自启,而且始终全屏,那不是无法回到桌面了吗?其实不用担心,我们可以自己设置一个按钮,提供回到桌面的功能,比如当用户点击右下角显示当前时间的地方。是不是听起来有点熟悉?没错,就是受到了 windows 的启发�(´ω`)。

    02 修改收银机主屏幕密度

    PART 1

    首先说明下,这种方式只针对使用瑞芯芯片的收银机才有效(不过好像收银机主板使用这个芯片还是蛮多的,至少从我们公司订购的几批机器上来看的确很多厂家都在用这个芯片),可以用以下命令检查是否是支持修改:

    adb shell cat /system/build.prop | grep ro.sf.lcd_density
    

    如果存在该属性则证明可以修改。下面是步骤:

    1. /system/build.prop 文件拉到本地,使用 adb 命令:
    adb pull /system/build.prop ./
    
    1. 打开 build.prop 文件,找到 ro.sf.lcd_density 属性,这个属性就是用来指定屏幕密度的,直接修改成我们想要的密度就可以了,默认是 160,我们可以修改为 240。个人觉得,对于一般收银机来说,这是看着最舒服的:
    #set default lcd density to Rockchip tablet
    ro.sf.lcd_density=240
    
    1. 将修改完毕后的文件覆盖掉原文件,当然首先要将 /system 挂载为可读写再覆盖:
    adb root
    adb shell mount -o rw,remount /system
    adb push build.prop /system/
    
    1. 最后不要忘记修改 /system 为只读:
    adb shell mount -o ro,remount /system
    adb shell reboot
    

    最后,当机子重启完毕,新的屏幕密度就已经起作用了。

    PART 2

    当然,上面这些步骤对于安卓开发来说没难度,但是对于运维来说,其实还是挺麻烦的,所以写了个 batch 脚本(运维用Windows -_-||),只要用数据线连接上收银机,双击运行下就ok了,我是不是很棒~

    Github 地址:ChangeDensity-win-batch


    喜欢我的文章就用你最喜欢的手指点个赞吧~ (づ ̄3 ̄)づ╭❤~

    相关文章

      网友评论

        本文标题:安卓收银机开发笔记

        本文链接:https://www.haomeiwen.com/subject/phpzmftx.html