Android开发基础——Android简介
本系列文章主要针对Android 10(Q)进行介绍。
Android系统架构
Android大致可以分为4层架构:
- Linux内核层
- 系统运行库层
- 应用框架层
- 应用层
Linux内核层
Android系统是基于Linux内核的,这一层为Android设备的各种硬件提供了底层的驱动,如显示驱动,音频驱动,相机驱动,蓝牙驱动,Wi-Fi驱动,电源管理等。
系统运行库层
这一层通过一层C/C++库为Android系统提供了主要的特性支持。如SQLite库提供了数据库的支持,OpenGL|ES提供了3D绘图的支持,Webkit库提供了浏览器内核的支持等。
这一层还有Android运行时库,其主要提供了一些核心库,允许开发者使用Java语言来编写Android应用。另外,Android运行时库中还包含了Dalvik虚拟机(5.0系统之后改为ART运行环境),其使得每一个Android应用都能运行在独立的进程中,并且拥有一个自己的虚拟机示例。相较于Java虚拟机,Dalvik和ART都是专门针对移动设备定制的,它针对手机内存,CPU性能有限等情况做了优化处理。
应用框架层
这一层主要提供了构建应用程序时可能用到的各种API,Android自带的一些核心应用就是使用这些API完成的,开发者可以使用这些API来构建自己的应用程序。
应用层
所有安装在手机上的应用程序都是属于这一层的,比如系统自带的联系人,短信等程序,或者是从Google Play上下载的软件,自己开发的程序等。
Android应用开发特色
Android系统为开发优秀的应用程序提供了很多便利的功能。
四大组件
Android系统四大组件分别是Activity,Service,BroadcastReceiver和ContentProvider。
- Activity是所有应用程序的门面,只要是在应用中能够看到的东西,都是放在Activity中的
- Service在后台运行,即使用户退出应用,Service仍然是可以继续运行的
- BroadcastReceiver则允许应用接收来自各处的广播信息,比如电话,信息等,而应用也可以向外发出广播信息
- ContentProvider则为应用程序之间共享数据提供了可能,比如想要读取系统通讯录中的联系人,就需要通过ContentProvider来实现
系统控件
Android系统为开发者提供了丰富的系统空间,使得用户可以方便地编写漂亮的界面。同时用户还可以定制自己的控件。
SQLite数据库
Android系统还自带了这种轻量型,运算速度极快的嵌入式关系型数据库。其不仅支持标准的SQL语法,还可以通过Android封装好的API进行操作,让存储和读取数据变得非常方便。
强大的多媒体
Android系统还提供了丰富的多媒体服务,如音乐,视频,录音,拍照等,这些功能都可以在程序中使用代码进行控制,从而丰富应用的功能。
搭建开发环境
前期准备
开发Android程序所需要准备的工具主要有以下3个:
JDK:JDK是Java语言的软件开发工具包,它包含了Java的运行环境,工具集合,基础类库等内容
Android SDK:Android SDK是Google提供的Android开发工具包,在开发Android程序时,需要通过引入该工具包来使用Android相关的API
Android Studio:之前Android项目都是使用Eclipse开发的,通过安装ADT插件就可以用来开发Android程序了。而Android Studio则是Google推出的一款官方的IDE工具,使用更为方便
环境搭建
Google将开发环境的搭建进行了集成,下载最新的开发工具就可以完成整个环境的搭建。工具的下载站点是:
Download Android Studio & App Tools - Android Developers
Android Studio 应用社区-安卓应用下载中心:安卓游戏/安卓软件/游戏合集/软件合集/安卓游戏下载/安卓软件下载
HelloWorld
项目创建
在环境搭建完成之后,当然是编写HelloWorld了。
首先创建一个新的项目:
从上面的项目创建可以看出,能够选择创建手机,平板,可穿戴设备,TV等类型项目,但这里只关注手机和平板。
项目创建中的各项字段含义为:
- Name:表示项目名,此处为HelloWorld
- Package name:表示项目包名,Android系统通过包名来区分不同应用程序,因此包名一定要具有唯一性。Android Studio会根据应用名称自动生成合适的包名,也可以自行修改
- Save location:项目代码存放位置
- Lanuage:选择开发语言,可选为Java和Kotlin,这里选择Kotlin(Google推荐)
- Minimum SDK:设置项目的最低兼容版本
之后,项目创建成功。
启动模拟器
Android Studio自动生成了很多东西,此时不需要编写任何代码,该项目即可运行。不过在此之前,还需要有一个运行的载体,可以是一个真正的手机,也可以是Android模拟器。这里先使用模拟器运行程序。
模拟器可以在Android Studio的界面上创建,选择设备,下载对应的镜像,然后启动。之后模拟器就会像一个真正的手机一样,有一个开机过程,启动完成后的模拟器如下:
运行项目
现在模拟器已经启动了,之后就可以将该项目运行到模拟器上。
各项图标的含义为:
- 左侧的锤子:用来编译项目
- app下拉列表:用来选择运行哪一个项目,通常app就是当前的主项目
- 设备下拉列表:用来选择运行到哪个设备
- 右侧的三角:运行项目
- 右侧的方框:停止项目
项目运行之后,在模拟器上的显示如下:
之后,在启动器列表中也可以看到多了一个HelloWorld应用:
项目目录
其实整个过程中并没有编写任何代码,但是项目还是可以运行的,这是因为Android Studio已经自动生成的。这里看一下整个项目代码结构:
这里看一下上面显示的内容含义。
.gradle和.idle
这两个目录下放置的都是Android Studio自动生成的一些文件,无须关心,无须手动编辑。
app
项目中的代码,资源等内容都是放置在这个目录下的。
build
这个目录主要包含了一些在编译时自动生成的文件,也无须关心。
gradle
这个目录下包含了gradle wrapper的配置文件,使用gradle wrapper的方式不需要提前将gradle下载好,而是会自动根据本地的缓存情况决定是否需要联网下载gradle。Android Studio默认就是启动gradle wrapper方式的,如果需要更改成离线模式,可以在Settings中进行配置更改。
.gitignore
该文件是用来将指定的目录或文件排除在版本控制之外的。
build.gradle
这是项目全局的gradle构建脚本,通常这个文件中的内容是不需要更改的。
gradle.properties
该文件是全局的gradle配置文件,在这里配置的属性将会影响到项目中所有的gradle编译脚本。
gradles和gradlew.bat
这两个文件是用来在命令行界面中执行gradle命令的,其中gradlew是在Linux或Mac系统中使用的,gradlew.bat是在Windows系统中使用的。
local.properties
该文件用于指定本机中的Android SDK路径,通常内容是自动生成的,无需更改。如果本机中的Android SDK位置发生了变化,将该文件中的路径更改为新的位置即可。
settings.gradle
该文件用于指定项目中所有引入的模块。由于HelloWorld项目中只有一个app模块,因此该文件中也就只引入了app这一个模块。通常情况下,模块的引入是自动完成的。
上面提到的文件和目录大部分都是自动生成的,无需更改,而app目录下内容才是项目中的重点,其结构为:
这里看一下上面显示的内容含义。
build
该目录和之前的build目录类似,也包含了一些在编译时自动生成的文件,其内容也更加复杂,不过也无须关心。
libs
如果项目中包含了第三方jar包,就需要把这些jar包都放在libs目录下,放在这个目录下的jar包会被自动添加到项目的构建路径中。
androidTest
这里是用来编写Android Test测试用例的,可以对项目进行一些自动化测试。
java
该目录是放置所有Java代码的地方,也包含Kotlin的代码,在该目录下,系统已经主动生成了一个MainActivity文件。
res
该目录下的内容包含项目中使用到的所有图片,布局,字符串等资源。该目录还包含很多子目录,图片放在drawable目录下,布局放在layout目录下,字符串放在values目录下。
AndroidManifest.xml
这是整个项目的配置文件,程序中定义的所有四大组件都需要在该文件中注册,另外还可以在该文件中给应用程序添加权限声明。
test
这里用来编写Unit Test测试用例,是对项目进行自动化测试的另一种形式。
.gitignore
该文件用于将app模块内指定的目录或文件排除在版本控制之外,作用和外层的.gitignore
文件类似。
build.gradle
这里app模块的gradle构建脚本,该文件中指定了很多项目构建相关的配置。
proguard-rules.pro
该文件用于指定项目代码的混淆规则,当代码开发完成后打包成安装包文件,如果不希望代码被别人破解,通常会将代码进行混淆。
项目运行规则
这里看一下HelloWorld项目是如何运行的。首先是AndroidManifest.xml文件:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.example.helloworld"><applicationandroid:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/Theme.HelloWorld"><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></application></manifest>
上边的文件中,activity节点中的代码段表示对MainActivity的注册,没有在AndroidManifest.xml文件中注册的Activity是不能够使用的。其中intent-filter中的两行代码比较重要,表示MainActivity是该项目的主Activity,在手机上点击应用图标,首先启动的就是该Activity。
而MainActivity其实就是之前启动项目后出现的界面,其代码为:
class MainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)}
}
从上面可以看出,MainActivity继承自AppCompatActivity的。AppCompatActivity是AndroidX中提供的一种向下兼容的Activity,可以使Activity在不同系统版本中的功能保持一致性。
而Activity类是Android系统提供的一个基类,项目中所有自定义的Activity都必须继承它或者它的子类才能拥有Activity的特性(AppCompatActivity是Activity的子类)。
同时上面的代码中还有一个onCreate()方法,该方法是一个Activity被创建时必定要执行的方法,其中只有两行代码,并且没有“Hello World!”的字样。那么其显示又是从何而来的?
其实Android程序设计讲究逻辑与视图分离,因此更一般的做法是在布局文件中编写界面,然后在Activity中引入进来。可以看到onCreate()方法的第二行调用了setContentView()方法,就是该方法给当前的Activity引入了一个activity_main布局:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Hello World!"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toTopOf="parent" /></androidx.constraintlayout.widget.ConstraintLayout>
之前提到图片,布局,字符串等内容都放置在res目录下,同样上面的文件也位于res/layout目录下,上边的TextView中的内容正是"Hello World!"。
项目中的资源
既然所有的资源都是在res目录下的,那么看一下其目录结构:
上边显示的内容中:
- drawable:所有以drawable开头的目录都是用来存放图片的
- mipmap:所有以mipmap开头的目录都是用来存放应用图标的
- values:所有以values开头的目录都是用来存放字符串,样式,颜色等配置的
- layout:所有以layout开头的目录都是用来存放布局文件的
而之所以有很多mipmap开头的目录,其实是为了使程序能够更好地兼容各种设备,其它目录也有类似的作用,虽然Android Studio没有自动生成,但是用户也可以手动创建drawable-hdpi,drawable-xhdpi,drawable-xxhdpi等目录。在应用开发时,最好能够为同一张图片准备不同分辨率的版本,放置在对应目录下,程序在运行的时候,会自动根据当前运行设备分辨率的高低选择加载哪个目录下的图片。只不过这是最好的情况,更多的时候只会存在一份图片,此时只要将所有图片都放在drawable-xxhdpi目录下就好了,因为这是最主流的设备分辨率目录。
比如res/values/strings.xml文件:
<resources><string name="app_name">HelloWorld</string>
</resources>
上面文件中定义了app_name,这对应应用程序名的字符串,可以通过两种方式进行应用:
- 在代码中通过R.string.app_name引用该字符串
- 在XML中通过@string/app_name引用该字符串
上边提到的是基本的语法,其中string部分可以替换为drawable,以引用图片资源,替换为mipmap,以引用应用图标,替换为layout,以引用布局文件。
比如之前提到的AndroidManifest.xml文件中的icon,lable,roundIcon等都是采用了上面的引用形式:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.example.helloworld"><applicationandroid:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/Theme.HelloWorld"><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></application></manifest>
build.gradle文件
Android Studio是通过Gradle进行项目构建的,该工具基于Groovy的领域特定语言(DSL)来进行项目设置,而不同于基于XML的繁琐配置。
在之前的目录结构中,提到存在两个build.gradle文件,一个在最外层的项目目录下,另一个在app目录下,这两个文件都对项目构建起到了重要的作用。这里看一下这两个文件,首先是最外层的build.gradle文件:
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {repositories {google()mavenCentral()}dependencies {classpath "com.android.tools.build:gradle:7.0.0"classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.20"// NOTE: Do not place your application dependencies here; they belong// in the individual module build.gradle files}
}task clean(type: Delete) {delete rootProject.buildDir
}
上面的代码都是自动生成的:
- repositories声明了google()和mavenCentral()两行配置,分别对应了一个代码仓库,声明了这两行配置后,就可以在项目中使用相关的依赖库了
- dependencies使用classpath声明了Gradle和Kotlin插件,因为Gradle插件不是专门为创建Android项目而开发的,其它项目如Java/C++也可以使用Gradle来构建,因此需要声明。其声明部分最后表示的是插件的版本号,其一般是和当前Android Studio的版本对应的。而Kotlin插件则表示当前项目是使用Kotlin开发的。
而内层app下的build.gradle文件为:
plugins {id 'com.android.application'id 'kotlin-android'
}android {compileSdk 33defaultConfig {applicationId "com.example.helloworld"minSdk 21targetSdk 33versionCode 1versionName "1.0"testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"}buildTypes {release {minifyEnabled falseproguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'}}compileOptions {sourceCompatibility JavaVersion.VERSION_1_8targetCompatibility JavaVersion.VERSION_1_8}kotlinOptions {jvmTarget = '1.8'}
}dependencies {implementation 'androidx.core:core-ktx:1.3.2'implementation 'androidx.appcompat:appcompat:1.2.0'implementation 'com.google.android.material:material:1.3.0'implementation 'androidx.constraintlayout:constraintlayout:2.0.4'testImplementation 'junit:junit:4.+'androidTestImplementation 'androidx.test.ext:junit:1.1.2'androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}
上面的内容中:
- plugins:说明了相关的插件
- com.android.application:表示这是一个应用程序模块(com.android.library表示这是一个库模块,两者区别在于应用程序模块可以直接运行,库模块只能作为代码库依附于别的应用程序模块来运行)
- kotlin-android:表示应用了该插件
- android:配置项目构建的各种属性
- compileSdk:用于指定项目的编译版本
- defaultConfig:可以配置项目的相关细节
- applicationId:是每个应用的唯一标识符,默认使用项目创建时指定的包名,如果后期需要更改包名,就是修改这里
- minSdk:指定项目最低兼容的Android系统版本
- targetSdk:表示在该目标版本上已经进行了充分测试,系统将会为应用程序启用一些最新的功能和特性
- versionCode:用于指定项目的版本号
- versionName:用于指定项目的版本名
- testInstrumentationRunner:用于在当前项目中启用JUnit测试,可以为当前项目编写测试用例,以保证功能的正确性和稳定性
- buildTypes:用于指定生成安装文件的相关配置,通常只会有两个子项,release和debug
- release:用于指定生成正式版安装文件的配置
- minifyEnabled:用于指定是否对项目的代码进行混淆,true表示混淆,false表示不混淆
- proguardFiles:用于指定混淆时使用的规则文件,这里指定了两个文件,proguard-android-optimize.txt是在Android SDK/tools/prouard目录下的,该目录包含所有项目通用的混淆规则,proguard-rules.pro是在当前项目的根目录下的,里边可以编写当前项目特有的混淆规则
- debug:用于指定生成测试版安装文件的配置,可以忽略不写。不过通过Android Studio运行项目生成的都是测试版安装文件
- release:用于指定生成正式版安装文件的配置
- compileOptions:指定编译选项配置
sourceCompatibility:指定编译编译.java文件的jdk版本
targetCompatibility:确保class文件与targetCompatibility指定版本,或者更新的Java虚拟机兼容
kotlinOptions:指定Kotlin的相关选项
jvmTarget:指定kotlin相关的编译配置
dependencies:指定当前项目的所有依赖关系,通常项目中可能存在三种依赖关系:本地依赖,库依赖和远程依赖。本地依赖可以对本地的jar包或目录添加依赖关系,库依赖可以对项目中的库模块添加依赖关系,远程依赖则可以对之前提到的仓库上的开源项目添加依赖关系
implementation fileTree():表示本地依赖声明,这里没有用到
implementation:表示远程依赖,如 androidx.appcompat:appcompat:1.2.0就是一个标准的远程依赖库格式, androidx.appcompat表示域名部分,用于和其它公司的库做区分,appcompat表示工程名部分,用于和同一个公司中不同的库工程做区分,1.2.0表示版本号,用于和同一个库不同的版本做区分。加上这句声明后,Gradle在项目构建时会首先检查一下本地是否已经有该库的缓存,如果没有的话则会自动联网下载,然后再添加到项目的构建路径中。
implementation project():表示库依赖声明,这里没有用到
testImplementation:用于声明测试用例库
androidTestImplementation:用于声明测试用例库
日志工具
日志工具类
Android中的日志工具类是Log(Android.util.log),该类中提供了5种方法来打印日志:
- Log.v():对应级别verbose,级别最低,用于打印琐碎的,重要性最小的日志信息
- Log.d():对应级别debug,级别次低,用于打印一些调试信息,以进行程序调试和分析问题
- Log.i():对应级别info,级别中等,用于打印一些比较重要的数据,以帮助分析用户行为
- Log.w():对应级别warn,级别次高,用于打印一些警告信息,以提示用户可能存在潜在的风险
- Log.e():对应级别error,级别最高,用于打印错误信息,比如catch语句中的内容
为了验证打印内容,可以将之前的MainActivity修改为:
package com.example.helloworldimport androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Logclass MainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)Log.d("MainActivity","Hello World")}
}
在Log.d()中存在两个参数:
- tag:一般传入当前类名,主要用于对打印信息进行过滤
- msg:实际想要打印的内容
之后运行项目,在Logcat中就可以看到打印信息:
2022-09-04 20:05:49.382 11550-11550/com.example.helloworld D/MainActivity: Hello World
打印的内容包含日期,时间,进程号,包名,日志等级,类名,打印信息,可以说是很详细了。
Log和println()
其实从上面的内容看,Log类的作用就是进行信息的打印,其功能和println差不多,这里将上边的代码进行修改,对比一下:
package com.example.helloworldimport androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Logclass MainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)Log.d("MainActivity","Hello World")println("MainActivity" + " " + "Hello World")}
}
其相关打印结果为:
2022-09-04 20:17:06.043 11854-11854/com.example.helloworld D/MainActivity: Hello World
2022-09-04 20:17:06.043 11854-11854/com.example.helloworld I/System.out: MainActivity Hello World
从上面打印结果来看,虽然都能够定位到是MainActivity这个类,但是其形式并没有使用Log类方便。同时使用Log类还有两个好处,一个是可以对打印内容的重要性进行分级,另一个是可以在调试的时候对打印内容进行过滤。
上图显示的内容为:
- Show only selected application:表示只显示当前选中程序的日志
- Firebase:是Google提供的一个开发者工具和基础架构平台,可以忽略
- No Filters:相当于没有过滤器
- Edit Filter Configuration:则可以配置过滤器
比如添加如下的过滤器:
这样就能够在Logcat中过滤tag为MainActivity的所有日志。
而Logcat还可以进行日志级别控制:
上图显示的内容为:
- Verbose:显示所有等级日志
- Debug:显示Debug等级及其以上等级的日志
- Info:显示Info等级及其以上等级的日志
- Warn:显示Warn等级及其以上等级的日志
- Error:显示Error等级及其以上等级的日志
- Assert:和Assert有关
同时Logcat中还支持关键字搜索,其功能类似文本编辑器中的内容搜索,不过Logcat中的关键字搜索支持正则表达式。
Android开发基础——Android简介相关推荐
- Android开发基础——Kotlin简介
什么是Kotlin Java代码在运行前需要编译生成一种特殊的class文件,然后Java虚拟机会识别并解释这些class文件,而Kotlin作为一种新的编程语言,就是将其代码同样编译生成为这样的cl ...
- Android开发基础 -- android studio 使用第三方模拟器连接方法,如海马玩模拟器
安装完模拟器后,要使用adb命令Android studio才能识别出来: 打开cmd,输入:adb connect 127.0.0.1:26944.如下: 海马玩模拟器的端口号是26944. 逍遥安 ...
- 2017-2018-2 20165236 实验四《Android开发基础》实验报告
2017-2018-2 20165236 实验四<Android开发基础>实验报告 一.实验报告封面 课程:Java程序设计 班级:1652班 姓名:郭金涛 ...
- eclipse Android 开发基础 Activity 窗体 界面
eclipse Android 开发基础 新建工程 新建布局layout,new Android Activity就相当于窗体Form. 新建Activity自动生成src下同名的java代码. pu ...
- 20155202 实验四 Android开发基础
20155202 实验四 Android开发基础 实验内容 1.基于Android Studio开发简单的Android应用并部署测试; 2.了解Android.组件.布局管理器的使用: 3.掌握An ...
- 2018-2019-2-20175225 实验四《Android开发基础》实验报告
一.实验报告封面 课程:Java程序设计 班级:1752班 姓名:张元瑞 学号:20175225 指导教师:娄嘉鹏 实验日期:2019年5月14日 实验时间:13:45 - 21:00 实验序号:实验 ...
- 实验四android开发基础
实验四android开发基础 提交点一 Android Stuidio的安装测试: 参考<Java和Android开发学习指南(第二版)(EPUBIT,Java for Android 2nd) ...
- 实验四:Android 开发基础
实验四:实验报告 课程:程序设计与数据结构 班级: 1623 姓名: 张旭升 学号:20162329 指导教师:娄嘉鹏 王志强 实验日期:5月26日 实验密级: 非密级 预习程度: 已预习 必修/选修 ...
- 20145122《Android开发基础》实验四实验报告
实验名称 Android开发基础 实验内容 1.Windows环境下Android Studio 2.能够运行安卓AVD模拟器 3.使用安卓虚拟手机显示HelloWorld以及自己的学号 统计的PSP ...
最新文章
- ASP.NET MVC – Nerdinner - notes
- Android PC投屏简单尝试—最终章1
- OCM备考 三. Managing Database Availability 之flashback
- kb4023057安装失败_微软重发Win10 KB4023057 补丁,推动Win10更新
- http-server 简介 复制的
- 不同类别的图像数量可视化
- 实用的Python库
- ServletContext的用法
- windows cmd 提示 ‘系统找不到指定路径‘ 提示 ‘ECHO 处于关闭状态‘
- vm安装win7 office2013
- html 的title中显示网页logo
- 高中计算机教室标语,高中教室宣传标语
- 智鼎在线测评是测什么_为什么求职者会反感企业招聘用的人才测评?
- 程序员加薪升职之全路径解析
- 通过JAVA从高德地图URL连接获取json数据 解析并存入数据库的程序举例
- Ubuntu 下配置 Typora 图片上传到 smms
- uplink端口能接路由器吗_交换机常见的网络故障,你知道如何解决吗?
- Python就业都有哪些岗位?
- 江南,我愿变成你怀中的一枝青莲
- 计算当前四边形是否为凸四边形
热门文章
- (Google)谷歌笔试算法题:要求相邻的两个数都不小于或者不大于其本身的排序
- 新氧在“看脸的时代”用精细化运营赋能医美产业
- 51单片机_7-2 使用内部计时器实现时钟显示
- ❥关于C++之函数指针函数对象
- 打造属于自己的量化投资系统2——利用backtrader创建简单移动平均线策略
- 管理者树立威信,牢记这“6字诀”!
- 安装ELK-Docker方式
- 让程序员心动的微瞬间(亲情篇)
- 空腹时 再饿都不能吃的11种食物
- python3从零学习-5.3.2、复数库cmath