实现一个Android锁屏App的难点总结

2023-11-12

http://blog.csdn.net/ldld1717/article/details/69389125

https://segmentfault.com/a/1190000007157971

自定义一个漂亮实用的锁屏app,如果能赢得用户的认可,替换系统自带的锁屏,绝对是一个不小的日活入口。这段时间正好总结一下最近调研的Android平台的锁屏app开发中的难点。

一、前言

锁屏的大概实现原理都很简单。监听系统的亮屏广播,在亮屏的时候展示自己的锁屏界面,用户在锁屏界面上进行一系列的动作才能解锁。有的手机启动锁屏界面的过程会很卡,所以会明显看到亮屏之后锁屏界面的启动有延时,因此也可以选择监听系统灭屏的广播,屏幕关掉的时候就将锁屏界面准备好,直接亮屏展示(灭屏后你的app会比较容易被杀死,这点要注意做保活)。

还需要注意,亮屏和灭屏广播,SCREEN_ON/SCREEN_OFF都是只能动态监听的,所以要另开一个Service来注册,这个Service的自启动和保活也要做好。

基本的实现细节就不多讲了,这篇文章只会讲遇到的几个难点。

二、锁屏实现中的难点

1.屏蔽Home键

既然是锁屏界面,当然只能通过界面上的一些滑动或者输入动作来解开锁屏,不能简单的直接被Home键一按,就解开了。从4.0开始,Home直接在framework层就被系统响应到,强退到桌面,第三方应用里已经无法再通过Activity.onKeyDown方法来监听和拦截Home键,尽管还象征性的保留了Home键的KeyCode来向前兼容,但是Home键按下去,并不会回调这个方法。

除了onKeyDown,有没有其他办法监听Home键,有的。前台App退到后台会有广播ACTION_CLOSE_SYSTEM_DIALOGS,收到广播携带的intent之后,解析里面的"reason"参数,就可以知道退出原因是什么了。home键按下后,reason是"homekey",最近任务键按下后,reason是"recentapps"。

这当然不是最终方案,因为有些三星ROM里并不会有这个广播。而且广播的意思只是通知你一下,人家framework层已经把你的应用退回桌面了,你能监听home键,但没有办法拦截home键。也许想到了可以监听到home键的时候,马上把自己的Activity又重新打开展示,我试了一下,home键按下后startActivity会有延时3秒左右,这应该是Google早就想到了我们会这么干,做了这么一个延时方案。

直接拦截行不通了,想想别的路子。按Home键是让系统退回到Launcher(即桌面启动器),那么如果我们的锁屏Activity本身就是Launcher的话,那按Home键不就等于回到我们的锁屏Activity,也就可以阻止它把锁屏Activity关掉了。

怎么把自己的Activity声明为Launcher,在Activity中添加intent-filter:

<intent-filter>
    <action android:name="android.intent.action.MAIN" />
    <category android:name="android.intent.category.HOME" />
    <category android:name="android.intent.category.DEFAULT" />
</intent-filter>

这样,新安装的app会是一个能够作为launcher的app,所以首次按Home键的时候,就会有弹窗提示你选择要进入哪个launcher,选择我们自己的Activity,这样home键就被我们接管了。

不过这样有一个很明显的问题,如果不在我们的锁屏界面按Home键,同样会进入到锁屏Activity。当然,解决的方式也简单,当我们按Home时进入锁屏Activity的onCreate里做一个判断,如果前一个前台Activity是锁屏Activity,那就不用对Home键处理,如果不是锁屏Activity,那就要关闭锁屏Activity,跳到用户真正的桌面启动器去了。真正的桌面启动器是哪一个,我们可以这样来找:

List<String> pkgNamesT = new ArrayList<String>();
List<String> actNamesT = new ArrayList<String>();
List<ResolveInfo> resolveInfos = context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);  
for (int i = 0; i < resolveInfos.size(); i++) {
    String string = resolveInfos.get(i).activityInfo.packageName;
    if (!string.equals(context.getPackageName())) {//自己的launcher不要      
        pkgNamesT.add(string);
        string = resolveInfos.get(i).activityInfo.name;
        actNamesT.add(string);
    }
}

如果实际的launcher只有一个,那直接跳转过去就可以了:

ComponentName componentName = new ComponentName(pkgName, actName); 
Intent intent = new Intent(); 
intent.setComponent(componentName); 
context.startActivity(intent); 
((Activity) context).finish();

如果手机安装有多个launcher(如360桌面一类的app)就会麻烦一点,需要展示一个列表让用户来选取用哪个launcher,这个在产品形态上可能会让用户觉得有点不解。
现在,如果在其他APP里按一下Home键,会跳到我们的锁屏Activity然后跳转到真正的launcher。这里可能会有Activity闪现一下的场景,影响用户体验。最优的办法其实是另外弄一个Activity来作为Home键跳转的Activity,这个Activity设为透明的,就不会被用户感知。如此,产品形态就变成了,锁屏Activity中按Home键,跳转到透明Activity,跳转回锁屏Activity,相当于Home键无效;其他APP中按Home键,跳转到透明Activity,跳转到真正的桌面。
实现透明的Activity,只需要在xml中声明

android:theme="@android:style/Theme.Translucent.NoTitleBar"

这样的界面是透明的,实际上有占位在屏幕的顶层,所以跳转后记得要finish掉,不然会阻断跳转后的界面的交互。另外,Theme.NoDisplay也能将Activity设置为不可见,而且不占位,但是笔者实现的时候发现,NoDisplay的Activity无法被系统设置为launcher(设置后会弹窗让你重新设置,如此反复)

2.悬浮窗的实现方式

由于受Home键无法直接拦截的限制,Activity实现的锁屏会需要绕较多的路。所以有的锁屏应用会使用悬浮窗来实现,悬浮窗能够无视Home键,在按下home键的时候不会退到后台。所以不需要在home键的问题上纠结。悬浮窗统一由WindowManager来管理,具体的实现比较简单,笔者就不赘述了,有个坑要注意,悬浮窗需要声明权限:

    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

有的手机设置里,默认是不给应用授权悬浮窗使用权的,所以应用里还要考虑引导用户授权悬浮窗使用。

此外,有些应急解锁的场景,比如来电接听,闹铃处理,对于Activity实现的锁屏界面,系统会自动把所有的前台Activity隐藏,让用户直接去处理这些场景。但是悬浮窗会盖住场景,所以遇到这些场景,悬浮窗实现的锁屏界面要自己去处理这些特殊场景的自动解锁。

3.禁用系统锁屏

有了自己的锁屏界面,还需要禁用掉系统的锁屏,以免造成用户需要解锁两次的局面。
首先我们需要知道用户是否设置了锁屏,方法如下:
对于API Level 16及以上SDK,可以使用如下方法判断是否有锁:

((KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE)).isKeyguardSecure()

对API Level 15及以下SDK,可以使用反射来判断:

try {
    Class<?> clazz = Class.forName("com.android.internal.widget.LockPatternUtils");
    Constructor<?> constructor = clazz.getConstructor(Context.class);
    constructor.setAccessible(true);
    Object utils = constructor.newInstance(this);
    Method method = clazz.getMethod("isSecure");
    return (Boolean) method.invoke(utils);
}catch (Exception e){
    e.printStackTrace();
}

好了,得知用户设置了系统锁屏,怎么关掉呢?有前人建议了这种方法

KeyguardManager km = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
KeyguardManager.KeyguardLock keyguardLock = km.newKeyguardLock("");
keyguardLock.disableKeyguard();

需要权限

<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />

但经笔者测验,这种方法只能禁用滑动锁,如果用户设置的是图案或者PIN的锁的话,是无法直接取消的。禁用掉密码锁或者图案锁是一个很危险的行为,基于此,Google应该是不会把它开放给开发者的,所以现在的锁屏应用的禁用锁的办法,都是直接跳到系统锁屏设置界面,直接引导用户去手动关闭。可以通过如下代码跳到用户锁屏设置界面:

Intent in = new Intent(Settings.ACTION_SECURITY_SETTINGS);
startActivity(in);

这个也会有些许的兼容性问题,比如,360手机的ROM并没有把设置系统锁屏的功能放在安全设置中,所以打开安全设置的界面找不到取消系统锁屏的地方,这个在一众锁屏应用中并没有做兼容。

三、附加功能中的难点

上面的功能都是直接针对锁屏本身的实现来说的。锁屏应用除了本身能够有“锁住屏幕”的功能外,还应该有其他一些漂亮又实用的功能,最起码应该是尽量往系统锁屏的样式上靠拢并发挥,才方便被用户接受。

1.获取通知

新的Notification到来时应该展示在锁屏界面上,所以我们需要对通知栏进行监听。从android 4.3(api 18)开始,Google给我们提供了一个NotificationListenerService类,第三方应用可以更方便的获得通知栏使用权(Notification Access),当然,这么敏感的权限得要应用自己声明,同时还要引导用户手动授权。如下,建立一个NotificationMonitor类继承于NotificationListenerService,并声明权限:

<service android:name=".NotificationMonitor"
    android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
    <intent-filter>
        <action android:name="android.service.notification.NotificationListenerService" />
    </intent-filter>
</service>

然后同引导用户关闭系统锁屏一样,要引导用户来授权通知栏使用权:

startActivity(new Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS));

可以通过如下代码检查到通知栏使用权是否已经拿到:

private boolean isNotificationListenEnabled(){
        String pkgName = getPackageName();
        final String flat = Settings.Secure.getString(getContentResolver(),
                "enabled_notification_listeners");
        if (!TextUtils.isEmpty(flat)) {
            final String[] names = flat.split(":");
            for (int i = 0; i < names.length; i++) {
                final ComponentName cn = ComponentName.unflattenFromString(names[i]);
                if (cn != null) {
                    if (TextUtils.equals(pkgName, cn.getPackageName())) {
                        return true;
                    }
                }
            }
        }
        return false;
    }

拿到通知栏使用权后,系统通知栏的变化就可以在NotificationMonitor里面监听到了:

public class NotificationMonitor extends NotificationListenerService {
    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return super.onStartCommand(intent,flags,startId);
    }

    //新的Notification到达
    @Override
    public void onNotificationPosted(StatusBarNotification sbn) {
        super.onNotificationPosted(sbn);
    }

    //新的Notification到达,api 21新增
    @Override
    public void onNotificationPosted(StatusBarNotification sbn, RankingMap rankingMap) {
        super.onNotificationPosted(sbn, rankingMap);
    }

    //Notification被移除
    @Override
    public void onNotificationRemoved(StatusBarNotification sbn) {
        super.onNotificationRemoved(sbn);
    }

    //Notification被移除,api 21新增
    @Override
    public void onNotificationRemoved(StatusBarNotification sbn, RankingMap rankingMap) {
        super.onNotificationRemoved(sbn, rankingMap);
    }

    //Notification排序变动,api 21新增
    @Override
    public void onNotificationRankingUpdate(RankingMap rankingMap) {
        super.onNotificationRankingUpdate(rankingMap);
    }

    //Service与系统通知栏完成绑定时回调,绑定后才能收到通知栏回调,api 21新增
    @Override
    public void onListenerConnected() {
        super.onListenerConnected();
    }
}

同时,NotificationListenerService还提供了cancelNotification和cancelAllNotification方法,用于移除通知栏的通知,可以很方便的实现在自定义的锁屏界面移除掉通知了。

笔者实现这个类的时候发现了一个坑,所有的代码都是OK的,通知栏使用权也授权了,但是来通知时始终没有回调onNotificationPosted,查问题查了很久,后来看到网上有人遇到同样的问题,另外新建了一个类把代码复制过去,就OK了,这样看来应该是编译器的问题。

获取了通知栏使用权的Service天然就能被保活,如果被杀死,Android系统能够将它重启。所以平时看到一些应用要求获取通知栏使用权时,要注意这类应用会永久驻存后台的。当然,如果这个Service所在进程崩溃达到一定次数的话,Android系统也会灰心,在下次关机重启前不会再将Service重启,所以,开发中最好能将这个Service放在一个轻量独立的进程中。

2.获取HotSeat区快捷方式

桌面快捷方式分为两类,Desktop区,指随着屏幕滚动的那部分,HotSeat区,指放置于桌面底部不随屏幕滚动的部分。用户自定义的HotSeat区里的快捷方式属于常用的应用。如果能够在锁屏界面也添加这部分的快捷启动,会是一个比较友好的功能。这个的主要问题是,怎么获取到HotSeat区的快捷方式呢。

系统快捷方式存储在数据库文件launcher.db中的favorites表中,如图所示:
可以看到有对应的快捷方式的id,title和intent,这个Container属性是用来指示所在文件夹的id,然而可以看到有的container为负数。这是为什么,笔者查看了一下Android Launcher相关的源码,找到这么两句:

/**
* The icon is a resource identified by a package name and an integer id.
*/
public static final int CONTAINER_DESKTOP = -100;
public static final int CONTAINER_HOTSEAT = -101;

也就是说,container为-100的是Desktop区的快捷方式,container为-101的正是要找的HotSeat区的快捷方式。
现在知道了快捷方式的存储方式,接下来的问题就是去找launcher.db文件的路径。
在不同版本的Android原生api中,由于默认使用的launcher启动器的包名不一样,launcher.db存储的路径也不一样。

Android API 7及以下:/data/data/com.android.launcher/databases/laucher.db
Android API 8~18:/data/data/com.android.launcher2/databases/laucher.db
Android API 19及以上:/data/data/com.android.launcher3/databases/laucher.db

而对于各式各样的第三方ROM,使用了千奇百怪的laucher包名,这个路径就更乱了:

HTC: /data/data/com.htc.launcher/databases/laucher.db
360: /data/data/net.qihoo360.launcher/databases/laucher.db
华为: /data/data/com.huawei.launcher3/databases/laucher.db
小米: /data/data/com.miui.mihome2/databases/laucher.db
...

当然,我们不会通过直接读取数据库的方式来获取快捷方式的信息,系统自带的laucher会提供ContentProvider给外部读取。避开了对数据库路径做兼容的大坑,转眼就掉进了另一个大坑,通过Provider来读取快捷方式,所需要的权限和URI也需要做兼容。

从快捷方式的存储可见,Android 的碎片化是多么的严重,所以最后笔者决定不再深入去兼容实现,这是得不偿失的行为,有兴趣实现的可以看看这篇文章,判断一个快捷方式是否存在是多么的难:http://www.jianshu.com/p/dc3d...

3.获取壁纸

锁屏界面的背景和手机桌面壁纸保持一致,不至于让用户觉得突兀,这里有两种办法实现获取壁纸。

Activity Style模式

如果是Activity实现的锁屏界面,可以直接设置Activity的theme就可以用壁纸做背景了。

android:theme="@android:style/Theme.Wallpaper.NoTitleBar"

WallPaperManager模式

悬浮窗模式的锁屏界面无法用theme,那么可以通过WallPaperManager来获取壁纸。

// 获取壁纸管理器
WallpaperManager wallpaperManager = WallpaperManager
                .getInstance(this);
// 获取当前壁纸
Drawable wallpaperDrawable = wallpaperManager.getDrawable();
// 将Drawable,转成Bitmap
Bitmap bm = ((BitmapDrawable) wallpaperDrawable).getBitmap();
mRootView.setBackgroundDrawable(new BitmapDrawable(bm));

这种方式在小米等仿iOS的一屏桌面上是OK的,但是在原生Android那样的两屏桌面(快捷方式与全部app分别在不同屏),快捷方式那屏获取的壁纸是一整张大壁纸,而实际laucher显示的是切割后的壁纸。所以以上方式会把尺寸不符的壁纸设为了背景。需要自己去根据laucher的屏数和当前是第几屏来进行切图,laucher的总屏数可以在上述launcher.db里的workspaceScreens表里找到,而具体当前在第几屏是存在launcher app内存实例中的,无法获取。如果真要切的话,建议直接按照屏幕宽高切下整张壁纸的左边一屏就好了。


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

实现一个Android锁屏App的难点总结 的相关文章

  • Kotlin1.8新特性

    Kotlin1 8 0新特性 新特性概述 JVM 的新实验性功能 递归复制或删除目录内容 提升了 kotlin reflect 性能 新的 Xdebug 编译器选项 提供更出色的调试体验 kotlin stdlib jdk7 与 kotli
  • Android file类使用详解

    一 Android file类 在开发Android应用时免不了会跟文件打交道 本篇文章记录总结自己常用到的文件操作 数据的存储有多种方式 比如数据库存储 SharedPreferences存储 文件存储等 这里我们将要介绍最简单的文件存储
  • ViewPager 详解(二)---详解四大函数

    http blog csdn net harvic880925 article details 38487149
  • 【Android】WebView控件最全使用解析

    WebView控件最全使用解析 一 WebView 概述 二 WebView使用基础篇 2 1添加方式 2 2 加载远程网页 2 3 加载本地网页 2 4 加载HTML片段 2 5 WebView 常用方法 三 WebView 进阶篇 3
  • 耗时操作ANR和handler

    耗时操作 1 什么是ANR 在应用程序的主线程中执行一段耗时的代码 就有可能出现ANR异常 耗时的代码未执行结束时 界面会卡住 用户对界面进行了操作 10秒之后耗时代码如果还未结束 就会出现ANR异常 2 怎么避免ANR 主线程中不要执行耗
  • Android(java方法)上实现mp4的分割和拼接 (二)

    http blog csdn net banking17173 article details 20646251 这节谈一下如何在Android上实现mp4文件的高效率切割 业务需求举例 把一段2分钟的mp4文件切割出00 42 至 01
  • Android Studio连接夜神模拟器

    Android Studio连接夜神模拟器 一 下载夜神模拟器 二 夜神模拟器连接Android Studio 三 其他操作 3 1 屏幕旋转 3 2 创建其他模拟器 一 下载夜神模拟器 官网 https www yeshen com 下载
  • 设置ImageButton的点击效果

    我要设置一个ImageButton的点击效果 普通状态背景透明 按下状态有一个背景图 src是一个图片 如下所示
  • Android Service最全面的解析

    本篇文章再次来自 刘明渊 话说刘明渊已经是我公众号的老熟人了 这是第三次发表他投稿的文章 前两篇关于Intent的译文都广受大家好评 而本篇对于Service的译文同样精彩 其实像这种官方文档翻译类文章的投稿我都是非常欢迎的 因为官方文档的
  • Android项目JNI层C/C++文件中添加LOG信息

    第一步 在项目的mk文件中加入 LOCAL LDLIBS llog 第二步 在要添加LOG的cpp文件中引入一个头文件和添加一个定义 include
  • Layout的放大和缩小效果例子(ScaleAnimation)

    个Layout从中心放大和缩小的例子 直接上代码 1 ScaleDialog java文件 Java代码 package cn com import android app Activity import android graphics
  • AIDL原理和相关文件解析

    Binder概述 相信从事Android相关的研发人员 都对Binder有个或多或少的了解 相关技术博客也有一大推 我今天对Binder的学习过程进行一个记录 理论性的叙述会少一点 更多的是基于AS自动生成的AIDL文件进行代码分析 但读者
  • Android基础学习(十七)—— Retrofit

    Retrofit本身并没有提供网络访问的能力 但是它底层封装了OkHttp 也是由Square公司贡献的一个处理网络请求的开源项目 A type safe HTTP client for Android and Java https git
  • hint和输入都是在EditText的左上角

    2012 8 8 09 59 55 上传 下载附件 2 16 KB 如何实现这种效果 hint和输入都是在EditText的左上角 android gravity top left
  • C/C++在Android开发中的应用

    JNI开发系列阅读 JNI与底层调用1 http blog csdn net axi295309066 article details 60758515 JNI与底层调用2 http blog csdn net axi295309066 a
  • 广播接收者两种注册方式及优缺点

    两种注册方式 静态注册 在清单文件中配置
  • adb logcat命令查看并过滤android输出log

    http blog csdn net hansel article details 38088583 cmd命令行中使用adb logcat命令查看Android系统和应用的log dos窗口按ctrl c中断输出log记录 logcat日
  • 【Android】DataBinding 最全使用解析

    DataBinding 最全使用解析 一 DataBinding 概述 二 基本用法 2 1 使用入门 2 2 布局和绑定表达式 2 3 事件绑定 2 4 单向绑定 2 5 双向绑定 三 高级用法 BindingAdapter 一 Data
  • Android四大组件-BroadcastReceiver、ContentProvider、Service

    目录 一 BroadcastReceiver 1 定义 2 作用 3 生命周期 4 广播注册方式 动态注册 静态注册 5 广播类型 普通广播 即发出广播后所有接收者都能收 有序广播 按照广播的优先级接受 broadcastReceiver可
  • HTTP文件断点续传原理解析(源码)

    生活中 有许多事物 在没有被揭开面纱之前 我们往往会觉得很神秘很高深 认为它一定很难 进而望而却步 失去了解它的机会 然而 很多事 只要我们自己能沉下心来 细细研究 那些神秘高深的 也会变得简单明了 HTTP文件断点续传 就是这样一个好例子

随机推荐

  • Connect函数阻塞

    1 采用select 在学习嵌入式Linux网络编程中 很多同学都发现了一个问题 那就是调用connect函数时 如果服务端关闭 客户 端调用connect 函数时 发现阻塞在那里 而且利用ctrl c信号去停止客户端程序时 需要等待一个较
  • git:一次回滚多个commit

    说明 独立分散的commit共同回滚 git revert n sha 1 git 单次commit对应的sha 1值 sha 1 sha 1 ps n代表不会生成新的commit 如果想直接生成commit请去掉 n 最近连续的coomi
  • hr谈薪资后说请示领导_如何巧妙回答面试中的薪资问题呢?

    好不容易挺过了群面 单面 没想到在HR面被薪资问题打个措手不及 你的期望薪资是多少 说低了总觉得委屈自己 说高了又怕offer不保 好不容易在前面几轮面试积攒的自信 在这个问题上就变成 emm差不多就行吧 然后面试一结束就开始无限后悔 对于
  • 【ML特征工程】第 1 章 :机器学习管道

    大家好 我是Sonhhxg 柒 希望你看完之后 能对你有所帮助 不足请指正 共同学习交流 个人主页 Sonhhxg 柒的博客 CSDN博客 欢迎各位 点赞 收藏 留言 系列专栏 机器学习 ML 自然语言处理 NLP 深度学习 DL fore
  • STM32F407 单片机+DMA+环形缓冲区+GPS报文解析

    本文采用DMA 环形缓冲区对GPS报文进行解析 思路是通过DMA中断接收到GPS报文后 存放到环形缓冲区 然后在主程序中解析GPS报文 解析GPS报文的关键是 将环形缓冲区中的字节转换成字符串 然后在字符串中查找GPS报文头标识 例如 GP
  • Block头部解析

    Block解析介绍了Block的各个组成部分 魔法数 块大小 块头部 交易个数 交易 本文将详细介绍块魔法数和块头部的各个组成部分 魔法数 魔法数是比特币客户端解析Block数据时的识别码 比特币正式网络的魔法数是0xD9B4BEF9 不同
  • 地图标识符号大全_资源小结:分省地图查询(9.1版)

    公众号首页回复关键字 分省地图 或通过菜单栏可以快速找到本页 本页内容不断更新 建议收藏起来备查 北京市 北京市最新行政区划图 行政统计表 图集下载 北京市地图集 分区 北京市人文地图 高清版 北京经典旅游线路图 北京城区地图 一亿像素高清
  • vue3和ts使用

    Vue3和TypeScript是两个非常流行的前端技术 它们都有着自己的优点和特点 Vue3是Vue js的最新版本 它带来了很多新的特性和改进 包括更好的性能 更好的开发体验和更好的可维护性 TypeScript是一种静态类型语言 它可以
  • 一文搞懂STM32 PWM配置

    本文主要介绍通过CubeMX对STM32G070CBT6进行配置生成PWM波 内容包括PWM的基本概念 PWM的应用 PWM产生的方法 STM32 PWM波配置详解 1 PWM PWM 英文名Pulse Width Modulation 是
  • 02-不得不了解的js特性

    一 回顾js特性 针对浏览器端js 它有哪些特性 弱类型 解释型 1 弱类型 所谓强类型 就意味着在声明变量的时候 需要确定数据类型 一经确定就不能改变 而弱类型 在声明变量的时候 是无需声明变量的类型 变量的类型有其值来决定 并且是可以随
  • 使用pyecharts出现 'ModuleNotFoundError: No module named 'pyecharts_snapshot' 异常

    使用pyecharts时 出现 ModuleNotFoundError No module named pyecharts snapshot 试了几次都无法解决 突然想到 pyecharts snapshot 会不会也是一个第三方库 毕竟异
  • MySQL 列属性修改操作

    1 mysql中修改字段长度 sql view plain copy ALTER TABLE tb article MODIFY COLUMN NAME VARCHAR 50 这里的tb article为表名 NAME为字段名 50为修改后
  • Vue 组件的单元测试

    1 基本的示例 单元测试是软件开发非常基础的一部分 单元测试会封闭执行最小化单元的代码 使得添加新功能和追踪问题更容易 Vue 的单文件组件使得为组件撰写隔离的单元测试这件事更加直接 它会让你更有信心地开发新特性而不破坏现有的实现 并帮助其
  • [docker]笔记-网络管理

    1 docker网络原理 docker安装完成后 会在宿主机中创建一个虚拟网桥 用于容器之间和容器与外部网络的连接 虚拟网桥通常名称为docker0 可以使用ip link show命令进行查看 在docker中 各个容器是通过这个dock
  • 虚拟+现实

    随着现代信息技术与软硬件技术的快速发展 嵌入式系统的功能日益强大 嵌入式设备和软件应用领域越来越宽泛 近年来 嵌入式软件代码量呈爆炸式增长 对测试的要求越来越高 尤其是涉及防务 航空 汽车等安全关键领域 半实物仿真测试系统的研制难度适中 投
  • 合宙Air103

    基础资料 基于Air103开发板 Air103 LuatOS 文档 上手 开发上手 LuatOS 文档 探讨重点 对官方I2C demo中功能的复现 进行相关内容的学习及探讨 实现功能 功能2 三轴加速度陀螺仪 MPU6050模块 硬件准备
  • Typora+PicGo-Core上传服务设置

    一 Typora中安装PicGo Core 二 安装插件 Win10为例 首先点击验证图片上传选项根据提示找到安装路径 我的路径为C Users 86137 AppData Roaming Typora picgo win64 picgo
  • Qt5.14版本通用环境配置安装——最详细教学(看不懂,你怪我)

    大家好 我是会飞的鱼 blog 今天我来给大家介绍一下Qt5 14 1安装 有不足之处 请大家多多指教 感谢大家支持 目录 前言 安装文件下载 安装 设置 QtCreator 编译路径 设置 Qt 源码路径 以上就是全部安装步骤 已经完成
  • moxa串口服务器型号,moxa串口服务器产品配置说明

    moxa串口服务器产品配置说明 内容精选 换一换 为弹性云服务器配置的安全组规则未生效 以下排查思路根据原因的出现概率进行排序 建议您从高频率原因往低频率原因排查 从而帮助您快速找到问题的原因 如果解决完某个可能原因仍未解决问题 请继续排查
  • 实现一个Android锁屏App的难点总结

    http blog csdn net ldld1717 article details 69389125 https segmentfault com a 1190000007157971 自定义一个漂亮实用的锁屏app 如果能赢得用户的认