1 简介

最近研究了Android的静默安装和智能安装,于是写博客记录一下。
静默安装就是无声无息的在后台安装apk,没有任何界面提示。
智能安装就是有安装界面,但全部是自动的,不需要用户去点击。
首先强调两点:

  1. 静默安装必须要root权限
  2. 智能安装必须要用户手动开启无障碍服务

2 原理

  1. 静默安装、卸载的原理就是利用pm install命令来安装apk,pm uninstall 来卸载apk.
  2. 智能安装是利用android系统提供的无障碍服务AccessibilityService,来模拟用户点击,从而自动安装.

3 pm命令介绍

(1) pm install
pm install 命令的用法及参数解释如下:

pm install [-l] [-r] [-t] [-i INSTALLER_PACKAGE_NAME] [-s] [-f] PATHOptions:-l: install the package with FORWARD_LOCK.
  -r: reinstall an exisiting app, keeping its data.
  -t: allow test .apks to be installed.
  -i: specify the installer package name.
  -s: install package on sdcard.
  -f: install package on internal flash.

(2) pm uninstall
pm uninstall 命令的用法及参数解释如下:

pm uninstall [-k] PACKAGEOptions:-k: keep the data and cache directories around.

上面英语很简单,不解释了.

4 静默安装

为了方便演示,我把爱奇艺的安装包重命名为test.apk后放在了sdcard上。你可以自己去爱奇艺官网去下载,也可以自己找一个apk放到sdcard上,但是要知道apk的包名,后面卸载的时候要用到。
先上代码:

//静默安装private void installSlient() {String cmd = "pm install -r /mnt/sdcard/test.apk";Process process = null;DataOutputStream os = null;BufferedReader successResult = null;BufferedReader errorResult = null;StringBuilder successMsg = null;StringBuilder errorMsg = null;try {//静默安装需要root权限process = Runtime.getRuntime().exec("su");os = new DataOutputStream(process.getOutputStream());os.write(cmd.getBytes());os.writeBytes("\n");os.writeBytes("exit\n");os.flush();//执行命令process.waitFor();//获取返回结果successMsg = new StringBuilder();errorMsg = new StringBuilder();successResult = new BufferedReader(new InputStreamReader(process.getInputStream()));errorResult = new BufferedReader(new InputStreamReader(process.getErrorStream()));String s;while ((s = successResult.readLine()) != null) {successMsg.append(s);}while ((s = errorResult.readLine()) != null) {errorMsg.append(s);}} catch (Exception e) {e.printStackTrace();} finally {try {if (os != null) {os.close();}if (process != null) {process.destroy();}if (successResult != null) {successResult.close();}if (errorResult != null) {errorResult.close();}} catch (Exception e) {e.printStackTrace();}}//显示结果tvTest.setText("成功消息:" + successMsg.toString() + "\n" + "错误消息: " + errorMsg.toString());}

这段代码就是在程序中执行pm命令,和在adb下执行 pm install -r /mnt/sdcard/test.apk 效果是一样的, 关键的代码是 Runtime.getRuntime().exec(“su”) ,这段代码会要求获取root权限,所以你的手机必须root,不想root的话,直接用模拟器也可以。

通过 Runtime.getRuntime().exec(“su”) 获取到 process 对象后就可以写入命令了,每写入一条命令就要换行,写入 ‘\n’ 即可,最后写入exit后离开命令执行的环境.

5 静默卸载

静默卸载和静默安装是一样的,只是命令不同,静默卸载需要用到包名,同样,静默卸载也需要root权限
看代码:

//爱奇艺apk的包名
private static final String PACKAGE_NAME = "com.qiyi.video";
//静默卸载private void uninstallSlient() {String cmd = "pm uninstall " + PACKAGE_NAME;Process process = null;DataOutputStream os = null;BufferedReader successResult = null;BufferedReader errorResult = null;StringBuilder successMsg = null;StringBuilder errorMsg = null;try {//卸载也需要root权限process = Runtime.getRuntime().exec("su");os = new DataOutputStream(process.getOutputStream());os.write(cmd.getBytes());os.writeBytes("\n");os.writeBytes("exit\n");os.flush();//执行命令process.waitFor();//获取返回结果successMsg = new StringBuilder();errorMsg = new StringBuilder();successResult = new BufferedReader(new InputStreamReader(process.getInputStream()));errorResult = new BufferedReader(new InputStreamReader(process.getErrorStream()));String s;while ((s = successResult.readLine()) != null) {successMsg.append(s);}while ((s = errorResult.readLine()) != null) {errorMsg.append(s);}} catch (Exception e) {e.printStackTrace();} finally {try {if (os != null) {os.close();}if (process != null) {process.destroy();}if (successResult != null) {successResult.close();}if (errorResult != null) {errorResult.close();}} catch (Exception e) {e.printStackTrace();}}//显示结果tvTest.setText("成功消息:" + successMsg.toString() + "\n" + "错误消息: " + errorMsg.toString());}

和静默安装一样的代码就不解释了。还有,如果你不知道一个apk的包名,那么请反编译后去看AndroidManifest.xml文件,如果这个文件打开全是乱码,说明是被混淆过的,那么直接安装它,然后到/data/data下面去找它的包,当然,手机得root才能进/data/data目录。

6 智能安装

智能安装就稍微麻烦点了,原理是用到了android提供的AccessibilityService服务,这个服务可以获取屏幕上的节点,一个节点也就是一个view,我们写的xml文件中每个标签就是一个节点,然后可以模拟用户的操作,对这些节点进行点击、滑动等操作。我们就是利用这个原理,来自动点击安装按钮的,当然使用这个服务必须用户手动开启无障碍服务。下面我们来看具体的实现方法。

(1) 创建AccessibilityService配置文件
在res目录下创建xml目录,然后在xml目录下创建一个accessibility_service_config.xml文件,内容如下
res/xml/accessibility_service_config.xml:

<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"android:accessibilityEventTypes="typeAllMask"android:accessibilityFeedbackType="feedbackGeneric"android:accessibilityFlags="flagDefault"android:canRetrieveWindowContent="true"android:description="@string/desc"android:packageNames="com.android.packageinstaller"/>

accessibilityEventTypes:指定我们在监听窗口中可以模拟哪些事件,typeAllMask表示所有的事件都能模拟.
accessibilityFeedbackType:指定无障碍服务的反馈方式.
canRetrieveWindowContent:指定是否允许我们的程序读取窗口中的节点和内容,当然是true.
description: 当用户手动配置服务时,会显示给用户看.
packageNames: 指定我们要监听哪个应用程序下的窗口活动,这里写com.android.packageinstaller表示监听Android系统的安装界面。
其余参数照写即可。
res/strings.xml:

<resources><string name="app_name">SlientInstallTest</string><string name="desc">智能安装app功能演示</string>
</resources>

(2) 创建AccessibilityService服务

public class MyAccessibilityService extends AccessibilityService {private static final String TAG = "[TAG]";private Map<Integer, Boolean> handleMap = new HashMap<>();@Overridepublic void onAccessibilityEvent(AccessibilityEvent event) {AccessibilityNodeInfo nodeInfo = event.getSource();if (nodeInfo != null) {int eventType = event.getEventType();if (eventType == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED || eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {if (handleMap.get(event.getWindowId()) == null) {boolean handled = iterateNodesAndHandle(nodeInfo);if (handled) {handleMap.put(event.getWindowId(), true);}}}}}@Overridepublic void onInterrupt() {}//遍历节点,模拟点击安装按钮private boolean iterateNodesAndHandle(AccessibilityNodeInfo nodeInfo) {if (nodeInfo != null) {int childCount = nodeInfo.getChildCount();if ("android.widget.Button".equals(nodeInfo.getClassName())) {String nodeCotent = nodeInfo.getText().toString();Log.d(TAG, "content is: " + nodeCotent);if ("安装".equals(nodeCotent) || "完成".equals(nodeCotent) || "确定".equals(nodeCotent)) {nodeInfo.performAction(AccessibilityNodeInfo.ACTION_CLICK);return true;}}//遇到ScrollView的时候模拟滑动一下else if ("android.widget.ScrollView".equals(nodeInfo.getClassName())) {nodeInfo.performAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);}for (int i = 0; i < childCount; i++) {AccessibilityNodeInfo childNodeInfo = nodeInfo.getChild(i);if (iterateNodesAndHandle(childNodeInfo)) {return true;}}}return false;}
}

当进入apk安装界面就会回调onAccessibilityEvent()这个方法,我们只关心TYPE_WINDOW_CONTENT_CHANGED和TYPE_WINDOW_STATE_CHANGED两个事件,为了防止重复处理事件,用一个map来过滤事件,后面递归遍历节点,找到’安装’ ‘完成’ ‘确定’ 的按钮,就点击,由于安装界面需要滚动一下才能出现安装按钮,所以遇到ScrollView的时候就滚动一下.

(3) 在AndroidManifest中配置服务

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/><application
        android:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:supportsRtl="true"android:theme="@style/AppTheme"><activity android:name=".MainActivity"><intent-filter><action android:name="android.intent.action.MAIN"/><category android:name="android.intent.category.LAUNCHER"/></intent-filter></activity><service
            android:name=".MyAccessibilityService"android:label="智能安装App"android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"><intent-filter><action android:name="android.accessibilityservice.AccessibilityService"/></intent-filter><meta-data
                android:name="android.accessibilityservice"android:resource="@xml/accessibility_service_config"/></service></application>

重点是后面的service标签:
android:label:这个就是用户看到的无障碍服务的名称
android:permission: 需要用到BIND_ACCESSIBILITY_SERVICE这个权限.
action: android.accessibilityservice.AccessibilityService 有了这个action,用户才能在设置里面看到我们的服务,否则用户无法开启我们写的服务,也就不能进到我们写的MyAccessibilityService里面了.所以,注意不要写错了,如果你发现无障碍服务里面没有我们写的服务,请检查这里.

(4) 调用智能安装代码
前面准备工作完毕后,现在要用了,调用智能安装的代码如下:

 //智能安装private void smartInstall() {Uri uri = Uri.fromFile(new File("/mnt/sdcard/test.apk"));Intent localIntent = new Intent(Intent.ACTION_VIEW);localIntent.setDataAndType(uri, "application/vnd.android.package-archive");startActivity(localIntent);}

(5) 手动配置智能安装服务
代码运行之后,还要用户选择开启智能安装服务,让用户自己去找是不明智的,因此,我们要主动跳到配置界面,代码如下:

//跳转到开启智能安装服务的界面
Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
startActivity(intent);

配置如下图:

看到了吗,上面显示的就是Service里面的label的值,如果你没有上面的选项,请检查AndroidManifest里面Service的配置.
点击’智能安装App’,开启服务,如下图:

其中的提示文字就是我们在res/xml/accessibility_service_config.xml文件中配置的description属性

7 只能我们写的app可以自动安装

这样写完代码可以运行,点击按钮自动安装sdcard上的test.apk.但是你会发现,所有apk都会自动安装,这就不符合我们的要求了,我们要求只能通过我们写的app来自动安装,其他apk还是要用户手动去点。怎么解决这个问题呢?
思路是:在MainActivity中创建一个public static boolean flag,在MyAccessibilityService的onAccessibilityEvent()中加一个flag判断,然后调用智能安装前flag设为true,创建apk安装事件的广播接收器,当apk安装完成后,设置falg为false,这样其他apk就不能自动安装了,就解决了这个问题
下面上完整代码.

8 完整代码

app/MainActivity.java:

public class MainActivity extends AppCompatActivity implements View.OnClickListener {private static final String TAG = "[TAG][MainActivity]";private static final String PACKAGE_NAME = "com.qiyi.video";private String apkPath = "/mnt/sdcard/test.apk";public static boolean flag = false;//控制只能自己的app才能执行智能安装private TextView tvTest;private MyInstallReceiver receiver;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);tvTest = (TextView) findViewById(R.id.tv_test);findViewById(R.id.btn_install).setOnClickListener(this);findViewById(R.id.btn_uninstall).setOnClickListener(this);findViewById(R.id.btn_set).setOnClickListener(this);findViewById(R.id.btn_smart_install).setOnClickListener(this);//注册apk安装监听receiver = new MyInstallReceiver();IntentFilter filter = new IntentFilter();filter.addAction("android.intent.action.PACKAGE_ADDED");filter.addAction("android.intent.action.PACKAGE_REMOVED");filter.addDataScheme("package");this.registerReceiver(receiver, filter);}@Overridepublic void onClick(View v) {switch (v.getId()) {//静默安装case R.id.btn_install:installSlient();break;//静默卸载case R.id.btn_uninstall:uninstallSlient();break;//设置无障碍服务case R.id.btn_set://跳转到开启无障碍服务的界面Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);startActivity(intent);break;//智能安装case R.id.btn_smart_install://控制只能自己的app才能智能安装flag = true;smartInstall();break;}}//静默安装private void installSlient() {String cmd = "pm install -r /mnt/sdcard/test.apk";Process process = null;DataOutputStream os = null;BufferedReader successResult = null;BufferedReader errorResult = null;StringBuilder successMsg = null;StringBuilder errorMsg = null;try {//静默安装需要root权限process = Runtime.getRuntime().exec("su");os = new DataOutputStream(process.getOutputStream());os.write(cmd.getBytes());os.writeBytes("\n");os.writeBytes("exit\n");os.flush();//执行命令process.waitFor();//获取返回结果successMsg = new StringBuilder();errorMsg = new StringBuilder();successResult = new BufferedReader(new InputStreamReader(process.getInputStream()));errorResult = new BufferedReader(new InputStreamReader(process.getErrorStream()));String s;while ((s = successResult.readLine()) != null) {successMsg.append(s);}while ((s = errorResult.readLine()) != null) {errorMsg.append(s);}} catch (Exception e) {e.printStackTrace();} finally {try {if (os != null) {os.close();}if (process != null) {process.destroy();}if (successResult != null) {successResult.close();}if (errorResult != null) {errorResult.close();}} catch (Exception e) {e.printStackTrace();}}//显示结果tvTest.setText("成功消息:" + successMsg.toString() + "\n" + "错误消息: " + errorMsg.toString());}//静默卸载private void uninstallSlient() {String cmd = "pm uninstall " + PACKAGE_NAME;Process process = null;DataOutputStream os = null;BufferedReader successResult = null;BufferedReader errorResult = null;StringBuilder successMsg = null;StringBuilder errorMsg = null;try {//卸载也需要root权限process = Runtime.getRuntime().exec("su");os = new DataOutputStream(process.getOutputStream());os.write(cmd.getBytes());os.writeBytes("\n");os.writeBytes("exit\n");os.flush();//执行命令process.waitFor();//获取返回结果successMsg = new StringBuilder();errorMsg = new StringBuilder();successResult = new BufferedReader(new InputStreamReader(process.getInputStream()));errorResult = new BufferedReader(new InputStreamReader(process.getErrorStream()));String s;while ((s = successResult.readLine()) != null) {successMsg.append(s);}while ((s = errorResult.readLine()) != null) {errorMsg.append(s);}} catch (Exception e) {e.printStackTrace();} finally {try {if (os != null) {os.close();}if (process != null) {process.destroy();}if (successResult != null) {successResult.close();}if (errorResult != null) {errorResult.close();}} catch (Exception e) {e.printStackTrace();}}//显示结果tvTest.setText("成功消息:" + successMsg.toString() + "\n" + "错误消息: " + errorMsg.toString());}//智能安装private void smartInstall() {Uri uri = Uri.fromFile(new File(apkPath));Intent localIntent = new Intent(Intent.ACTION_VIEW);localIntent.setDataAndType(uri, "application/vnd.android.package-archive");startActivity(localIntent);}//监听apk安装private class MyInstallReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {if (intent.getAction().equals("android.intent.action.PACKAGE_ADDED")) {     // installString packageName = intent.getDataString();Log.i(TAG, "安装了 :" + packageName);//安装完毕,设置flag,从而使得其余的apk不能自动安装flag = false;}if (intent.getAction().equals("android.intent.action.PACKAGE_REMOVED")) {   // uninstallString packageName = intent.getDataString();Log.i(TAG, "卸载了 :" + packageName);}}}@Overrideprotected void onDestroy() {super.onDestroy();if (receiver != null) {unregisterReceiver(receiver);}}
}

界面上就三个按钮
res/layout/activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:paddingBottom="@dimen/activity_vertical_margin"android:paddingLeft="@dimen/activity_horizontal_margin"android:paddingRight="@dimen/activity_horizontal_margin"android:paddingTop="@dimen/activity_vertical_margin"><TextView
        android:id="@+id/tv_test"android:layout_width="match_parent"android:layout_height="wrap_content"android:text=""/><Button
        android:id="@+id/btn_install"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_centerInParent="true"android:text="安装"/><Button
        android:id="@+id/btn_uninstall"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_below="@id/btn_install"android:text="卸载"/><Button
        android:id="@+id/btn_set"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_below="@id/btn_uninstall"android:text="开启智能安装功能"/><Button
        android:id="@+id/btn_smart_install"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_below="@id/btn_set"android:text="智能安装"/>
</RelativeLayout>

服务配置文件
res/xml/accessibility_service_config.xml

<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"android:accessibilityEventTypes="typeAllMask"android:accessibilityFeedbackType="feedbackGeneric"android:accessibilityFlags="flagDefault"android:canRetrieveWindowContent="true"android:description="@string/desc"android:packageNames="com.android.packageinstaller"/>

智能安装服务
app/MyAccessibilityService.java:

public class MyAccessibilityService extends AccessibilityService {private static final String TAG = "[TAG]";private Map<Integer, Boolean> handleMap = new HashMap<>();@Overridepublic void onAccessibilityEvent(AccessibilityEvent event) {AccessibilityNodeInfo nodeInfo = event.getSource();if (nodeInfo != null && MainActivity.flag) {int eventType = event.getEventType();if (eventType == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED || eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {if (handleMap.get(event.getWindowId()) == null) {boolean handled = iterateNodesAndHandle(nodeInfo);if (handled) {handleMap.put(event.getWindowId(), true);}}}}}@Overridepublic void onInterrupt() {}//遍历节点,模拟点击安装按钮private boolean iterateNodesAndHandle(AccessibilityNodeInfo nodeInfo) {if (nodeInfo != null) {int childCount = nodeInfo.getChildCount();if ("android.widget.Button".equals(nodeInfo.getClassName())) {String nodeCotent = nodeInfo.getText().toString();Log.d(TAG, "content is: " + nodeCotent);if ("安装".equals(nodeCotent) || "完成".equals(nodeCotent) || "确定".equals(nodeCotent)) {nodeInfo.performAction(AccessibilityNodeInfo.ACTION_CLICK);return true;}}//遇到ScrollView的时候模拟滑动一下else if ("android.widget.ScrollView".equals(nodeInfo.getClassName())) {nodeInfo.performAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);}for (int i = 0; i < childCount; i++) {AccessibilityNodeInfo childNodeInfo = nodeInfo.getChild(i);if (iterateNodesAndHandle(childNodeInfo)) {return true;}}}return false;}
}

最后是配置文件AndroidManifest.xml:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.slientinstalltest"><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/><application
        android:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:supportsRtl="true"android:theme="@style/AppTheme"><activity android:name=".MainActivity"><intent-filter><action android:name="android.intent.action.MAIN"/><category android:name="android.intent.category.LAUNCHER"/></intent-filter></activity><service
            android:name=".MyAccessibilityService"android:label="智能安装App"android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"><intent-filter><action android:name="android.accessibilityservice.AccessibilityService"/></intent-filter><meta-data
                android:name="android.accessibilityservice"android:resource="@xml/accessibility_service_config"/></service></application></manifest>

注意:请把自己要安装的apk放到sdcard上,并且修改代码中的apk路径和包名

9 运行效果

10 代码下载

演示代码已经上传,下载地址:

http://download.csdn.net/detail/fuchaosz/9570881

11 总结

Android智能安装的原理就是利用了类似钩子的服务,这个服务还可以用于微信抢红包的开发,怎么样,是不是比ios好玩儿的多呢.

12 转载请注明来自”梧桐那时雨”的博客:http://blog.csdn.net/fuchaosz/article/details/51852442

Tips
如果觉得这篇博客对你有帮助或者喜欢博主的写作风格,就给博主留个言或者顶一下呗,鼓励博主创作出更多优质博客,Thank you.

Android 静默安装和智能安装的实现方法相关推荐

  1. Android实现APK智能安装且安装后自启动,亲测有用!

    一.智能安装 (一)什么是智能安装? 最近因为公司需求需要实现智能安装,apk从服务器上下载后,自动打开安装,安装完后自己打开,难了我好长时间才实现的,记录一下. 首先实现有两种方式: 静默安装: 在 ...

  2. Android采用pm实现静默安装(降级安装)的解决方案

    最近在做一个apk分析器,里面可以解析系统中所有安装app的信息,并提供组内开发的apk文件下载.静默安装(包括降级安装),其中在降级安装中难度较大,在Android4.4与Android 8的解决方 ...

  3. android静默卸载,Android实践 -- Android静默安装和卸载

    App的静默安装和卸载 Android系统本身提供了安装卸载功能,但是api接口是@hide的,不是公开的接口,所以在应用级别 是无法实现静默安装和卸载的,要实现静默安装和卸载需要是系统应用,要有系统 ...

  4. android实现后台静默安装,Android 静默安装实现方法

    Android静默安装的方法,静默安装就是绕过安装程序时的提示窗口,直接在后台安装. 注意:静默安装的前提是设备有ROOT权限. 代码如下: /** * 静默安装 * @param file * @r ...

  5. Android 基于AccessibilityService智能安装Apk 仿 豌豆荚

    本文授权发布公众号[刘桂林],星球[Hi Android] 今天我简单的来给大家分享一下基于AccessibilityService功能实现智能安装的功能,事实上这个功能在豌豆荚或者其他应用商店应该也 ...

  6. 记录开发经历-----Android静默安装卸载

    App的静默安装和卸载(有系统签名) Android系统本身提供了安装卸载功能,但是api接口是@hide的,不是公开的接口,所以在应用级别是无法实现静默安装和卸载的,要实现静默安装和卸载需要是系统应 ...

  7. Android 静默安装apk方法--兼容了5.1, 6.0, 7.1, 10, 11等各安卓版本

    系统级app需要实现静默安装apk的功能,且能兼容各安卓系统版本 废话不多说,直接上代码: Process process = null;BufferedReader successResult = ...

  8. 如何安装EOS智能合约开发工具包CDT

    本文简单的介绍一下如何安装EOS智能合约开发工具包(Contract Development Toolkit),简称CDT,是与智能合约编制相关的工具集合.对于EOSIO初学者来说,可以通过使用CDT ...

  9. 判断android应用程序是否已安装

    2019独角兽企业重金招聘Python工程师标准>>> android应用程序是否已安装,查看是否此包的相关信息   PackageInfo packageInfo; try {   ...

最新文章

  1. 程序员,如何三十而立?
  2. 【 FPGA 】常数( localparam )和参数( parameter )
  3. mysql2014授权设置_SQLServer2014许可证(六)虚拟化中的授权
  4. oracle 行级死锁_ORACLE死锁的分类
  5. CentOS 6网络配置
  6. 记录一次quartus II prime standard 18添加器件库的方法
  7. js:进一步关闭(范围:下一个)
  8. 西门子ddc_铁门关西门子两通电动阀VVF42.25-10C+SKD60西
  9. TNonblockingServer 连接管理
  10. linux集群启动脚本,Hadoop2.2.0集群启动和停止Shell脚本
  11. SharePoint快速调试技巧
  12. 聚类(3)-- Gaussian Mixtures Model
  13. 元宇宙里“倒腾狗”,预示“下一代互联网”要来了?
  14. excel内容合并脚本
  15. Excel制作二维码、条形码?你肯定没见过
  16. 使php爬虫能够长期运行的一点总结
  17. 对不起,我被裁员了。
  18. 卸载office提示无法打开修补程序包 修补程序包是否存在的解决方法.
  19. vue3中导出excel表格
  20. 记录 activity onStop、onDestroy 延迟调用问题解决过程

热门文章

  1. 4 年前端狗 2 年 CTO
  2. 【小米MIoT设备接入HomeAssistant通用插件教程】
  3. 1.面板数据模型理论--变截距面板数据模型
  4. 程序员硬核“Python抢票教程”,帮你抢回家车票(附源码)
  5. 如何让收到的邮件附件自动储存在Sharepoint里
  6. OPENWRT 插件ipk单独编译-无需编译整个固件
  7. mui框架android,mui框架安卓离线打包高级应用
  8. Ubuntu显示WiFi信号强度
  9. hspice2007安装教程(win10)
  10. 一维向量转换为n维向量_如何在N维上固定万向节锁