Android开机动画

Android开机动画

  • 1、BootLoader开机图片
  • 2、Kernel开机图片
  • 3、系统启动时(BootAnimation)动画
    • 3.1 bootanimation.zip位置
    • 3.2 bootanimation启动
    • 3.3 SurfaceFlinger启动bootanimation
    • 3.4 播放开机动画playAnimation
    • 3.6 开机动画退出检测
    • 3.7 简易时序图
  • 4、bootanimation.zip文件

android12-release
推荐 Android 12 开机动画代码与流程详解


在这里插入图片描述

1、BootLoader开机图片

一般使用rle格式图片;例如放在splash分区

adb reboot bootloader
fastboot flash splash splash.img
fastboot reboot

2、Kernel开机图片

记录 kernel/drivers/video/msm/msm_fb.c 也是读出根目录下的xx.rle,并显示为开机画面

3、系统启动时(BootAnimation)动画

使用BootAnimation程序显示开机画面,如需修改开机画面,不用修改代码,只需按格式要求做bootanimation.zip包,放在系统的/system/media目录中,或/oem/media/product/media等目录。

代码路径:frameworks/base/cmds/bootanimation

3.1 bootanimation.zip位置

frameworks/base/cmds/bootanimation/BootAnimation.cpp,例如bootanimation.zip
在这里插入图片描述

3.2 bootanimation启动

frameworks/base/cmds/bootanimation/Android.bp
frameworks/base/cmds/bootanimation/bootanim.rc
frameworks/base/cmds/bootanimation/bootanimation_main.cpp
frameworks/base/cmds/bootanimation/BootAnimation.cpp
frameworks/base/cmds/bootanimation/BootAnimationUtil.cpp

SurfaceFlinger进程名:bootanim
bin文件:/system/bin/bootanimation
对应启动入口:/frameworks/base/cmds/bootanimation/bootanimation_main.cpp

bootAnimationDisabled()检测系统属性(debug.sf.nobootanimation、ro.boot.quiescent、ro.bootanim.quiescent.enabled),noBootAnimation 是否启动开机动画。注意init进程在启动bootanimation服务是disable的,不会主动将应用程序bootanimation启动起来。启动bootanimation是从surfaceFlinger这边来启动的

frameworks/base/cmds/bootanimation/bootanimation_main.cpp

int main()
{setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_DISPLAY);bool noBootAnimation = bootAnimationDisabled();ALOGI_IF(noBootAnimation,  "boot animation disabled");if (!noBootAnimation) {sp<ProcessState> proc(ProcessState::self());ProcessState::self()->startThreadPool();// create the boot animation object (may take up to 200ms for 2MB zip)sp<BootAnimation> boot = new BootAnimation(audioplay::createAnimationCallbacks());waitForSurfaceFlinger();boot->run("BootAnimation", PRIORITY_DISPLAY);ALOGV("Boot animation set up. Joining pool.");IPCThreadState::self()->joinThreadPool();}return 0;
}

frameworks/base/cmds/bootanimation/BootAnimationUtil.cpp

bool bootAnimationDisabled() {char value[PROPERTY_VALUE_MAX];property_get("debug.sf.nobootanimation", value, "0");if (atoi(value) > 0) {return true;}property_get("ro.boot.quiescent", value, "0");if (atoi(value) > 0) {// Only show the bootanimation for quiescent boots if this system property is set to enabledif (!property_get_bool("ro.bootanim.quiescent.enabled", false)) {return true;}}return false;
}

3.3 SurfaceFlinger启动bootanimation

SurfaceFlinger启动-Android12 初始化时候 mStartPropertySetThread->Start() 在线程中设置property_set("ctl.start", "bootanim")启动开机动画

/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
frameworks/native/services/surfaceflinger/StartPropertySetThread.cpp

#include <cutils/properties.h>
#include "StartPropertySetThread.h"namespace android {StartPropertySetThread::StartPropertySetThread(bool timestampPropertyValue):Thread(false), mTimestampPropertyValue(timestampPropertyValue) {}status_t StartPropertySetThread::Start() {return run("SurfaceFlinger::StartPropertySetThread", PRIORITY_NORMAL);
}bool StartPropertySetThread::threadLoop() {// Set property service.sf.present_timestamp, consumer need check its readinessproperty_set(kTimestampProperty, mTimestampPropertyValue ? "1" : "0");// Clear BootAnimation exit flagproperty_set("service.bootanim.exit", "0");property_set("service.bootanim.progress", "0");// Start BootAnimation if not startedproperty_set("ctl.start", "bootanim");// Exit immediatelyreturn false;
}} // namespace android

3.4 播放开机动画playAnimation

  • result = android()android原生动画;result = movie()自动动画
  • playAnimation(*mAnimation)播放动画;releaseAnimation(mAnimation)释放动画资源
  • 播放动画过程:initTexture(frame.map, &w, &h)drawClock(animation.clockFont, part.clockPosX, part.clockPosY)drawProgress(lastDisplayedProgress, animation.progressFont, posX, posY)checkExit()
  • checkExit()检测属性"service.bootanim.exit"退出动画
bool BootAnimation::threadLoop() {bool result;// We have no bootanimation file, so we use the stock android logo// animation.if (mZipFileName.isEmpty()) {result = android();} else {result = movie();}mCallbacks->shutdown();eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);eglDestroyContext(mDisplay, mContext);eglDestroySurface(mDisplay, mSurface);mFlingerSurface.clear();mFlingerSurfaceControl.clear();eglTerminate(mDisplay);eglReleaseThread();IPCThreadState::self()->stopProcess();return result;
}
bool BootAnimation::movie() {if (mAnimation == nullptr) {mAnimation = loadAnimation(mZipFileName);}if (mAnimation == nullptr)return false;// mCallbacks->init() may get called recursively,// this loop is needed to get the same resultsfor (const Animation::Part& part : mAnimation->parts) {if (part.animation != nullptr) {mCallbacks->init(part.animation->parts);}}mCallbacks->init(mAnimation->parts);bool anyPartHasClock = false;for (size_t i=0; i < mAnimation->parts.size(); i++) {if(validClock(mAnimation->parts[i])) {anyPartHasClock = true;break;}}if (!anyPartHasClock) {mClockEnabled = false;}// Check if npot textures are supportedmUseNpotTextures = false;String8 gl_extensions;const char* exts = reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS));if (!exts) {glGetError();} else {gl_extensions.setTo(exts);if ((gl_extensions.find("GL_ARB_texture_non_power_of_two") != -1) ||(gl_extensions.find("GL_OES_texture_npot") != -1)) {mUseNpotTextures = true;}}// Blend required to draw time on top of animation frames.glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);glShadeModel(GL_FLAT);glDisable(GL_DITHER);glDisable(GL_SCISSOR_TEST);glDisable(GL_BLEND);glBindTexture(GL_TEXTURE_2D, 0);glEnable(GL_TEXTURE_2D);glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);bool clockFontInitialized = false;if (mClockEnabled) {clockFontInitialized =(initFont(&mAnimation->clockFont, CLOCK_FONT_ASSET) == NO_ERROR);mClockEnabled = clockFontInitialized;}initFont(&mAnimation->progressFont, PROGRESS_FONT_ASSET);if (mClockEnabled && !updateIsTimeAccurate()) {mTimeCheckThread = new TimeCheckThread(this);mTimeCheckThread->run("BootAnimation::TimeCheckThread", PRIORITY_NORMAL);}playAnimation(*mAnimation);if (mTimeCheckThread != nullptr) {mTimeCheckThread->requestExit();mTimeCheckThread = nullptr;}if (clockFontInitialized) {glDeleteTextures(1, &mAnimation->clockFont.texture.name);}releaseAnimation(mAnimation);mAnimation = nullptr;return false;
}
bool BootAnimation::playAnimation(const Animation& animation) {const size_t pcount = animation.parts.size();nsecs_t frameDuration = s2ns(1) / animation.fps;SLOGD("%sAnimationShownTiming start time: %" PRId64 "ms", mShuttingDown ? "Shutdown" : "Boot",elapsedRealtime());int fadedFramesCount = 0;int lastDisplayedProgress = 0;for (size_t i=0 ; i<pcount ; i++) {const Animation::Part& part(animation.parts[i]);const size_t fcount = part.frames.size();glBindTexture(GL_TEXTURE_2D, 0);// Handle animation packageif (part.animation != nullptr) {playAnimation(*part.animation);if (exitPending())break;continue; //to next part}// process the part not only while the count allows but also if already fadingfor (int r=0 ; !part.count || r<part.count || fadedFramesCount > 0 ; r++) {if (shouldStopPlayingPart(part, fadedFramesCount, lastDisplayedProgress)) break;mCallbacks->playPart(i, part, r);glClearColor(part.backgroundColor[0],part.backgroundColor[1],part.backgroundColor[2],1.0f);// For the last animation, if we have progress indicator from// the system, display it.int currentProgress = android::base::GetIntProperty(PROGRESS_PROP_NAME, 0);bool displayProgress = animation.progressEnabled &&(i == (pcount -1)) && currentProgress != 0;for (size_t j=0 ; j<fcount ; j++) {if (shouldStopPlayingPart(part, fadedFramesCount, lastDisplayedProgress)) break;processDisplayEvents();const int animationX = (mWidth - animation.width) / 2;const int animationY = (mHeight - animation.height) / 2;const Animation::Frame& frame(part.frames[j]);nsecs_t lastFrame = systemTime();if (r > 0) {glBindTexture(GL_TEXTURE_2D, frame.tid);} else {if (part.count != 1) {glGenTextures(1, &frame.tid);glBindTexture(GL_TEXTURE_2D, frame.tid);glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);}int w, h;initTexture(frame.map, &w, &h);}const int xc = animationX + frame.trimX;const int yc = animationY + frame.trimY;Region clearReg(Rect(mWidth, mHeight));clearReg.subtractSelf(Rect(xc, yc, xc+frame.trimWidth, yc+frame.trimHeight));if (!clearReg.isEmpty()) {Region::const_iterator head(clearReg.begin());Region::const_iterator tail(clearReg.end());glEnable(GL_SCISSOR_TEST);while (head != tail) {const Rect& r2(*head++);glScissor(r2.left, mHeight - r2.bottom, r2.width(), r2.height());glClear(GL_COLOR_BUFFER_BIT);}glDisable(GL_SCISSOR_TEST);}// specify the y center as ceiling((mHeight - frame.trimHeight) / 2)// which is equivalent to mHeight - (yc + frame.trimHeight)const int frameDrawY = mHeight - (yc + frame.trimHeight);glDrawTexiOES(xc, frameDrawY, 0, frame.trimWidth, frame.trimHeight);// if the part hasn't been stopped yet then continue fading if necessaryif (exitPending() && part.hasFadingPhase()) {fadeFrame(xc, frameDrawY, frame.trimWidth, frame.trimHeight, part,++fadedFramesCount);if (fadedFramesCount >= part.framesToFadeCount) {fadedFramesCount = MAX_FADED_FRAMES_COUNT; // no more fading}}if (mClockEnabled && mTimeIsAccurate && validClock(part)) {drawClock(animation.clockFont, part.clockPosX, part.clockPosY);}if (displayProgress) {int newProgress = android::base::GetIntProperty(PROGRESS_PROP_NAME, 0);// In case the new progress jumped suddenly, still show an// increment of 1.if (lastDisplayedProgress != 100) {// Artificially sleep 1/10th a second to slow down the animation.usleep(100000);if (lastDisplayedProgress < newProgress) {lastDisplayedProgress++;}}// Put the progress percentage right below the animation.int posY = animation.height / 3;int posX = TEXT_CENTER_VALUE;drawProgress(lastDisplayedProgress, animation.progressFont, posX, posY);}handleViewport(frameDuration);eglSwapBuffers(mDisplay, mSurface);nsecs_t now = systemTime();nsecs_t delay = frameDuration - (now - lastFrame);//SLOGD("%lld, %lld", ns2ms(now - lastFrame), ns2ms(delay));lastFrame = now;if (delay > 0) {struct timespec spec;spec.tv_sec  = (now + delay) / 1000000000;spec.tv_nsec = (now + delay) % 1000000000;int err;do {err = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &spec, nullptr);} while (err<0 && errno == EINTR);}checkExit();}usleep(part.pause * ns2us(frameDuration));if (exitPending() && !part.count && mCurrentInset >= mTargetInset &&!part.hasFadingPhase()) {if (lastDisplayedProgress != 0 && lastDisplayedProgress != 100) {android::base::SetProperty(PROGRESS_PROP_NAME, "100");continue;}break; // exit the infinite non-fading part when it has been played at least once}}}// Free textures created for looping parts now that the animation is done.for (const Animation::Part& part : animation.parts) {if (part.count != 1) {const size_t fcount = part.frames.size();for (size_t j = 0; j < fcount; j++) {const Animation::Frame& frame(part.frames[j]);glDeleteTextures(1, &frame.tid);}}}return true;
}

3.6 开机动画退出检测

  • checkExit()检测属性"service.bootanim.exit"退出动画;在playAnimation方法和android方法中都有一个checkExit方法来负责检查是否退出动画
  • WMS中performEnableScreen()设置SystemProperties.set("service.bootanim.exit", "1")
void BootAnimation::checkExit() {// Allow surface flinger to gracefully request shutdownchar value[PROPERTY_VALUE_MAX];property_get(EXIT_PROP_NAME, value, "0");int exitnow = atoi(value);if (exitnow) {requestExit();}
}

在这里插入图片描述

private void performEnableScreen() {synchronized (mGlobalLock) {ProtoLog.i(WM_DEBUG_BOOT, "performEnableScreen: mDisplayEnabled=%b"+ " mForceDisplayEnabled=%b" + " mShowingBootMessages=%b"+ " mSystemBooted=%b mOnlyCore=%b. %s", mDisplayEnabled,mForceDisplayEnabled, mShowingBootMessages, mSystemBooted, mOnlyCore,new RuntimeException("here").fillInStackTrace());if (mDisplayEnabled) {return;}if (!mSystemBooted && !mShowingBootMessages) {return;}if (!mShowingBootMessages && !mPolicy.canDismissBootAnimation()) {return;}// Don't enable the screen until all existing windows have been drawn.if (!mForceDisplayEnabled) {if (mBootWaitForWindowsStartTime < 0) {// First time we will start waiting for all windows to be drawn.mBootWaitForWindowsStartTime = SystemClock.elapsedRealtime();}for (int i = mRoot.getChildCount() - 1; i >= 0; i--) {if (mRoot.getChildAt(i).shouldWaitForSystemDecorWindowsOnBoot()) {return;}}long waitTime = SystemClock.elapsedRealtime() - mBootWaitForWindowsStartTime;mBootWaitForWindowsStartTime = -1;if (waitTime > 10) {ProtoLog.i(WM_DEBUG_BOOT,"performEnableScreen: Waited %dms for all windows to be drawn",waitTime);}}if (!mBootAnimationStopped) {Trace.asyncTraceBegin(TRACE_TAG_WINDOW_MANAGER, "Stop bootanim", 0);// stop boot animation// formerly we would just kill the process, but we now ask it to exit so it// can choose where to stop the animation.SystemProperties.set("service.bootanim.exit", "1");mBootAnimationStopped = true;}if (!mForceDisplayEnabled && !checkBootAnimationCompleteLocked()) {ProtoLog.i(WM_DEBUG_BOOT, "performEnableScreen: Waiting for anim complete");return;}try {IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger");if (surfaceFlinger != null) {ProtoLog.i(WM_ERROR, "******* TELLING SURFACE FLINGER WE ARE BOOTED!");Parcel data = Parcel.obtain();data.writeInterfaceToken("android.ui.ISurfaceComposer");surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHEDdata, null, 0);data.recycle();}} catch (RemoteException ex) {ProtoLog.e(WM_ERROR, "Boot completed: SurfaceFlinger is dead!");}EventLogTags.writeWmBootAnimationDone(SystemClock.uptimeMillis());Trace.asyncTraceEnd(TRACE_TAG_WINDOW_MANAGER, "Stop bootanim", 0);mDisplayEnabled = true;ProtoLog.i(WM_DEBUG_SCREEN_ON, "******************** ENABLING SCREEN!");// Enable input dispatch.mInputManagerCallback.setEventDispatchingLw(mEventDispatchingEnabled);}try {mActivityManager.bootAnimationComplete();} catch (RemoteException e) {}mPolicy.enableScreenAfterBoot();// Make sure the last requested orientation has been applied.updateRotationUnchecked(false, false);
}

3.7 简易时序图

在这里插入图片描述

4、bootanimation.zip文件

bootanimation.zip
在这里插入图片描述 在这里插入图片描述
bootanimation.zip\desc.txt:

1080 2400 5
p 0 5 part0

bootanimation.zip\part0:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/69171.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【微服务部署】三、Jenkins+Maven插件Jib一键打包部署SpringBoot应用Docker镜像步骤详解

前面我们介绍了K8SDockerMaven插件打包部署SpringCloud微服务项目&#xff0c;在实际应用过程中&#xff0c;很多项目没有用到K8S和微服务&#xff0c;但是用到了Docker和SpringBoot&#xff0c;所以&#xff0c;我们这边介绍&#xff0c;如果使用Jenkinsjib-maven-plugin插件打…

基于springboot实现websocket实时通讯启动项目报错

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…

MySQL之事务与引擎

目录 一、事物 1、事务的概念 2、事务的ACID特点 3、事务之间的相互影响 4、Mysql及事务隔离级别(四种) 1、查询会话事务隔离级别 2、查询会话事务隔离级别 3、设置全局事务隔离级别 4、设置会话事务隔离级别 5、事务控制语句 6、演示 1、测试提交事务 2、测试事务回滚 4…

鲁棒优化入门(7)—Matlab+Yalmip两阶段鲁棒优化通用编程指南(下)

0.引言 上一篇博客介绍了使用Yalmip工具箱求解单阶段鲁棒优化的方法。这篇文章将和大家一起继续研究如何使用Yalmip工具箱求解两阶段鲁棒优化(默认看到这篇博客时已经有一定的基础了&#xff0c;如果没有可以看看我专栏里的其他文章)。关于两阶段鲁棒优化与列与约束生成算法的原…

【数学建模竞赛】数据预处理知识总结1——数据清洗

数据预处理是什么 在数学建模赛题中&#xff0c;官方给所有参赛选手的数据可能受到主观或客观条件的影响有一定的问题&#xff0c;如果不进行数据的处理而直接使用的话可能对最终的结果造成一定的影响&#xff0c;因此为了保证数据的真实性和建模结果的可靠性&#xff0c;需要…

SpringBoot v2.7.x+ 整合Swagger3入坑记?

目录 一、依赖 二、集成Swagger Java Config 三、配置完毕 四、解决方案 彩蛋 想尝鲜&#xff0c;坑也多&#xff0c;一起入个坑~ 一、依赖 SpringBoot版本&#xff1a;2.7.14 Swagger版本&#xff1a;3.0.0 <dependency><groupId>com.github.xiaoymin<…

【LeetCode】328. 奇偶链表

328. 奇偶链表&#xff08;中等&#xff09; 思路 如果链表为空&#xff0c;则直接返回链表。 对于原始链表&#xff0c;每个节点都是奇数节点或偶数节点。头节点是奇数节点&#xff0c;头节点的后一个节点是偶数节点&#xff0c;相邻节点的奇偶性不同。因此可以将奇数节点和偶…

图:关键路径

1. AOE网 与AOV网不同&#xff0c;AOE是用边表示活动的图或者网。 1.AOE网的概念 在带权有向图中&#xff0c;以顶点表示事件&#xff0c;以有向边表示活动&#xff0c; 以边上的权值表示完成该活动的开销(如完成活动所需的时间)&#xff0c; 称之为用边表示活动的网络&…

基于Springcloud微服务框架 +VUE框架开发的智慧工地系统源码

建筑行业快速发展&#xff0c;各建筑工程的建设规模在不断扩大&#xff0c;各岗位工作人员的工作内容所涉及的方面也越来越广泛。随着信息技术水平不断提高,人工记录的方式已经不能够满足大项目的管理要求&#xff0c;就此&#xff0c;创造出一种新型的施工管理技术——智慧工地…

【设计模式】装饰者模式

目录 一、定义二、结构三、优点四、使用场景五、代码示例六、截图示例 一、定义 1.在不改变现有对象结构的情况下&#xff0c;动态给该对象添加额外功能的模式 2.类B继承于类A&#xff0c;并将类A作为B类的属性&#xff08;B类聚合A类&#xff09; 3.BufferedInputStream、Buff…

OSI与TCP IP各层的结构与功能,都有哪些协议

分析&回答 OSI七层模型 层功能TCP/IP协议族应用层文件传输&#xff0c;电子邮件&#xff0c;文件服务&#xff0c;虚拟终端TFTP&#xff0c;HTTP&#xff0c;SNMP&#xff0c;FTP&#xff0c;SMTP&#xff0c;DNS&#xff0c;Telnet表示层数据格式化&#xff0c;代码转换…

pip安装第三方库与设置

pip的使用 假如下载numpy pip install numpypypi 镜像源「配置」 常用镜像源列表 官方&#xff1a;https://pypi.org/simple 百度&#xff1a;https://mirror.baidu.com/pypi/simple/ 清华&#xff1a;https://pypi.tuna.tsinghua.edu.cn/simple 阿里&#xff1a;https://m…

uni-app 可视化创建的项目 移动端安装调试插件vconsole

可视化创建的项目&#xff0c;在插件市场找不到vconsole插件了。 又不好npm install vconsole 换个思路&#xff0c;先创建一个cli脚手架脚手架的uni-app项目&#xff0c;然后再此项目上安装vconsole cli脚手架创建uni-app项目 安装插件 项目Terminal运行命令&#xff1a;npm…

ArcGIS美化科研论文地图(利用在线底图)

1.加载在线底图服务 在ArcGIS Desktop中打开Catalog窗口&#xff0c;在GIS Servers中点击Add ArcGIS Server&#xff0c;之后选项全部默认&#xff0c;仅在URL中输入以下网址https://services.arcgisonline.com/arcgis 之后就可以看到底图了 我们在WorldElevation3D中选择Nat…

Leetcode---360周赛

题目列表 2833. 距离原点最远的点 2834. 找出美丽数组的最小和 2835. 使子序列的和等于目标的最少操作次数 2836. 在传球游戏中最大化函数值 一、距离原点最远的点 这题主要是理解题意&#xff0c;遇到L往左走&#xff0c;遇到R往右走&#xff0c;遇到_左右都可以走&#x…

SpringBoot 集成 Canal 实现监听MySQL表数据

SpringBoot 集成 Canal 准备工作什么是 CanalCanal 在 Spring Boot 中的作用和优势准备工作安装和配置 MySQL 数据库 安装Canal项目集成导入依赖添加配置信息创建监听类测试 准备工作 什么是 Canal Canal 是阿里巴巴开源的基于数据库增量日志解析的数据同步和订阅组件&#x…

关于两个不同数据库的两张表建立数据库链接,关联查询数据

一、数据库链接 数据库链接&#xff08;database link&#xff09;是用于跨不同数据库之间进行连接和数据传输的工具或方法。它允许在一个数据库中访问另一个数据库中的对象和数据。 二、具体操作 以Oracle数据库为例 --1.建立链接tjpt CREATE DATABASE LINK tjpt CONNECT…

知识图谱笔记:TransE

1 知识图谱介绍 一条知识图谱可以表示为一个三元组(sub,rel,obj)。 举个例子&#xff1a;小明的爸爸是大明&#xff0c;表示成三元组是&#xff08;小明&#xff0c;爸爸&#xff0c;大明&#xff09;。前者是主体&#xff0c;中间是关系&#xff0c;后者是客体。主体和客体统…

基于JavaScript粒子流动效果

这是一个HTML文件&#xff0c;主要包含了一些CSS样式和JavaScript代码&#xff0c;用于创建一个动画效果。 在CSS部分&#xff0c;定义了一些基本的样式&#xff0c;包括页面的背景颜色、位置、大小等。特别的&#xff0c;定义了两种球形元素&#xff08;.ball_A 和 .ball_B&am…

MySql学习笔记08——事务介绍

事务 基本概念 事务是一个完整的业务逻辑&#xff0c;是一个最小的工作单元&#xff0c;不可再分。 一个完整的业务逻辑包括一系列的操作&#xff0c;这些操作是整个业务逻辑中的最小单元&#xff0c;这些操作要么同时成功&#xff0c;要么同时失败。 由于只有DML语句中才会…