Android基础第一篇

转载请标明出处:
http://blog.csdn.net/gj782128729/article/details/52314797
本文出自:【高境的博客】

1. 何为1G/ 2G/ 3G/ 4G技术


1.1. G代表什么?

G代表Generation的简称,有代的意思。

1G代表作是大哥大,采用通信标准是模拟制式,只能进行语音通话,不能上网。

2G代表作是小灵通,通信标准是gsm,可以进行语音通话、发短信,也可以简单上网,上网的协议采用wap。

3G时代的通信标准是WCDMA/CDMA2000等,上网速度更快。

4G时代通信标准是TD-LTE,LTE(Long Time Evolution长期演变过程)。

1.2. 1G/ 2G/ 3G/ 4G的主要区别

最主要区别是采用的制式和上网速度的不同。3G和4G的速度展示如图:
这里写图片描述

2. Android的起源


Android系统最初由安迪·鲁宾等人开发制作,最初开发这个系统的目的是创建一个数码相机的先进操作系统;后来发现市场需求不够大,加上智能手机市场快速成长,于是Android被改造为一款面向智能手机的操作系统。Android系统原来的公司名字就叫做Android,于2005年8月被美国科技企业Google收购。2008年第一款搭载Android系统的手机面世(T-Mobile G1也叫HTC Dream)。

3. Android的发展史


Android发展史:诞生八年一路辉煌,Android是以Linux为基础的开放源码操作系统。其公司于2003年在美国加州成立。2005年由Google收购注资,并组建开放手机联盟。2007年11月12日,Android Beta操作系统SDK正式发布。

3.1. Android版本的变化

版本号版本名称
1.0Astro(阿童木) 内测版
1.1Bender(发条机器人)内测版
1.5Cupcake(纸杯蛋糕)
1.6Donut(甜甜圈)
2.1Eclair(闪电泡芙)
2.2Froyo(冻酸奶)
2.3Gingerbread(姜饼)
3.0Honeycomb(蜂巢)
4.0Ice cream SandWich(冰激凌三明治)
4.1/4.2/4.3Jelly Bean(果冻豆)
4.4KitKat (雀巢巧克力)
5.0/5.1Lollipop(棒棒糖)(Android L)
6.0Marshmallow(棉花糖)(Android M)
7.0Nougat(牛轧糖)

3.2. 不同版本界面比较

以下列举了Android版本从1.5-4.2的系统界面图,从图中可以看出,Android系统的界面越来越美观。

这里写图片描述

4. Android体系结构


Android体系结构共分四层,如图:

这里写图片描述

1.Linux内核(Linux Kernel)
Android核心系统服务依赖于Linux2.6内核,如安全性、内存管理、进程管理、网络协议栈和驱动模型。Linux内核也是作为硬件与软件栈的抽象层。驱动:显示驱动、摄像头驱动、键盘驱动、WiFi驱动、Audio驱动、flash内存驱动、Binder(IPC)驱动、电源管理等。

2.函数库层(Libraries)
Android包含一些C/C++库,这些库能被Android系统中不同的组件使用。它们通过Android应用程序框架为开发者提供服务。
系统库包括九个子系统,分别是图层管理、媒体库、SQLite、OpenGLEState、FreeType、WebKit、SGL、SSL和libc。
Android运行时包括核心库和Dalvik虚拟机,前者既兼容了大多数Java语言所需要调用的功能函数,又包括了Android的核心库,比如android.os、android.net、android.media等等。后者是一种基于寄存器的java虚拟机,Dalvik虚拟机主要是完成对生命周期的管理、堆栈的管理、线程的管理、安全和异常的管理以及垃圾回收等重要功能。

3.应用框架层(Application Framework)
该层是Android应用开发的基础,开发人员大部分情况是在和它打交道。开发人员也可以完全访问核心应用程序所使用的API框架。该应用程序的架构设计简化了组件的重用;任何一个应用程序都可以发布它的功能块并且任何其它的应用程序都可以使用其所发布的功能块(不过得遵循框架的安全性限制)。同样,该应用程序重用机制也使用户可以方便的替换程序组件。

4.层应用层(Applications)
Android会同一系列核心应用程序包一起发布,该应用程序包包括email客户端,SMS短消息程序,日历,地图,浏览器,联系人管理程序等。所有的应用程序都是使用Java语言编写的。

5. JVM和Dalvik VM


5.1. Dalvik的起源

Dalvik虚拟机是Google公司自主设计的运行于Android平台的Java虚拟机。JVM是归Oracle公司所有的,运行在基于PC机上的Window 和Linux操作系上的java虚拟机。Google工程师之所以设计Dalvik虚拟机主要有以下两点原因:若要使用JVM需要获得授权许可,这意味着需要缴纳大量的费用;JVM主要是针对于CPU快,内存大的传统PC机,不适合移动设备。下图是Oracle公司和Google公司诉讼历程:
这里写图片描述

5.2. 两种虚拟机比较

JVM(Java Virtual Machine),Java虚拟机是虚构出来的运行Java程序的运行时,是通过在实际的计算机上仿真模拟各种计算机功能的实现。它具有完善的硬件架构(如处理器、堆栈、寄存器等),还具有相应的指令系统,使用JVM就是使用Java程序,与操作系统无关。理论上在任何操作系统中,只要有对应的JVM,就可以运行Java程序。
Dalvik VM是在Android系统上运行Android程序的虚拟机,其指令集是基于寄存器架构的,执行特有的文件格式-dex字节码来完成对象生命周期管理、堆栈管理、线程管理、安全异常管理、垃圾回收等重要功能。

以下是JVM和Dalvik VM编译过程:
这里写图片描述
jar文件和apk内部组成对比:
这里写图片描述
从它们的编译过程可以看出:
(1) JVM运行的是.class文件的Java字节码,但是Dalvik VM运行的是其转换后的dex(Dalvik Executable)文件。
(2) JVM从.class文件或者JAR包中加载字节码然后运行,而Dalvik VM无法直接从.class文件或JAR包中加载字节码,它需要通过dx.bat工具将应用程序所有的.class文件编译成一个.dex文件,Dalvik VM则运行这个.dex文件。

5.3. ART模式

ART模式英文全称为:Android RunTime,谷歌Android4.4系统新增的一种应用运行模式,与传统的Dalvik模式不同,ART模式可以实现更为流畅的安卓系统体验。

ART模式与Dalvik模式最大的不同在于,在启动ART模式后,系统在安装应用的时候会进行一次预编译,在安装应用时会先将代码转换为机器语言存储在本地,这样在运行程序的时候就不回每次都进行一次编译了,执行效率也大大提升。

但凡事总有正反两面,ART在解决了该问题的同时,同时也有如:会占用略高一些的存储空间、安装程序时要相比普通Dalvik模式要长一些时间来实现预编译。用一个比喻来说,骑自行车Dalvik是已经折叠起来的自行车,每次骑都要先组装自行车才能骑,ART是已经组装好的自行车,每次骑直接上车就能走。

6. Android Sdk的下载安装


Sdk(Standard Development Kit):标准开发工具集,即我们开发Android应用所需要的工具集。下载步骤如下:
1 打开Eclipse
2 打开SDKManager选项 如下图:
这里写图片描述
3 下载相对应的版本 如下图:
这里写图片描述

7. 模拟器的创建


1 打开Android Virtual Device Manager
这里写图片描述
2 创建模拟器,点击create,填写具体模拟器参数,点击ok创建成功。
这里写图片描述
这里写图片描述

参数参数作用
AVD Name安卓模拟器名称
Device模拟器设备镜像
Target模拟器系统版本
CPU/ABI系统架构
RAM运行内存
VM Heap虚拟机最大内存即单个应用最大可用的内存
SD Card SizeSd卡内存大小

8. Android SDK目录结构


8.1. SDK目录结构图

这里写图片描述

8.2. SDK目录结构介绍

目录介绍
AVD Name安卓模拟器名称
add-ons存着一些谷歌提供的附加库
docs存着谷歌提供的文档
extras谷歌给提供的一些额外的jar包 比如v4 v7 v13
platforms是每个平台sdk真正的文件 里面会根据api来划分api的版本
platform-tools谷歌给提供了一些常见的工具 比如adb dx.bat aapt等
system-images提供的系统镜像
source谷歌提供的源码
temp目录里面存放的是临时文件
tools谷歌提供的一些额外工具 比如画9patch图片

adb(Android Debug Bridge):Android调试桥
dx.bat:把所有的.class文件转换成一个dex文件
aapt(Android Application Package Tools):应用打包工具

9. ADB环境变量的配置


配置ADB环境变量是为了在命令行中直接使用adb指令,就如同安装JDK以后配置JDK的环境变量。配置步骤如下:
找到Android SDK下的platform-tools所在的目录路径,将路劲添加到环境变量path下,需要注意的是如果是添加在最前面,需要在路劲后面加上分号”;”。

右击计算机,选择属性,然后选择高级系统设置:
这里写图片描述
选择环境变量:
这里写图片描述
点击Path,选择编辑:
这里写图片描述
将Android SDK下的platform-tools所在的目录路径(adb.exe所在目录)加入:
这里写图片描述
验证adb环境变量配置成功方法:在命令行中输入adb命令,会出现如下图:
这里写图片描述

10. ADB简介及常见指令


ADB(Android Debug Bridge):ADB是Android提供的一个通用的调试工具,通俗的理解就是debug工具,借助这个工具,我们可以管理设备或手机模拟器的状态。

指令功能
adb devices列出所有的设备
adb start-server开启adb服务
adb kill-server关闭adb服务
adb logcat查看log
adb shell挂载到linux空间
adb install安装应用程序 如adb install helloworld.apk
adb uninstall卸载应用程序 如 adb uninstall helloworld.apk
adb push把文件/目录推到手机里
adb pull把文件/目录从手机里面拉出来

11. DDMS使用


11.1. DDMS简介

DDMS(Dalvik Debug Monitor Service),是Android开发环境中的Dalvik虚拟机调试监控服务。它为我们提供例如:为测试设备截屏、针对特定的进程查看正在运行的线程已经堆信息、Logcat、广播状态信息、模拟电话呼叫、接收SMS、虚拟地理坐标等。
DDMS这个工具存放在SDK-tools路径下。
在Eclipse-ADT中打开DDMS入口如下图:
这里写图片描述

11.2. DDMS透视图模块介绍

模块介绍
Devices模块列出当前开启的设备
Logcat模块日志猫控制台
Console控制台
File Explorer手机文件查看模块
Emulator control模拟一下电话的状态 比如打电话,发短信,地理位置等

Eclipes-ADT中各个模块的位置:
这里写图片描述

12. HelloWorld及工程目录


12.1. 创建HelloWorld工程

1 打开Eclipse,右击创建一个新的Android工程:
这里写图片描述
2 填写项目名称、包名、选择最小支持的sdk版本等信息:
这里写图片描述
3 设置应用程序图标,然后一直Next,直到最后Finish:
这里写图片描述
这里写图片描述

12.2. 应用程序开发目录

Android应用程序开发目录结构如下图:
这里写图片描述

目录作用
srcJava源代码的存放目录
gen自动生成目录,目录中存放所有由Android开发工具自动生成的文件。目录中最重要的就是R.java文件,这个文件由Android开发工具自动产生的,Android开发工具会自动根据你放入res目录的资源,同步更新修改R.java文件。正因为R.java文件是由开发工具自动生成的,所以我们应避免手工修改R.java。R.java在应用中起到了字典的作用,它包含了各种资源的id,通过R.java,应用可以很方便地找到对应资源;另外编绎器也会检查R.java列表中的资源是否被使用到,没有被使用到的资源不会编绎进软件中,这样可以减少应用在手机占用的空间。
res资源(Resource)目录,在这个目录中我们可以存放应用使用到的各种资源,如xml界面文件,图片或数据。
libs支持库目录 程序开发时需要的一些三方的jar包可以放在这个目录,系统会自动把里面的jar包,添加到环境变量。
assets资产目录,当中的文件不会再R文件中生成引用。
bin自动生成的 apk文件 classes.dex
AndroidManifest.xml项目清单文件 Android中四大组件、权限、版本号需要在清单文件里面配置。(类比Web工程中的web.xml)

res目录具体介绍:

目录作用
srcJava源代码的存放目录
res/drawable存放图片资源*res/layout:存放布局文件
res/values存放字符串资源: strings.xml,arrays.xml,colors.xml,dimens.xml,styles.xml
res/xmlgetResources().getXML()读取
res/raw存放应用使用到的原始文件,如音效文件等。

13. Apk编译打包过程


13.1. Apk编译打包

这里写图片描述
第一步:打包资源文件,生成R.java文件
第二步:处理AIDL文件,生成对应的.java文件
第三步:编译Java文件,生成对应的.class文件
第四步:把.class文件转化成Dalvik VM支持的classes.dex文件
第五步:打包生成未签名的.apk文件
第六步:对未签名的.apk文件进行签名
第七步:对前后的.apk文件进行对齐处理。
aapt: Android Application Package Tools 打包apk文件的工具

13.2. 应用程序签名

Android系统要求每一个Android应用程序必须要经过数字签名才能够安装到系统中,也就是说如果一个Android应用程序没有经过数字签名,是没有办法安装到系统中的。我们使用开发工具Eclipse直接将应用程序部署到手机或者模拟器上的时候使用了工具默认的debug签名。

Android通过数字签名来表示应用程序的作者和在应用程序之间建立信任关系,这个数字签名由应用程序的作者完成,并不需要权威的数字证书签名机构认证,它只是用来让应用程序包自我认证的。

14. 电话拨号器案例


本案例需要实现的功能是在输入框中输入手机号码,点击“拨打此号码”按钮会拨打输入框中的手机号码。

14.1. 编写页面布局

这里写图片描述
由于初学者,还没有学习Android中的常见布局,所以暂时我们可以直接从Eclipse工具中控件栏中拖入控件。

14.2. 编写业务逻辑

第一步,找到控件的引用:

EditText et_number = (EditText) findViewById(R.id.et_number);
Button btn_call = (Button) findViewById(R.id.btn_call);

第1行,通过findViewById()方法找到控件EditText,返回值是一个View对象,我们需要进行强制装换成EditText类型,参数传入该控件在布局文件中的id;
第2行,通过findViewById()方法找到控件Button,返回值是一个View对象,我们需要进行强制装换Button类型,参数传入该控件在布局文件中的id;

第二步,给按钮设置点击事件监听:

    btn_call.setOnClickListener(new MyOnClickListener());
    class MyOnClickListener implements OnClickListener{
        @Override
        public void onClick(View v) {
            String number = et_number.getText().toString().trim();
            Intent intent = new Intent();
            intent.setAction(Intent.ACTION_CALL);
            intent.setData(Uri.parse("tel:"+number));
            startActivity(intent);
        }
    }

第1行,给Button设置点击监听事件,参数传入我们自定义的监听对象;
第2行,定义按钮点击监听类,该类需要实现OnClickListener接口,需要实现接口中的onClick方法,当点击按钮,会回调接口中的onClick方法;
第3行,通过EditText的getText()得到一个Editable对象,该对象有toString()方法,获取到EditText中的输入的值,trim()方法删除字符串开始和结束位置的空格;
第6行,创建意图对象;
第7行,设置意图的动作为拨打电话:Intent.ACTION_CALL;
第8行,设置意图的数据;
第12行,开启意图。
因为应用要使用手机的电话服务,所以需要在清单文件AndroidMainfest.xml中添加电话服务权限:

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

14.3. 运行测试及结果

如果没有加上拨打电话的权限,程序会崩溃。查看日志,日志提示需要我们加入android.permission.CALL_PHONE权限:
这里写图片描述
创建两个模拟器,名称分别为5554和5556,将应用程序部署到5554模拟器上,输入号码5556,点击拨打按钮:
这里写图片描述
这里写图片描述

15. 四种点击事件


15.1. 内部类的方式

Button有setOnClickListener方法,方法参数需要传入一个接口对象,既然是接口,我们可以来实现该接口。

    btn_call.setOnClickListener(new MyOnClickListener());
    class MyOnClickListener implements OnClickListener{
        @Override
        public void onClick(View v) {
            Log.i("MainActivity", "我被点击了~~~");
        }
    }

第2-7行,定义一个内部类,实现OnClickListener接口,实现该接口必须实现接口的onClick()方法,当按钮被点击了就会自动回调onClick()方法。

15.2. 匿名内部类的方式

该方法与上一种方式大体一致,只不过给Button的setOnClickListener()方法传入一个匿名内部类作为参数。

    btn_call.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
            Log.i("MainActivity", "我被点击了~~~");
        }
    });

15.3. 当前类实现OnClickListener

让当前类实现OnClickListener接口,因此必须在该类中必须实现onClick()方法。将this作为参数给Button的setOnClickListener()方法。

    public class MainActivity extends Activity
            implements OnClickListener {
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            Button btn_call = (Button) findViewById(R.id.btn_call);
            btn_call.setOnClickListener(this);
        }

        @Override
        public void onClick(View v) {
            Log.i("MainActivity", "我被点击了~~~");
        }
    }

15.4. 布局文件声明onclick属性

    <Button
        android:id="@+id/btn_call"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="call"
        android:text="Button" />

在代码中我们需要加入一个方法,注意:方法名需要和onClick属性一致,而且必须传入View参数:

    public void call(View view){
        Log.i("MainActivity", "我被点击了~~~");
    }

16. Android中常见布局


16.1. 线性布局LinearLayout

线性布局用<LinearLayout></LinearLayout>标签标示。分为水平方向和垂直方向两种,默认为水平方向。
android:orientation=”horizontal”和android:orientation=”vertical” 属性来控制线性布局的方向。以下为布局代码和两种效果展示:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="horizontal" >

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="button1" />

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="button2" />

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="button3" />

    </LinearLayout>

这里写图片描述
这里写图片描述

16.2. 相对布局RelativeLayout

相对布局RelativeLayout允许子元素指定它们相对于其父元素或兄弟元素的位置,这是实际布局中最常用的布局方式之一。相对布局用<RelativeLayout></RelativeLayout>标签标示。
下面是RelativeLayout用到的一些重要的属性:
第一类:属性值为true或false

属性作用
android:layout_centerHrizontal水平居中
android:layout_centerVertical垂直居中
android:layout_centerInparent相对于父元素完全居中
android:layout_alignParentBottom贴紧父元素的下边缘
android:layout_alignParentLeft贴紧父元素的左边缘
android:layout_alignParentRight贴紧父元素的右边缘
android:layout_alignParentTop贴紧父元素的上边缘

第二类:属性值必须为id的引用名:”@id/id_name”

属性作用
android:layout_below在某元素的下方
android:layout_above在某元素的的上方
android:layout_toLeftOf在某元素的左边
android:layout_toRightOf在某元素的右边
android:layout_alignTop本元素的上边缘和某元素的的上边缘对齐
android:layout_alignLeft本元素的左边缘和某元素的的左边缘对齐
android:layout_alignBottom本元素的下边缘和某元素的的下边缘对齐
android:layout_alignRight本元素的右边缘和某元素的的右边缘对齐

第三类:属性值为具体的像素值,如30dip,40px

属性作用
android:layout_marginBottom离某元素底边缘的距离
android:layout_marginLeft离某元素左边缘的距离
android:layout_marginRight离某元素右边缘的距离
android:layout_marginTop离某元素上边缘的距离

16.3. 帧布局FrameLayout

FrameLayout对象好比一块在屏幕上提前预定好的空白区域,可以将一些元素填充在里面,如图片。所有元素都被放置在FrameLayout区域的最左上区域,而且无法为这些元素制指定一个确切的位置,若有多个元素,第一个添加的控件被放在最底层,那么后面的元素会重叠显示在前一个元素上,这种显示方式有些类似于堆栈。
注意点:
a.默认对齐方式是左上角对其。
b.若要设置子视图的位置,要设置layout_margin、layout_gravity 等属性值。

    <?xml version="1.0" encoding="utf-8"?>
    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" >

        <TextView

            android:layout_width="fill_parent"
            android:layout_height="80dp"
            android:background="#ff0000" />

        <TextView
            android:layout_marginLeft="20dp"
            android:layout_marginTop="20dp"
            android:layout_width="fill_parent"
            android:layout_height="80dp"
            android:background="#00ff00" />

        <TextView
            android:layout_marginTop="40dp"
            android:layout_marginLeft="40dp"
            android:layout_width="fill_parent"
            android:layout_height="80dp"
            android:background="#0000ff" />

    </FrameLayout>

这里写图片描述

16.4. 表格布局TableLayout

TableLayout是指将子元素的位置分配到行或列中。Android的一个TableLayout有许多TableRow组成,一个TableRow就是一行,列数按照TableRow中子布局最多的个数。TableLayout容器不会显示Row,Column,及Cell的边框线,每个Row拥有0个或多个Cell,每个Cell拥有一个View对象。

    <?xml version="1.0" encoding="utf-8"?>
    <TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
        <TableRow
            android:layout_width="match_parent"
            android:layout_height="wrap_content" >
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="用户名" />
            <EditText
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:ems="10" />
        </TableRow>
        <TableRow
            android:layout_width="match_parent"
            android:layout_height="wrap_content" >
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="密码" />
            <EditText
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" />
        </TableRow>
    </TableLayout>

16.5. 绝对布局AbsoluteLayout

一般开发中不会使用,因为不利于屏幕适配。

17. Android中的单位


首先我们需要了解一下几个重要概念:
什么是屏幕尺寸、屏幕分辨率、屏幕像素密度?
什么是dp、dip、dpi、sp、px?他们之间的关系是什么?
什么是mdpi、hdpi、xdpi、xxdpi?如何计算和区分?

17.1. 屏幕尺寸

屏幕尺寸指屏幕的对角线的长度,单位是英寸,1英寸=2.54厘米。比如常见的屏幕尺寸有2.4、2.8、3.5、3.7、4.2、5.0、5.5、6.0等。

17.2. 屏幕分辨率

屏幕分辨率是指在横纵向上的像素点数,单位是px,1px=1个像素点。一般以纵向像素*横向像素,如320*240,480*320,800*480,1960*1080等。

17.3. 屏幕像素密度

屏幕像素密度是指每英寸上的像素点数,单位是dpi,即“dot per inch”的缩写。屏幕像素密度与屏幕尺寸和屏幕分辨率有关,在单一变化条件下,屏幕尺寸越小、分辨率越高,像素密度越大,反之越小。

17.4. dp、dip、dpi、sp、px

px:之前的分辨率就是用像素为单位,大多数情况下,比如UI设计、Android原生API都会以px作为统一的计量单位,如获取屏幕宽高等。

dip和dp是一个意思(设备独立像素),都是Density Independent Pixels的缩写,即密度无关像素。之前我们说过dpi是屏幕像素密度,如果一英寸里面有160个像素,这个屏幕的像素密度就是160dpi,那么dp和px如何换算呢?

在Android中,规定以160dpi为基准,1dip=1px,如果像素密度是320dpi,则1dip=2px。也就是换算公式为:px=dp*(dpi/160);

sp:即scale-independent pixels,与dp类似,但是可以根据文字大小首选项进行缩放,是设置字体大小的单位。

17.5. mdpi、hdpi、xdpi、xxdpi

其实还有一个ldpi,但是随着移动设备配置的不断升级,这个像素密度的设备以及很罕见了,所以现在适配时不需要考虑。
mdpi、hdpi、xdpi、xxdpi用来修饰Android中的drawable文件夹及values文件夹,用来区分不同像素密度下的图片和dimen值。
那么如何区分呢?Google官方指定按照下列标准进行区分:
这里写图片描述

  • 9
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值