手机的发展根据通信技术大致可以划分为 4 个时代(G:Generation 的缩写)
第一代模拟制式手机(1G):1G 就是大哥大,手机类似于简单的无线电双工电台,通话是锁定在一定频率,所以使用可调频电台就可以窃听通话
第二代 GSM、CDMA 等数字手机(2G):手机使用 PHS,GSM 或者 CDMA 这些十分成熟的标准,具有稳定的通话质量和合适的待机时间,支持彩信业务的 GPRS 和上网业务的 WAP 服务,以及各式各样的 Java 程序等
第三代移动通信技术(3G):3G,是英文 3rd Generation 的缩写,指第三代移动通信技术。指将无线通信与国际互联网等多媒体通信结合的新一代移动通信系统。它能够处理图像、音乐、视频流等多种媒体形式,提供包括网页浏览、电话会议、电子商务等多种信息服务
第四代移动电话行动通信(4G):4G。该技术包括 TD-LTE 和 FDD-LTE 两种制式。4G 是集 3G 与 WLAN 于一体,并能够传输高质量视频图像,它的图像传输质量与高清晰度电视不相上下。4G 系统能够以 100Mbps 的速度下载,比目前的拨号上网快 200 倍,并能够满足几乎所有用户对于无线服务的要求。此外,4G 可以在 DSL 和有限电视调制解调器没有覆盖的地方部署,然后再扩展到整个地区
1G 制式:彻底退出历史舞台……
2G/3G/4G 的区别:网速的区别。
2G:打个电话给你:"我租了一张苍老师的 VCD,一起来看"。
3G:发个消息给你:"种子发你邮箱了,注意查收,请叫我雷锋"。
4G:发个地址给你:"在线看,高清的,还能边看边吐槽"。
2G 拨号上网,带宽 12.2k 每用户。
3G 宽带上网,带宽 384k~2M 每用户。
4G 光纤到户,带宽可以达到 100M 每用户。
2003 年 10 月,安迪 · 鲁宾牵头创建了一家公司,名为 Android,开始开发一款针对手机端的操作系统。
2005 年 8 月,谷歌低调收购了这家公司及其团队,安迪 · 鲁宾成为 Google 公司工程部副总裁,继续负责 Android 项目。
2007 年 11 月,谷歌公司正式向外界展示了这款名为 Android 的操作系统,并宣布建立一个全球性的联盟组织,该组织由 34 家手机制造商、软件开发商、电信运营商以及芯片制造商共同组成,他们共同搭建起了 Android 系统最早的生态圈。
2011 年,Android 在全球的市场份额首次超过塞班系统,跃居第一,目前的主要竞争对手是 iOS。
Android 的系统架构采用了分层的设计。从架构图看,Android 分为四层,从低层到高层分别是 Linux 内核层、系统运行库层、应用程序框架层和应用程序层
Linux 核心,Android 系统是基于 Linux 系统修改过来的,Android 底层都是 Linux 的东西,大多都是操作硬件的一些驱动,如 Display Driver、Audio Drivers 等,Linux 内核也同时作为硬件和软件栈之间的抽象层
用 C 语言编写的完成 Android 核心功能的一些类库,这些库能被 Android 系统中不同的组件使用。它们通过 Android 应用程序框架为开发者提供服务
应用框架层,全部是用 Java 语言编写的,供开发人员调用。Android 系统中的每个应用都依赖于该框架提供的一系列服务和系统,其中包括:
应用层,我们安装的所有应用都属于这一层,如,微信,植物大战僵尸。该层不仅包括系统内置的应用也包括用户自己安装的应用,比如 email 客户端,SMS 短消息程序,日历,地图,浏览器,联系人管理程序,QQ,微信,淘宝,美团等,该层所有的应用程序都是使用 Java 语言编写的
闹钟应用的功能实际上就是定时播放音乐。闹钟应用调用 APPLICATION FRAMEWORK 层的 MediaPlayer,MeidaPlayer 访问 LIBRARIES 层中的 Media Framework,Media Framework 再使用 C 语言操作 Andio Drivers 去播放音乐
JavaSE 程序使用的虚拟机叫 Java Virtual Machine,简称 JVM,Android 应用也使用 Java 语言开发,但是使用的虚拟就是 Dalvik Virtual Machine,简称 DVM。
Dalvik 是 Google 公司自己设计用于 Android 平台的 Java 虚拟机。它执行的是已转换为. dex(即 Dalvik Executable)格式的 Java 应用程序的运行,.dex 格式是专为 Dalvik 设计的一种压缩格式,适合内存和处理器速度有限的系统。
Dalvik 经过优化,允许在有限的内存中同时运行多个虚拟机的实例,并且每一个 Dalvik 应用作为一个独立的 Linux 进程执行。独立的进程可以防止在虚拟机崩溃的时候所有程序都被关闭。
DVM 执行的是. dex 格式文件,JVM 执行的是. class 格式文件。Android 程序编译完之后生成. class 文件,然后,dex 工具会把. class 文件处理成. dex 文件,然后把资源文件和. dex 文件等打包成. apk 文件,apk 就是 android package 的意思。
Dalvik 基于寄存器,而 JVM 基于栈。基于寄存器的虚拟机对于编译后变大的程序来说,在它们执行的时候,花费的时间更短。
Dalvik 和 Java 运行环境的区别:
ART 模式英文全称为:Android runtime,谷歌从 Android 4.4 系统开始新增的一种应用运行模式,与传统的 Dalvik 模式不同,ART 模式可以实现更为流畅的 Android 系统体验。
在 4.4 系统之前,Android 系统在 Linux 的底层下构筑 Dalvik 一层的虚拟机,通过其可以更好适应多样的硬件架构,开发者只需要按一套规则进行应用便可,无需因为不同的硬件架构而处理与底层的驱动关系,从而大大提高开发的效率,但因为应用均是运行在 Dalvik 虚拟机中,因此应用程序每次运行的时候,一部分代码都需要重新进行编译,这过程需要消耗一定的时间和降低应用的执行效率,最明显的便是拖延了应用的启动时间和降低了运行速度。
ART 模式最大的作用就是提升了 Android 系统流畅度,相比 Dalvik 模式中出现的耗电快、占用内存大、即使是旗舰机用久了也会卡顿严重等现象,ART 模式中这种问题得到了很好的解决,通过在安装应用程序时,自动对程序进行代码预读取编译,让程序直接编译成机器语言,免去了 Dalvik 模式要时时转换代码,实现高效率、省电、占用更低的系统内存、手机运行流畅。
ART 模式可以降低手机硬件配置要求,减少 RAM 内存依赖,不过在安卓 4.4 系统中,安装应用的时间比安卓 4.4 以下版本系统更长,这主要由于应用安装过程中需要先执行编码导致,并且安装应用更占存储空间(ROM)
Android 5.0 以上版本的手机正式开始使用 ART
Dalvik:应用程序每次运行的时候,字节码都需要通过即时编译器转换为机器码,这会拖慢应用的运行效率。
ART:应用在第一次安装的时候,字节码就会预先编译成机器码(java 语言翻译成 C 指令),使其成为真正的本地应用,应用的启动和执行速度都会显著提升。弊端就是 ART 需要存储 java 和 C 两份指令,有些耗内存。
上图说明:进入开发者模式,选择运行环境切换。在切换至 ART 模式时,系统会重新启动,改变运行环境,需要等待程序优化完毕,即可。
QQ 实际占用内用内存,原本为 44.64MB,ART 模式下,变为 63.00MB,说明 ART 有些耗内存(存两份指令)。
目前主流的开发工具有两个,一个是 Eclipse 另外一个是 Android Studio。Eclipse 需要和 ADT(Android Develop Tool)插件整合后才能使用,不过 Google 官方已经直接提供了 Eclipse 和 ADT 集成好的开发工具,叫 ADT-Bundle,但是现在 Google 已经不再支持这种方式开发,已经完全转移到 Android Studio 平台
Android Studio 是 Google 基于 IntelliJ IDEA 开发的 Android 集成开发工具,目前国内使用该开发工具的企业也越来越多。Android 基础阶段我们依然使用 Eclipse 作为开发工具,在后面的课程中才会使用到 Android Studio。
获取 SDK 工具包(Software development kits)、、
工具包,包含以下内容:
Android Studio 是一个 Android 开发环境,基于 IntelliJ IDEA,类似 Eclipse ADT,Android Studio 提供了集成的 Android 开发工具用于开发和调试。
双击 SDK Manager.exe。
SDK 文件夹目录结构(请对应上图查看):
docs 文件夹中是 SDK 帮助文档,在线文档使用起来很不方便。但是,我们可以使用离线文档。双击 sdk 目录下的 docs 文件夹,双击此文件夹中的 index.html,双击打开。然后,会等待很久,因为浏览器要去 google 服务器请求数据。如果请求不到,就会一直请求,直到超时。如果断网了,也就请求不到数据了
但是,我们可以脱机使用。步骤 1、打开火狐,选择 "开发者"–>"脱机工作"。
步骤 2、打开 SDK 离线文档,可以搜索 API。如,Activity。
2、安装 intel 文件夹中的 IntelHAXM.exe 可能报错。如果报错为如下,说明本机不支持安装 HAXM.exe,不用装了。
如果报错如下,说明本机支持,但是支持加速器的选项没有打开,去 BIOS 中打开即可。进入 BIOS 找到 virtual technology 选项,选择 enable 即可。
1、首先指定 SDK 的路径。
点击 Windows–>preferences–>Android,默认指定正确的 SDK 路径。但是,如果以前装过 SDK,那么就会指定旧的 SDK,也就是错误的,手动更换成新的 SDK 路径即可。
2、点击虚拟机管理器按钮–> 点击 New,创建模拟器。
3、点击 "detail" 可以看到模拟器配置明细。
4、点击 "Start"–>Launch,启动模拟器。
不建议使用这么大的分辨率,屏幕分辨率越大,启动越慢,最好用 320*480 的分辨率。
步骤 1、右击–>New–>Android Application Project。
步骤二、设置 Android 项目参数。
步骤三、设置应用图标。
步骤四、创建 Activity。我们创建的时候都使用空白的 Activity,需要什么效果,最好自己写。自动生成的 Activity,很多自动生成的代码需要删除、修改,很麻烦。
给 Activity 起个名字,一般就叫 MainActivity,不需要修改。
步骤五、生成项目成功。
步骤六、空白项目也可以部署,运行。右击–>Run As–>Android Application。
然后,此项目就会被部署到 Android 的模拟器上。选择 Console 中的 Android 选项卡,可以看到部署的状态。
步骤七、运行成功。
示例 1:更改应用程序图标、名称。
1、 将图标存入 drawable-hdpi 文件夹中。
2、查看 R.java 文件,可以看到生成了相应的 id。
3、打开 AndroidManifest.xml 文件,修改。
4、运行。
1、在 AndroidManifest.xml 文件中,修改图标及应用名称时,一定要注意:如果 activity 标签中没有 android:label 及 android:icon 这两个属性,那么显示的就是 application 标签中的这两个属性的值,不存在覆盖问题。但是,如果 activity 标签中也有 android:label 及 android:icon 这两个属性,那么就会覆盖 application 标签中的 android:label 及 android:icon 属性。也就是说,显示的就是 activity 标签中的这两个属性的值。
2、图片 3 中的图标及应用名称会始终依据 AndroidManifest.xml 文件中的 application 标签中的 android:icon 和 android:label 两个属性值展示,因为此界面属于管理页面,要与图 1 和图 2 中的普通的 Activity 区分开。
示例 2:修改展示内容。
1、修改 res 中 values 文件夹中的 strings.xml 文件。
2、查看 R.java 文件,可以看到生成了相应的 id。
3、修改 res 中 layout 文件夹中的布局文件 activity_mainxml。
4、运行。
1、Android 项目编译、打包成 apk.apk 中包含
PS:被编译的只有. java 代码
2、签名(给 apk 包打个数字签名)。然后再通过 ADB 运行到 Devices emulator 上,Devices 指的是手机,Emulator 指的是模拟器。系统判断两个应用是否属于同一款应用,首先先确认清单文件中 Manifest 标签的 package 属性值(应用程序在系统中的唯一标识)是否相同,其次判断签名是否相同。只有两个都相同,才会存在高版本覆盖低版本的情况。也就是说,只有签名相同或者包名相同,是无法覆盖的。签名是属于企业商业机密,是不能被他人获取的。签名是用一个 key 文件(相当于是秘钥)计算出来的一个字符串,不同的秘钥生成的字符串肯定不同,不同公司的签名也是不同的。所以,一般是无法山寨另一个公司的应用程序的。
PS:1、启动应用程序后,通过 LogCat(LogCat 展示的是 Android 模拟器的后台输出)可以看到一个应用程序的包名。
2、在 Android 里面,安装一个应用程序是不能选路径的。
通过点击 Window–>Show View–>Other…–>Android–>File Explorer,可以查看 Android 设备的文件目录结构。
3、所有第三方应用(也就是可以删除的项目)安装在 data/app 目录下,并且 apk 文件名是以包名命名的。
4、所有系统应用(不可以删除的项目)都安装在 system/app 目录下。
DDMS 是 Dalvik Debug Monitor Service 的简称。DDMS 为 IDE 和 emulator 以及 Android 真机架起来了一座桥梁。开发人员可以通过 DDMS 看到目标机器上运行的进程 / 线程状态,可以看进程的 heap 信息,可以查看 logcat 信息,可以查看进程分配内存情况,可以向目标机发送短信以及打电话,可以向 Android 发送地理位置信息。下面以 Eclipse 的 DDMS perspective 为例简单介绍 DDMS 的功能
1、Devices 选项卡用来查看与开发环境建立连接的 Android 设备,在这里是模拟器,也可以是真机。
2、SD 卡所在的目录为 storage/sdcard。
3、Emulator Control 为控制模拟器的选项卡。
PS:1、这里有个 bug,一旦用模拟器打电话,连接就会终端。只需要点击 Devices 选项卡右边的小三角–>Reset ADB,重启 ADB 即可。
2、DDMS 中所有的选项卡都可以在 Java 中使用,只需要切换到 Java 透视图,点击 Window–>show View,选择需要的选项卡即可。
ADB,Android debug bridge Android 调试桥,用于建立 Android 设备与开发环境的连接。
模拟器中的操作日志原本是不可能在 Windows 平台上输出的。但是,正是由于有了 ADB,所以 LogCat 中才可以输出模拟器中的操作日志。
1、ADB 是一个可执行的指令,在 CMD 中使用,使用前首先配置环境变量。
ADB 相关指令功能介绍:
adb install xxx.apk:把一个 apk 安装到模拟器中。
adb uninstall 应用包名:从模拟器中卸载一个 apk。
adb devices:查看当前跟 eclipse 建立连接的 Android 设备。
PS:adb 同时也是个进程,如果这个进程挂掉了,Android 设备和开发环境连接就会中断。
示例:
1、打开 "任务管理器"–> 点击 "adb.exe"–> 点击 "结束进程"。
2、可以看到没有任何 Android 设备再连接到模拟器上了。
3、通过控制台,我们可以看到经过 11 秒尝试连接后,ADB 连接重新恢复。
4、11 秒时间太长,我们可以使用 adb kill-server 杀死 adb 进程,通过 adb start-server 开启 adb。
可以看到经过不用花 11 秒,ADB 就已经启动了。
5、通过 adb devices 也可以重启 ADB。
adb shell:进入 Android 的命令行,其实是 Linux 的命令行。
示例:
1、可以通过 ls 指令查看当前目录结构。
2、可以通过 cd data 进入 data 目录,然后再通过 ls 查看 data 下的目录结构。
3、通过 ps 可以查看当前 Android 设备上运行的所有的进程,包括 C 进程和 Java 进程。
4、在 Devices 中看到的都是 Java 进程,可以通过 "stop" 按钮关掉进程。例如,关掉 sms(短信)进程。
PS
拨号器只负责拨号功能,打电话功能是通过切换到打电话的应用实现的。拨号器应用可以替换,但是打电话应用是无法替代的,只能使用 Android 自己的打电话应用。原因是与打电话相关的 API,上层应用是无法调用的,只有系统级别的应用才能调用。也就是说打电话相关的 API 在 Android jar 包中都是不存在的。但是,这些 API 在源码中是可以查看的。
步骤一、创建项目。
步骤二、写布局文件,打开 res\layout\activity_main.xml,编辑。
res\layout\activity_main.xml
- <LinearLayout 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"
- android:orientation="vertical"
- tools:context=".MainActivity" >
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="请输入号码:"
- android:textSize="18sp" />
- <EditText
- android:id="@+id/et"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:hint="请输入号码"
- />
- <Button
- android:id = "@+id/bt"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="拨打"
- />
- </LinearLayout>
PS
步骤三、写 java 代码,打开 src\cn.itcast.dialer\MainActivity.java,编辑。
src\cn.itcast.dialer\MainActivity.java
- package cn.itcast.dialer;
- import android.app.Activity;
- import android.content.Intent;
- import android.net.Uri;
- import android.os.Bundle;
- import android.view.Menu;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.widget.Button;
- import android.widget.EditText;
- public class MainActivity extends Activity {
- //onCreate方法是被系统在创建Activity时调用的。
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- //设置按钮点击侦听
- //通过资源id来获取指定的组件的对象
- Button bt = (Button) findViewById(R.id.bt);
- //设置点击侦听
- bt.setOnClickListener(new MyListener());
- }
- //这里的OnClickListener的全名为:android.view.View.OnClickListener
- class MyListener implements OnClickListener {
- //按钮按下时,此方法被调用
- @Override
- public void onClick(View v) {
- //findViewById返回的是布局所有组件的父类android.view.View,需要强转
- EditText et = (EditText) findViewById(R.id.et);
- //拿到用户输入的号码
- String phone = et.getText().toString();
- //告诉系统,我们的动作
- //1. 创建意图对象
- Intent intent = new Intent();
- //2. 设置动作
- intent.setAction(intent.ACTION_CALL);
- //3. 设置号码,通过Uri转
- intent.setData(Uri.parse("tel:" + phone));
- //4. 把动作告诉系统,开启打电话应用的Activity
- startActivity(intent);
- }
- }
- }
在 Android Studio 下,无需关联源码直接点击即可查看源码,因为 Android Studio 会自动反编译源码
1、Ctrl + 左键,点击某个类,再点击 Attach Source 按钮。
2、点击 External Folder…
3、选择关联 sdk\sources\android-18
看到源码,则说明关联成功。
步骤四、试运行,可以看到出现了安全异常,没有权限。因为打电话是需要费用的,所以需要出示权限。
步骤五、添加权限。
打开清单文件 AndroidManifest.xml,使用可视化方式,点击 Permission 选项卡–>Add–>Uses Permission。
添加 Uses Permission 的属性 "android.permission.CALL_PHONE",Ctrl+S 保存。
可以看到清单文件代码中生成了如下代码。
步骤六、重新运行,可以看到,拨打成功。
代码:三种 java 写法。
res\layout\activity_main.xml
- <LinearLayout 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"
- tools:context=".MainActivity"
- android:orientation="vertical">
- <Button
- android:id="@+id/bt_iq"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="点我一下,云鹤智商-10" />
- <Button
- android:id="@+id/bt_eq"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="点我一下,云鹤情商-10" />
- </LinearLayout>
src\cn.itcast.clickevent\MainActivity.java
- package cn.itcast.clickevent;
- import android.app.Activity;
- import android.os.Bundle;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.widget.Button;
- public class MainActivity extends Activity implements OnClickListener{
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- Button bt_iq = (Button) findViewById(R.id.bt_iq);
- Button bt_eq = (Button) findViewById(R.id.bt_eq);
- //第一种:Java写法,内部类实现OnClickListener接口,上个案例中就是按照内部类的方法实现的。
- //第二种:Java写法,匿名内部类实现OnClickListener接口。
- bt_iq.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- System.out.println("点我一下,云鹤智商-10");
- }
- });
- bt_eq.setOnClickListener(this);
- }
- //第三种:Java写法,当前类实现OnClickListener接口。
- @Override
- public void onClick(View v) {
- System.out.println("点我一下,云鹤情商-10");
- }
- }
运行结果:
代码:Android 写法。
res\layout\activity_main.xml
- <LinearLayout 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"
- tools:context=".MainActivity"
- android:orientation="vertical">
- <Button
- android:id="@+id/bt1"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="按钮1"
- android:onClick="click1"/>
- <Button
- android:id="@+id/bt2"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="按钮2"
- android:onClick="click1" />
- <Button
- android:id="@+id/bt3"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="按钮3"
- android:onClick="click1" />
- </LinearLayout>
src\cn.itcast.clickevent\MainActivity.java
- package cn.itcast.clickevent;
- import android.app.Activity;
- import android.os.Bundle;
- import android.view.View;
- public class MainActivity extends Activity {
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- }
- //Android写法。
- //注意:1. 在Activity中定义。
- // 2. 方法名必须与Button的onClick属性值相同。
- // 3. 返回值必须为void。
- // 4. 参数必须为View类型对象。系统调用此方法时,会把触发的对象传进来。这里就是按钮,Button是View的子类。
- // 5. 多个按钮Button的onClick属性值可以相同,点击任何一个按钮都会调用相同的方法。通过id可以判断用户按下的是哪一个按钮。
- public void click1(View v) {
- int id = v.getId();
- switch(id){
- case R.id.bt1:
- System.out.println("按钮1被按下");
- break;
- case R.id.bt2:
- System.out.println("按钮2被按下");
- break;
- case R.id.bt3:
- System.out.println("按钮3被按下");
- break;
- }
- }
- }
运行结果:
代码:res\layout\activity_main.xml
- <LinearLayout 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"
- tools:context=".MainActivity"
- android:orientation="vertical">
- <!-- android:inputType="phone"表示只能输入电话号码 -->
- <EditText
- android:id="@+id/et_phone"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:hint="请输入号码"
- android:inputType="phone" />
- <!-- android:lines="5"表示只能输入5行 -->
- <EditText
- android:id="@+id/et_content"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:hint="请输入内容"
- android:lines="5"/>
- <Button
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="发送"
- android:onClick="send"/>
- </LinearLayout>
src\cn.itcast.smssender\MainActivity.java
- package cn.itcast.smssender;
- import java.util.ArrayList;
- import android.app.Activity;
- import android.os.Bundle;
- import android.telephony.SmsManager;
- import android.view.View;
- import android.widget.EditText;
- public class MainActivity extends Activity {
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- }
- public void send(View v) {
- //获取用户输入的号码和数据
- EditText et_phone = (EditText) findViewById(R.id.et_phone);
- EditText et_content = (EditText) findViewById(R.id.et_content);
- String phone = et_phone.getText().toString();
- String content = et_content.getText().toString();
- //获取发送短信的API
- //SmsManager要使用android.telephony包内的,不要使用android.telephony.gsm包内的,已过时。
- SmsManager sm = SmsManager.getDefault();
- //如果短信过长,发布出去,可以把长短信拆分成若干条短短信。
- ArrayList smss = sm.divideMessage(content);
- for(String str : smss){
- //第一个参数表示对方号码。
- //第二个参数表示短信服务中心的号码,可以传null,表示使用默认的短信服务中心地址。
- //第三个参数表示短信内容。
- //第四个参数表示广播,如果不传null,短信发送成功或失败时,会给予回执信息。
- //第五个参数表示如果对方成功接收信息了,会给予回执信息。
- sm.sendTextMessage(phone, null, str, null, null);
- }
- }
- }
添加权限:
运行结果:
1、发送一般短信结果。
2、发送超长短信结果。
dp 最终显示长度多少是根据屏幕密度来换算的,屏幕越大,1dp 就能显示更长的像素。
320x480 屏幕上,1dp=1px,160dp=160px,正好是屏幕宽度的一般。
480x800 屏幕上,1dp=1.5px,160dp=240px,正好是屏幕宽度的一般
sp 与 dp 类似,只是 sp 用于字体大小,dp 用于长度大小。
res\layout\activity_main.xml
- <LinearLayout 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"
- tools:context=".MainActivity" >
- <TextView
- android:layout_width="160px"
- android:layout_height="wrap_content"
- android:text="@string/hello_world"
- android:background="#ff0000"
- android:textSize="15sp"/>
- <TextView
- android:layout_width="160dp"
- android:layout_height="wrap_content"
- android:text="@string/hello_world"
- android:background="#ff0000"
- android:textSize="15sp"/>
- </LinearLayout>
运行结果:
320x480 屏幕下显示:
480x800 屏幕下显示:
为适应各种界面风格,满足开发的需要,Android 提供了 6 种布局方式
通过这 6 种布局我们可以做出来各种复杂的 UI 效果。
示例 1:res\layout\activity_main.xml
- <LinearLayout 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"
- tools:context=".MainActivity"
- android:orientation="vertical"
- >
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="第一个" />
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="第二个" />
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="第三个" />
- </LinearLayout>
运行结果:
1、设置 android: orientation 为 vertical 结果。
2、设置 android: orientation 为 horizontal 结果。
gravity 属性是指定当前控件内容显示位置:
示例 2:res\layout\activity_main.xml
- <LinearLayout 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"
- tools:context=".MainActivity"
- android:orientation="vertical"
- >
- <TextView
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:gravity="center_horizontal"
- android:text="第一个"
- android:background="#ff0000"/>
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:gravity="center_horizontal"
- android:text="第二个"
- android:background="#00ff00"/>
- </LinearLayout>
运行结果:
设置第一个 TextView 的 android:layout_width 属性值为 match_parent,由于父组件足够宽,因此设置第一个 TextView 的 android:gravity 属性值为 center_horizontal,可以看到控件内容居中。但是,第二个 TextView 的父组件宽高都是由包裹着内容决定的,所以,设置第二个 TextView 的 android:gravity 起不到任何效果。
layout_gravity 属性是指定当前控件在父元素的位置:
示例 3:res\layout\activity_main.xml
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height
来源: http://www.bubuko.com/infodetail-1975112.html