当前位置: 首页 > news >正文

Android13 研究可以静态注册的广播

Android13 研究可以静态注册的广播

文章目录

  • Android13 研究可以静态注册的广播
    • 一、前言
    • 二、静态注册和代码示例
      • 1、AI搜到可静态注册的常见系统广播类型
    • 三、静态注册、动态注册对比示例
      • 1、 AndroidManifest.xml代码
      • 2、MyBroadcast.java
      • 3、MySerivce.java
      • 4、MainActivity.java代码
      • 5、验证过程
        • (1)开机重启后应用启动的广播日志
        • (2)开关wifi,触发网络变化广播
        • (3)切换语言后的广播日志:
        • (4)时间的广播
        • (5)U盘插拔广播
        • (6)应用安装
      • 6、验证可静态注册的常见系统广播类型
    • 三、其他
      • 1、Android13 研究可以静态注册的广播小结
      • 2、开机广播也可以动态监听?
      • 3、如何添加新的静态广播?
      • 4、Android广播接收者使用总结
      • 5、Android13 不能静态注册的几个广播
      • 6、Android adb命令发送广播介绍

一、前言

静态广播就是 AndroidManifest.xml中定义的广播,应用启动一次后续就能监听到。

在开发过程中,除了用到开机广播是静态注册的,其他广播没啥印象是可以静态注册有效的;

心血来潮,看看有啥静态广播可用。

之前分析过Android13 不能静态注册的几个广播,比如:

android.intent.action.SCREEN_ON //屏幕亮起
android.intent.action.SCREEN_OFF//屏幕亮起
android.intent.action.BATTERY_CHANGED //电池电量改变
android.intent.action.CONFIGURATION_CHANGED //配置改变,界面语言,设备方向等配置信息
android.intent.action.TIME_TICK //每分钟回调一次

主要是为了系统安全问题,这些广播都是比较频繁的,或者是重要时机的,避免普通应用乱用。

那么那些广播能静态注册呢?

本文简单分析介绍一下,有兴趣可以看看。

二、静态注册和代码示例

1、AI搜到可静态注册的常见系统广播类型

Intent 广播类型作用所需权限
android.intent.action.BOOT_COMPLETED系统启动完成RECEIVE_BOOT_COMPLETED
android.intent.action.ACTION_POWER_CONNECTED电源连接
android.intent.action.ACTION_TIMEZONE_CHANGED时区变更
android.intent.action.TIME_SET时间被设置
android.intent.action.ACTION_LOCALE_CHANGED语言切换
android.intent.action.ACTION_BATTERY_LOW电量不足
android.intent.action.ACTION_MY_PACKAGE_REPLACED应用更新完成
android.hardware.usb.action.USB_DEVICE_ATTACHEDUSB设备连接
android.hardware.usb.action.USB_DEVICE_DETACHEDUSB断开

上面是AI 搜索提供的可静态注册的广播,但是实际真的可以吗?

可能Android8 或者更旧的版本,很多广播可以静态注册,但是Android新版本上基本不行了!

下面是实测示例。

三、静态注册、动态注册对比示例

这个有静态和动态监听广播代码,一个Activity和一个Service动态监听、一个Broadcast静态监听;

1、 AndroidManifest.xml代码

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"android:sharedUserId="android.uid.system" //系统签名应用哦!xmlns:tools="http://schemas.android.com/tools"><application         ...><activityandroid:name=".MainActivity"android:exported="true"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity><serviceandroid:name=".MyService"android:exported="false"></service><receiverandroid:name=".MyBroadcast"android:enabled="true"android:exported="true"><intent-filter><action android:name="com.example.MY_CUSTOM_ACTION" /><action android:name="TestBroadcast" /><!-- 可添加多个 action 或 category --></intent-filter><!-- 系统启动完成广播 --><intent-filter><action android:name="android.intent.action.BOOT_COMPLETED" /></intent-filter><!-- 网络连接变化广播 --><intent-filter><action android:name="android.net.conn.CONNECTIVITY_CHANGE" /><action android:name="android.net.wifi.STATE_CHANGE" /></intent-filter><!-- 应用安装/卸载广播(需指定包名) --><intent-filter><action android:name="android.intent.action.PACKAGE_ADDED" /><action android:name="android.intent.action.PACKAGE_REMOVED" /><data android:scheme="package" /></intent-filter><!-- other intent-filter...--><intent-filter><action android:name="com.android.intent.action.SHOW_CONTRAST_DIALOG" /><action android:name="android.intent.action.TIME_TICK" /><action android:name="android.intent.action.ACTION_TIMEZONE_CHANGED" /><action android:name="android.intent.action.ACTION_LOCALE_CHANGED" /><action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" /><action android:name="android.hardware.usb.action.USB_DEVICE_DETACHED" /></intent-filter></receiver></application></manifest>

注册activity、service和receiver;receiver 定义静态广播监听的广播类型;

demo的是系统签名应用,否则无法接收到开机广播;

2、MyBroadcast.java

静态接收广播的类

package com.liwenzhi.broadcasttest;import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;public class MyBroadcast extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {LogUtil.debug("received broadcast intent action  = " + intent.getAction());context.startService(new Intent(context, MyService.class));}
}

这个比较简单,接收静态广播,并拉起服务;

服务只会启动一次,所以多次调用是没有问题的。

3、MySerivce.java

普通的Service,启动会回动态监听广播,并且拉起Activity。

package com.liwenzhi.broadcasttest;import static com.liwenzhi.broadcasttest.MainActivity.*;import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.usb.UsbManager;
import android.net.ConnectivityManager;
import android.os.Handler;
import android.os.IBinder;import androidx.core.content.ContextCompat;/*** 普通服务类*/
public class MyService extends Service {@Overridepublic void onCreate() {super.onCreate();LogUtil.debug("onCreate");//动态注册广播registerBroadcast(this);//测试发送自定义广播Intent intent = new Intent("TestBroadcast");sendBroadcast(intent);//拉起Activity,广播或者Service拉起Activity必须添加 FLAG_ACTIVITY_NEW_TASK flagsIntent intent2 = new Intent(this, MainActivity.class);intent2.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); //不加这个会报错!startActivity(intent2);LogUtil.debug("onCreate End");}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {LogUtil.debug("onStartCommand");return super.onStartCommand(intent, flags, startId);}@Overridepublic IBinder onBind(Intent intent) {LogUtil.debug("onBind");return null;}public void registerBroadcast(Context context) {LogUtil.debug("");IntentFilter filter = new IntentFilter();filter.addAction("TestBroadcast"); //自定义广播filter.addAction(Intent.ACTION_TIME_CHANGED);//time_setfilter.addAction(Intent.ACTION_TIME_TICK);filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);filter.addAction(Intent.ACTION_LOCALE_CHANGED);filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);filter.addAction(Intent.ACTION_BOOT_COMPLETED); //开机广播filter.addAction(Intent.ACTION_PACKAGE_ADDED); //应用安装广播filter.addAction(Intent.ACTION_PACKAGE_REMOVED);filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); //网络监听广播filter.addDataScheme("package"); // 必须添加,否则接收不到广播ACTION_PACKAGE_ADDEDregisterReceiver(mReceiver, filter);}//动态接收广播监听对象private final BroadcastReceiver mReceiver = new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {final String action = intent.getAction();LogUtil.debug("onReceive: action = " + action);switch (action) {case ACTION_NET_CHANGE_ACTION:LogUtil.debug("网络变化");break;case "TestBroadcast":LogUtil.debug("自定义广播接收");break;}}};}

这个Service主要功能:动态监听广播+打印,发送测试广播,拉起Activity;

这个Service其实写不写都可以,动态广播,在Activity监听是一样的效果;

这里只是看看Activity界面退出后,广播监听的效果;

开发的实际场景中也是有很多情况是在Service后台中动态监听广播的。

4、MainActivity.java代码

Activity 界面代码如下:

package com.liwenzhi.broadcasttest;import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.usb.UsbManager;
import android.net.ConnectivityManager;public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);LogUtil.debug("");registerBroadcast(this);//动态监听广播}@Overrideprotected void onDestroy() {super.onDestroy();unRegisterBroadcast(this);}//发送网络变化广播public void sendBroadcast(View view) {LogUtil.debug("");Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);sendBroadcast(intent);}//发送开机广播,拉起Servicepublic void sendBroadcast2(View view) {LogUtil.debug("");Intent intent = new Intent("android.intent.action.BOOT_COMPLETED");sendBroadcast(intent);startService(new Intent(this, MyService.class));LogUtil.debug("End");}//发送自定义广播public void sendBroadcast3(View view) {LogUtil.debug("");Intent intent = new Intent("TestBroadcast");sendBroadcast(intent);}//注册广播监听public void registerBroadcast(Context context) {LogUtil.debug("");IntentFilter filter = new IntentFilter();filter.addAction("TestBroadcast"); //自定义广播filter.addAction(Intent.ACTION_TIME_CHANGED);//time_setfilter.addAction(Intent.ACTION_TIME_TICK);filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);filter.addAction(Intent.ACTION_LOCALE_CHANGED);filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);filter.addAction(Intent.ACTION_BOOT_COMPLETED); //开机广播filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); //网络监听广播filter.addDataScheme("package"); // 必须添加,否则接收不到广播ACTION_PACKAGE_ADDEDregisterReceiver(mReceiver, filter, ContextCompat.RECEIVER_NOT_EXPORTED);}public void unRegisterBroadcast(Context context) {context.unregisterReceiver(mReceiver);}//广播接收者+打印private final BroadcastReceiver mReceiver = new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {final String action = intent.getAction();LogUtil.debug("onReceive: action = " + action);switch (action) {case ACTION_NET_CHANGE_ACTION:LogUtil.debug("网络变化");break;case "TestBroadcast":LogUtil.debug("自定义广播接收");break;}}};}

上面Activity 界面起来后,进行动态监听广播;

添加了三个按钮,1、发送网络变化广播;2、发送开机广播、拉起Service;3、发送自定义广播;

应用可以发送网络变化广播和开机广播?

其实是可以的,但是必须要系统签名权限,否则会报错;

但是实际场景,基本不会发出这种系统类型的广播。

5、验证过程

(1)开机重启后应用启动的广播日志
//(1)开机后静态广播监听接收到开机广播
07-09 06:01:46.413  3331  3331 I XXXAppLog: MyBroadcast.java (11 )::onReceive  - received broadcast intent action  = android.intent.action.BOOT_COMPLETED//(2)拉起Service,动态监听广播
07-09 06:01:46.422  3331  3331 I XXXAppLog: MyService.java (27 )::onCreate  - onCreate
07-09 06:01:46.422  3331  3331 I XXXAppLog: MyService.java (52 )::registerBroadcast  - 
07-09 06:01:46.458  3331  3331 I XXXAppLog: MyService.java (36 )::onCreate  - onCreate End
07-09 06:01:46.459  3331  3331 I XXXAppLog: MyService.java (41 )::onStartCommand  - onStartCommand
07-09 06:01:46.461  3331  3331 I XXXAppLog: MyService.java (72 )::onReceive  - onReceive: action = android.net.conn.CONNECTIVITY_CHANGE
07-09 06:01:46.461  3331  3331 I XXXAppLog: MyService.java (75 )::onReceive  - 网络变化
07-09 06:01:46.462  3331  3331 I XXXAppLog: MyService.java (72 )::onReceive  - onReceive: action = TestBroadcast
07-09 06:01:46.462  3331  3331 I XXXAppLog: MyService.java (84 )::onReceive  - 自定义广播接收//(3)Service拉起Activity
07-09 06:01:49.730  3331  3331 I XXXAppLog: MainActivity.java (35 )::onCreate  - 
07-09 06:01:49.730  3331  3331 I XXXAppLog: MainActivity.java (91 )::registerBroadcast  - 

可以看到开机广播日志,和Service、activity启动日志;

这能监听到静态开机广播是因为应用添加了系统签名;

网络变化广播,这个广播是应用刚监听就会接收到一次的,不管系统网络是否变化。

(2)开关wifi,触发网络变化广播
07-09 06:03:40.033  3331  3331 I XXXAppLog: MyService.java (72 )::onReceive  - onReceive: action = android.net.conn.CONNECTIVITY_CHANGE
07-09 06:03:40.033  3331  3331 I XXXAppLog: MyService.java (75 )::onReceive  - 网络变化
07-09 06:03:40.033  3331  3331 I XXXAppLog: MainActivity.java (116 )::onReceive  - onReceive: action = android.net.conn.CONNECTIVITY_CHANGE
07-09 06:03:40.034  3331  3331 I XXXAppLog: MainActivity.java (119 )::onReceive  - 网络变化

上面可以看到,动态监听的广播可以接收到网络变化的广播,静态广播无法监听到网络变化广播。

(3)切换语言后的广播日志:
07-09 06:04:34.615  3331  3331 I XXXAppLog: MainActivity.java (35 )::onCreate  - 
07-09 06:04:34.615  3331  3331 I XXXAppLog: MainActivity.java (91 )::registerBroadcast  - 
07-09 06:04:34.643  3331  3331 I XXXAppLog: MyService.java (72 )::onReceive  - onReceive: action = android.intent.action.LOCALE_CHANGED

这里可以看到切换语言后,Activity会重启,无法接收到切换语言的广播;

静态广播也是无法接收到切换语言的广播;

Service一直在后台所以会接收到语言切换的广播;

(4)时间的广播

修改时间和每分钟一次的日志:

MyService.java (72 )::onReceive  - onReceive: action = android.intent.action.TIME_SET
MainActivity.java (116 )::onReceive  - onReceive: action = android.intent.action.TIME_SETMyService.java (72 )::onReceive  - onReceive: action = android.intent.action.TIME_TICK
MainActivity.java (116 )::onReceive - onReceive: action = android.intent.action.TIME_TICK

静态广播也是无法接收到时间变化的广播;

Service和Activity是可以接收端时间变化的广播;

这里MyService比Activity广播接收到早,是因为MyService先注册的广播。

(5)U盘插拔广播

U盘插入和拔出日志:

//U盘插入
08-09 06:25:39.718  3303  3303 I XXXAppLog: MyService.java (72 )::onReceive  - onReceive: action = android.hardware.usb.action.USB_DEVICE_ATTACHED
08-09 06:25:39.718  3303  3303 I XXXAppLog: MainActivity.java (116 )::onReceive  - onReceive: action = android.hardware.usb.action.USB_DEVICE_ATTACHED
08-09 06:25:39.748  3303  3303 I XXXAppLog: MyBroadcast.java (11 )::onReceive  - received broadcast intent action  = android.hardware.usb.action.USB_DEVICE_ATTACHED
08-09 06:25:39.752  3303  3303 I XXXAppLog: MyService.java (41 )::onStartCommand  - onStartCommand
08-09 06:25:39.756  3598  3598 I XXXAppLog: MyBroadcast.java (11 )::onReceive  - received broadcast intent action  = android.hardware.usb.action.USB_DEVICE_ATTACHED//U盘拔出
08-09 06:25:56.179  3303  3303 I XXXAppLog: MyService.java (72 )::onReceive  - onReceive: action = android.hardware.usb.action.USB_DEVICE_DETACHED
08-09 06:25:56.180  3303  3303 I XXXAppLog: MainActivity.java (116 )::onReceive  - onReceive: action = android.hardware.usb.action.USB_DEVICE_DETACHED
08-09 06:25:56.212  3303  3303 I XXXAppLog: MyBroadcast.java (11 )::onReceive  - received broadcast intent action  = android.hardware.usb.action.USB_DEVICE_DETACHED
08-09 06:25:56.215  3303  3303 I XXXAppLog: MyService.java (41 )::onStartCommand  - onStartCommand
08-09 06:25:56.220  3598  3598 I XXXAppLog: MyBroadcast.java (11 )::onReceive  - received broadcast intent action  = android.hardware.usb.action.USB_DEVICE_DETACHED

静态广播、Service和Activity都是可以接收到U盘插拔的广播;

这里静态广播会接收到两次,不清楚具体原因!

Service和Activity是可以接收端时间变化的广播;

这里MyService和Activity广播比MyBroadcast接收到早,是因为动态注册的会先监听到广播;

(6)应用安装

应用安装也是只能动态监听到,无法静态监听到;

刚开始动态广播也是无法监听到,后面搜索发现,需要添加 package声明才能正常监听。

filter.addAction(Intent.ACTION_PACKAGE_ADDED); //应用安装
filter.addAction(Intent.ACTION_PACKAGE_REMOVED); //应用卸载
filter.addDataScheme("package"); // 必须添加,否则接收不到应用安装和协助广播,这个不影响其他广播接收

6、验证可静态注册的常见系统广播类型

Intent 广播类型作用所需权限
android.intent.action.BOOT_COMPLETED系统启动完成RECEIVE_BOOT_COMPLETED
android.hardware.usb.action.USB_DEVICE_ATTACHEDUSB设备连接
android.hardware.usb.action.USB_DEVICE_DETACHEDUSB断开

实测中只有上面三个广播是可以静态注册有效的;

BOOT_COMPLETED 广播普通应用是无法接收到的,系统签名应用才可以接收到。

难道只有上面几个广播可以静态注册,没有其他了吗,其实系统还是有一些不常用的静态广播,

可以看看原生Settings的注册广播:

apps\Settings\AndroidManifest.xml

//电池电量:
<receiver android:name="com.android.settings.fuelgauge.batteryusage.BatteryUsageBroadcastReceiver"
android:exported="true"><intent-filter><action android:name="android.intent.action.BATTERY_LEVEL_CHANGED"/><action android:name="com.android.settings.battery.action.CLEAR_BATTERY_CACHE_DATA"/><action android:name="com.android.settings.battery.action.ACTION_BATTERY_PLUGGING"/><action android:name="com.android.settings.battery.action.ACTION_BATTERY_UNPLUGGING"/></intent-filter>
</receiver>//蓝牙配对请求:
<receiver android:name=".bluetooth.BluetoothPairingRequest"
android:exported="true"><intent-filter><action android:name="android.bluetooth.device.action.PAIRING_REQUEST" /><action android:name="android.bluetooth.action.CSIS_SET_MEMBER_AVAILABLE"/></intent-filter>
</receiver>

翻了一下,除了开机广播,就是上面几个电量和蓝牙配对的广播了,

还有几个看不懂的广播,估计也是用得很少的。

另外电量广播和蓝牙的广播也是需要特定的权限,普通应用也是无法监听。

电量广播:

framework/base/core/java/android/content/Intent.java

    /*** Broadcast Action: Sent when the current battery level or plug type changes.** It has {@link android.os.BatteryManager#EXTRA_EVENTS} that carries a list of {@link Bundle}* instances representing individual battery level changes with associated* extras from {@link #ACTION_BATTERY_CHANGED}.** <p class="note">* This broadcast requires {@link android.Manifest.permission#BATTERY_STATS} permission.** @hide*/@SystemApipublic static final String ACTION_BATTERY_LEVEL_CHANGED ="android.intent.action.BATTERY_LEVEL_CHANGED";

蓝牙配对广播:

packages/modules/Bluetooth/framework/java/android/bluetooth/BluetoothDevice.java

    /*** Broadcast Action: This intent is used to broadcast PAIRING REQUEST*/@RequiresLegacyBluetoothAdminPermission@RequiresBluetoothConnectPermission@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)public static final String ACTION_PAIRING_REQUEST ="android.bluetooth.device.action.PAIRING_REQUEST";

所以,普通应用看起来只有一个U盘插拔的广播可以静态使用!

三、其他

1、Android13 研究可以静态注册的广播小结

(1)Android系统常用的静态广播有:开机广播、U盘插拔广播
(2)普通应用能用的静态广播只有U盘插拔广播
(3)静态能监听的广播动态也能监听
(4)动态监听的广播比静态监听的广播会接收到快一点
(5)U盘插/拔,静态广播会接收到两次

所以说静态广播没啥好研究的,普通应用想用来做保活不可能;

系统应用也不需要广播来进行保活,只需要在AndroidManifest定义 android:persistent=“true” 即可。

2、开机广播也可以动态监听?

是的。开机广播也可以动态监听。

正常情况,SystemServer 启动后到静态开机广播接收大概要一分多钟;

如果 SystemServer 启动后,拉起某个Service,动态监听开机广播,大概半分钟就能接收到开机广播。

静态开机广播是在上层大部分逻辑初始完成+Launcher启动一会后才能发出,

所以我在记忆热点启动都是在系统服务动态监听开机广播的中进行拉起热点或者进行一些系统初始化的。

总结一句话就是:任何静态监听的广播都可以动态监听,并且动态监听会比静态监听的更快接收到广播。

3、如何添加新的静态广播?

在framework/base/core/java/android/content/Intent.java 添加 Action定义就可以了吗?

其实不行,试了一下并没有用;

只是添加了Action后,应用导入更新的framework jar,可以应用调用到自定义的Intent变量而已。

但是也要注意Action的格式 android.intent.action.XXX:

    public static final String ACTION_BRO_TEST = "android.intent.action.BRO_TEST";

如果后面的字符串随便写个AA或者XXX是会编译报错的,需要另外配置允许的命名规则。

目前还没找到哪里是定义可以静态监听的地方,有兴趣的可以自行研究看看。

网上搜到: 白名单机制

源码中定义了允许静态注册的广播列表,如 BOOT_COMPLETED 被明确列入:

//frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
private static final ArraySet<String> sStaticBroadcastWhitelist = new ArraySet<>();
static {sStaticBroadcastWhitelist.add(Intent.ACTION_BOOT_COMPLETED);sStaticBroadcastWhitelist.add(Intent.ACTION_USER_PRESENT);// 其他允许静态注册的广播...
}

但是从Android13 的代码是无法查看到这段代码的,并且这几个关键字都没有,设置开机广播这里都没有找到。

可能在某个封装类里面有定义白名单列表的代码,但是我找不到。

4、Android广播接收者使用总结

BroadcastReceiver广播接收者是Android四大组件之一。

一般的都要在AndroidManifest中静态注册,但是只有广播接收者可以使用java代码的方法来动态注册。

https://blog.csdn.net/wenzhi20102321/article/details/53127914

5、Android13 不能静态注册的几个广播

本文介绍一些广播相关的知识,主要是静态广播注册无效的介绍。

其实从Android 8.0 就开始有这个问题的,只是本文的源码是基于Android13 分析的。

https://blog.csdn.net/wenzhi20102321/article/details/134956090

6、Android adb命令发送广播介绍

Android 广播除了代码中发送,还可以使用命令模拟发送,只要应用代码中进行了监听,都可以正常接收到的。

掌握手动发送广播命令,可以方便某些代码的调试。

https://blog.csdn.net/wenzhi20102321/article/details/136895508

http://www.dtcms.com/a/274488.html

相关文章:

  • 基于vscode开发工具显示git提交信息的插件
  • 物联网应用开发技术趋势与实践指南
  • 高德智能手表解决方案 助力荣耀手表5 Ultra开启智慧出行
  • 基于Java Spring Boot开发的旅游景区智能管理系统 计算机毕业设计源码32487
  • 多云环境下的成本管理挑战与对策
  • Vue集成MarkDown
  • 数据结构:栈、队列、链表
  • 磁场的秘密触手可及:霍尔传感器与嵌入式仿真平台赋能高校创新教学
  • HandyJSON使用详情
  • VS Code 插件扩展开发指南
  • AI的欧几里得要素时刻:从语言模型到可计算思维
  • 玖玖NFT数字藏品源码(源码下载)
  • 【达梦数据库|JPA】后端数据库国产化迁移记录
  • 解读:大模型(LLM)、检索增强生成(RAG)、智能体(Agent)
  • 城市之间消防主机长距离使用can转以太网通讯方案
  • JDBC 批处理操作详解
  • leetcode105深度解析:从前序与中序遍历序列构造二叉树
  • 我找工作的时候,AI到底帮了我还是坑了我?
  • 益丰新材闯上市:营收连降,核心原料依赖关联方,马韵升家族控股
  • 【每日刷题】x 的平方根
  • [TOOL] ubuntu 使用 ffmpeg 操作 gif、mp4
  • UNet改进(21):门控注意力机制在UNet中的应用与优化
  • mongodb 开源同步工具介绍
  • c++11——左值、右值、完美转发、移动语义
  • 【AI News | 20250710】每日AI进展
  • 60 美元玩转 Li-Fi —— 开源 OpenVLC 平台入门(附 BeagleBone Black 驱动简单解析)
  • UE5中的cesium
  • flex 布局完整功能介绍和示例演示
  • windows配置python环境
  • 获取Fortran程序内存使用情况的方法