android初探
随着nodejs的不断发展,前端的范围越来越大,所以,适当的了解移动端是非常有必要的,比如使用RN开发app,前端必须要和安卓工程师沟通共同开发,那么学习android的基本知识就很重要了,因为目前安卓开发都是使用额java语言,所以要了解android还是推荐先学一学java基本语言,下面就简单的介绍一下android。
android studio工具参考文章:https://developer.android.com/studio/intro/?utm_source=android-studio
一、android简介
android是一个开源的,基于Linux的移动设备操作系统,主要用于移动设备,比如智能手机以及平板电脑,是由谷歌开发的。
android具有很多优势,比如开放源代码、社区活跃、市场巨大、开发成本低等等。
android也有很多特性,比如连接性好。支持GSM/EDGE、IDEN、CDMA、EV-DO、Bluetooth、Wi-Fi等。使用数据存储的轻量级关系型数据库SQLite。
android应用程序使用android软件开发工具包,使用java语言开发,一旦开发完成,android应用程序可以很容易的打包,并在如Google Play等商店上出售。而我们主要了解学习的也是如何开发并打包android应用程序。
另外,如果要开发android,需要下载相应的开发工具,如java JDK、Android SDK、 JRE、Android Studio等。
注意:在下载android studio时,要直接下载带有SDK的,这样,就不需要单独安装SDK了,下载工具时,可以在eeyes.net下载,下载之后,我们可以参考android studio使用教程。
安装过程中,会报错Android SDK is missing, out of date, 这时我们需要进入 configure -> project default -> project structure 然后设置sdk路径即可:
接下来,我们可以看看android的整体架构:
如上所示,android操作系统是一个软件组件的的栈,在架构图中它大致可以分为五个部分和四个主要层,这四个层中,越往下则越偏向底层,越往上则越偏向应用层。我们下面会逐一介绍:
- 第一层linux内核。在这一层,我们可以看到各种驱动器,比如显示器驱动、相机驱动、蓝牙驱动、flash内存驱动、USB驱动等等。即在所有层的最底下一层就是Linux,它包含了大约115个补丁的Linux3.6,提供了基本的系统功能:进程管理、内存管理、设备管理等。同时,内核处理所有Linux所擅长的工作,比如网络和大量的驱动设备。
- 第二层程序库、android程序库、android运行时。这一层是linux内核层上面的一系列程序库额结合,它包括开源额web浏览器引擎webkit、知名的libc库、用于仓库存储和应用数据共享的SLQite数据库,用于播放、录制音频视频的库以及用于网络安全的SSL库等。android运行时是结构的第三部分,也属于倒数第二层,它是提供名为Dalvik虚拟机的关键组件,类似于java虚拟机,但是专门为了android做了设计和优化。而android程序库中包括了专门为android开发的基于java的程序库,如用户界面构建、图形绘制和数据库访问等。
- android.app - 提供应用程序模型的访问,是所有android应用程序的基石。
- android.content - 方便应用程序、组件之间的内容访问、发布和消息传递。
- android.database - 用于访问内容提供者发布的数据,包含SQLite数据库管理类。
- android.opengl - OpenGL ES 3D图片渲染API的java接口。
- android.os - 提供应用程序访问标注操作系统服务的能力,包括消息、系统服务和进程间通信。
- android.text - 在设备上渲染和操作文本。
- android.view - 应用程序用户界面的基础构建块。
- android.widget - 丰富的预置用户界面组件集合,包括按钮、标签、列表、布局管理、单选按钮等等。
- android.webkit - 一系列类的集合,允许为应用程序提供内建的web浏览能力。
- 第三层应用框架。应用框架以java类的形式为应用程序提供了很多高级的服务。作为应用开发者可以使用这些服务。
- 活动管理器 - 控制应用程序生命周期和活动栈的所有方面。
- 内容提供者 - 允许应用程序之间发布和分享数据。
- 资源管理器 - 提供对非代码嵌入资源的访问,如字符串、颜色设置和用户界面布局等。
- 通知管理器 - 允许应用程序显示对话框或者通知给用户。
- 视图系统 - 一个可扩展的视图集合,用于创建应用程序用户界面。
- 第四层应用程序。这是顶层中所有的android应用程序,我们写的app也会被安装在这一层中,比如通讯录、浏览器、游戏app等。
二、andriod应用程序组件
应用程序组件是一个Android应用程序的基本构建块,而AndroidManifest.xml描述了应用程序的每个组件,以及他们之间是如何交互的。如下是Android应用程序中使用的四个主要组件(ABCS):
- Activities 描述UI,并且处理用户与机器屏幕的交互。
- Services 处理与应用程序关联的后台操作。
- Broadcast Receivers 处理Android操作系统和应用程序之间的通信。
- Content Providers 处理数据和数据库管理方面的问题。
(1)Activities
一个活动(activity)就可以用来标识一个具有用户界面的屏幕。所以,对于一个app来说,会有很多activity,并且其中的一个会被标记为当前app启动时来显示的,且一个活动是Activity类的一个子类:
public class MainActivity extends Activity { }
即这里我们创建了一个MainActivity作为一个屏幕页,它是继承自Acitivity类的。
(2)Services
上面介绍了Activity是一个屏幕,可以和用户进行交互。而这里的service是一个服务,它运行在后台,用来执行长时间操作。比如服务可以是在后台播放音乐、获取网络数据等等,这些服务在执行过程中,不会影响道Acitivity。且所有服务都是继承自 Service类的。如下就是一个服务:
public class MyService extens Service { }
这样,我们就创建了一个Service。
(3)Broadcast Receivers
广播接收器也是很好理解的,就是它会在每个app中存在,可以接收到从其他应用程序或者系统发来的广播消息。比如某个应用程序在将某些数据下载到设备之后,可以通过发起广播让其他应用程序知道这些数据已经被下载了,然后其他这些被广播到的应用程序就可以使用了。且所有的广播接收器都是 BroadcastReceiver类的一个子类,如下:
public class MyReceiver extends BroadcastReceiver { }
(4)Content Providers
内容提供者组件通过请求从一个应用程序到另外一个应用程序提供数据。 这些数据可以存储在文件系统、数据库或者其他地方。且所有的内容提供者组件继承自 ContentProvider类,如下:
public class MyContentProvider extends ContentProvider { }
(5)附件组件
还有一些附件的组件也会常常用到,如下:
- Fragments 代表活动中的一个行为或者一部分用户界面。
- Views 绘制在屏幕上的UI元素,包括按钮、列表等。
- Layouts 控制屏幕格式,展示视图外观的View的继承。
- Intents 组件间的消息连线。
- Resources 外部元素,例如字符串资源、常用资源以及图片资源等。
- Manifest 应用程序的配置文件。
三、一个简单的android实例
通过Eclipse或者是Android Studio创建一个新的项目,可以将程序命名为HelloWorld,创建成功之后,会自动生成一些文件,我们首先需要了解Android项目中的一些文件目录和文件。
注意:推荐使用Android Studio,它是谷歌开发的,而安卓系统也是谷歌的,所以就可以知道还是优先选择android studio。 但是前几年更多的用的是eclipse,因为as是近几年才推出的,不过android studio是一个趋势。
下面的文件目录是使用Eclipse所创建的:
如上,我们创建了这么一个HelloWorld项目,下面有一些重要的文件逐一介绍:
- src: 包含项目中的所有.java源文件,默认情况下它包括一个MainActivity.java源文件对应的活动类,当应用程序通过应用图标启动时,就会运行它。
- gen:这包含了由编译器生成的.R文件,引用了所有项目中的资源。该文件是不能被修改的。
- bin: 这个文件夹包含了Android由APT构建的.apk包文件以及运行Android应用程序锁需要的其他所有东西。
- res/drawable-hdpi: 这个目录下包括所有的为高密度屏幕设计所需的drawable对象。
- res/layout: 这个目录存放用于定义用户界面的文件。
- res/values: 这个目录存放各种各样的包含一些列资源的XML文件,比如字符串和颜色的定义。
- AndroidManifest.xml 这个是应用程序的清单文件,描述了应用程序的基础特性。
(1)主要活动文件
主要活动代码在MainActivity.java的Java文件中,这是实际的应用程序文件,将被转化为Dalvik可执行文件并运行,下面是默认代码:
package com.example.helloworld; import android.os.Bundle; import android.app.Activity; import android.view.Menu; import android.view.MenuItem; import android.support.v4.app.NavUtils; public class MainActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.activity_main, menu); return true; } }
这里的R.layout.activity_main引用自res/layout目录下的activity_main.xml文件。而onCreate()可以看做是活动被加载之后众多被调用的方法之一,它是一个钩子函数。
(2)Manifest文件
无论开发什么组件作为应用程序的一部分,都需要在应用程序根目录下的manifest.xml文件中声明所有的组件。这个文件是Android操作系统和应用程序之间的接口。
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.helloworld" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="22" /> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".MainActivity" android:label="@string/title_activity_main" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> </application> </manifest>
(3)Strings文件
即strings.xml文件在res/value文件夹下,它包含了应用程序使用到的所有文本。比如按钮、标签的名称、默认文本以及其他相似的strings。一个默认的strings文件如下:
<resources> <string name="app_name">HelloWorld</string> <string name="hello_world">Hello world!</string> <string name="menu_settings">Settings</string> <string name="title_activity_main">MainActivity</string> </resources>
(4)R文件
gen/com.example.helloworld/R.java文件是活动的Java文件,是通过java编译德奥的,不能修改,下面就是一个R.java文件的示例:
/* AUTO-GENERATED FILE. DO NOT MODIFY. * * This class was automatically generated by the * aapt tool from the resource data it found. It * should not be modified by hand. */ package com.example.helloworld; public final class R { public static final class attr { } public static final class dimen { public static final int padding_large=0x7f040002; public static final int padding_medium=0x7f040001; public static final int padding_small=0x7f040000; } public static final class drawable { public static final int ic_action_search=0x7f020000; public static final int ic_launcher=0x7f020001; } public static final class id { public static final int menu_settings=0x7f080000; } public static final class layout { public static final int activity_main=0x7f030000; } public static final class menu { public static final int activity_main=0x7f070000; } public static final class string { public static final int app_name=0x7f050000; public static final int hello_world=0x7f050001; public static final int menu_settings=0x7f050002; public static final int title_activity_main=0x7f050003; } public static final class style { public static final int AppTheme=0x7f060000; } }
(5)Layout文件
activity_main.xml是一个在res/layout目录下的layout文件,我们需要非常频繁的修改这个文件来改变应用程序的布局,在“hello world”应用程序中,这个文件有默认的布局,如下:
<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" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:padding="@dimen/padding_medium" android:text="@string/hello_world" tools:context=".MainActivity" /> </RelativeLayout>
其中的TextView是一个Android的控件,用于构建用户图形界面,它包含了很多不同的属性,比如android:layout_width, android:layout_height等用来设置它的宽度和高度等。 其中@string是指res/values文件夹下的strings.xml文件。因此@string/hello_world指的是定义在strings.xml中的名为hello的字符串:"Hello World!"。
上面都清楚了之后,点击工具栏上的运行图标,就可以在模拟器窗口上看到你开发的应用程序了。
而下面的目录是通过Android Studio所创建的:
如上所示,就是一个创建出来的文件系统了,主要的内容在app中,这也是我比较喜欢的,并且将java和res都归为src中了,也是比较合适的,在src下面除了main之外,还有一些测试版本,整体还是非常有序的。
注意:这里我们选择的是Project,所以这种结构和磁盘中的真实存储方式是一样的,如果切换成android模式,会把一些必要的文件显示,而一些不必要的没有显示,但是我还是更习惯project形式的。
如何在Android Studio中将android项目生成apk文件?
如上所示,进入build的Generate Signed APK即可,如果没有签名,需要自行创建,然后就可以使用了。它会默认将文件存在C:/users/administrator/androidproject下,接着,我们把这个文件传输到手机上即可。
更多可以参考这篇文章
四、android资源访问
(1)资源管理
构建一个android程序,除了java代码,还需要大量的资源,比如位图、颜色定义、布局定义、字符串等等,这些资源一般在项目的res/目录下。 res/目录在各种子目录中包含了所有的资源,下标列出了res/目录中支持的资源:
在学习JavaScript时,我们发现XML文件几乎是没有用处的,除了在制作svg时广泛应用,但是在android开发时,xml文件却用的很广泛,上面的列表中,我们说res/目录下的资源大部分都是xml,比如anim下的xml文件用来定义动画、drawalbe下的xml用来定义图片、layout这个布局目录下的xml定义布局(非常重要)、values下的各种基本类型都是xml文件定义、最后xml目录还可以给开发者更多空间。
(2)资源替代
android开发不可能始终使用同样的资源,比如一般屏幕上的图片资源和高dpi屏幕上的图片资源是不一样的;国外手机和国内手机使用语言不同导致使用的资源也是不一样的;针对不同的设备资源可能也是不一样的,所以,我们需要为特定情况配置一些替代资源。
如下所示:
MyProject/ src/ main/ java/ MyActivity.java res/ drawable/ icon.png background.png drawable-hdpi/ icon.png background.png layout/ activity_main.xml info.xml values/ strings.xml
我们可以看到在res目录下drawable和drawable-hdpi的区别,后者是针对高dpi的手机提供的icon.png和background.png,这样,开发者就可以根据不同的手机来调用不同的图片了,这就是所谓的资源替代了。
又比如下面,我们可以对不同语言配置不同的替代资源:
MyProject/ src/ main/ java/ MyActivity.java res/ drawable/ icon.png background.png drawable-hdpi/ icon.png background.png layout/ activity_main.xml info.xml layout-ar/ main.xml values/ strings.xml
(3)资源访问
在android中,资源访问有两种方式,一种是通过java代码来访问资源;另外一种是在xml中直接访问。
a. 代码访问
比如下面的res/values/strings.xml是存放资源的文件,稍后,我们就会从访问下面这个文件中的资源:
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="hello">Hello, World!</string> </resources>
然后,我们就可以通过代码来访问了:
TextView msgTextView = (TextView) findViewById(R.id.msg); msgTextView.setText(R.string.hello);
其中第一行是为了获得合适的TextView,第二行是为了设置TextView中的值,这也就是通过代码访问资源了。
b.在XML中访问
比如在res/values/strings.xml中,就是我们需要使用的资源:
<?xml version="1.0" encoding="utf-8"?> <resources> <color name="opaque_red">#f00</color> <string name="hello">Hello!</string> </resources>
我们可以在布局文件中来访问这个资源,而不是通过java代码:
<?xml version="1.0" encoding="utf-8"?> <EditText xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:textColor="@color/opaque_red" android:text="@string/hello" />
这里,我们通过@color/opaque_red就访问到xml文件中的颜色了;通过@string/hello就访问到xml中的hello字符串了。
五、Android 活动(Activity)
活动在androi中代表了一个具有用户界面的单一屏幕,我们知道c++/java都是从main函数开始执行的,同样的,androi系统是从活动中的 onCreate() 回调的调用开始的,下面就是activity活动的生命周期:
即这个活动周期的过程中,就给我们提供了一些列的钩子函数,vue中的生命周期和android的这个生命周期就非常类似,同样的,这里的生命周期也是从上到下完成了一个android应用程序从构建到结束的过程,下面我们简单介绍:
- onCreate() - 该方法是Activity被创建时回调,我们在创建Activity时一般都需要重写该方法,然后在该方法中做一些初始化的操作,如通过setContentView设置界面布局的资源,初始化所需要的组件信息等。
- onStart() - 此方法被调用时Activity已经处于可见状态,但是还没有在前台显示,所以无法和用户进行交互,简单理解为Activity已经显示但是我们无法看见。
- onResume() - 当此方法回调时,说明Activity已经在前台可见,可以与用户交互了。
- onPause() - 表示Activity正在停止(Paused形态)。
- onStop() - 一般会在onPause方法执行完后直接执行,表示Activity即将停止或者完全被覆盖,此时Activity不可见,仅在后台运行。
- onDestroy() - 表示Activity正在被销毁,也是生命周期最后一个执行的方法,一般我们可以在此方法中做一些回收工作和最后的资源释放。
- onRestart() - 表示Activity正在重新启动。一般是用户打开了一个新的activity时,当前的Activity就会暂停,接着又回到了当前Activity页面时,onRestart方法就会被回调。
如下是MainActivity.java修改的内容,里面包含每一个基本的生命周期方法,Log.d方法用来生成日志信息:
package com.example.administrator.helloworld; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; public class MainActivity extends AppCompatActivity { String msg = "Android: "; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Log.d(msg, "The onCreate() event"); } protected void onStart() { super.onStart(); Log.d(msg, "The onStart() event"); } protected void onResume() { super.onResume(); Log.d(msg, "The onResume() event"); } protected void onPause() { super.onPause(); Log.d(msg, "The onPause() event"); } protected void onStop() { super.onStop(); Log.d(msg, "The onStop() event"); } protected void onDestroy() { super.onDestroy(); Log.d(msg, "The onDestroy() event"); } }
接着,在android studio中启动这个app,然后就可以看到如下信息了:
D/Android:: The onCreate() event D/Android:: The onStart() event D/Android:: The onResume() event
然后我们再在android studio中按暂停、结束等按钮也可以看到其他相关信息。
六、Android服务(Service)
服务是一个后台运行的组件,执行长时间运行且不需要用户交互的任务。即使应用被销毁也是可以工作的,服务包含有两种状态:
- Started - Android的应用程序组件通过startService()启动了服务,那么服务就是Started状态,一旦启动,服务可以在后台无限期运行,即使他的组件已经被销毁。
- Bound - 当Android的应用程序组件通过bindService()绑定了服务,则服务是Bound状态。 Bound状态的服务提供了一个客户服务器接口来允许组件和服务进行交互,如发送请求、获取结果,甚至通过IPC来进行跨进程通信。
服务也是拥有生命周期方法的,可以实现加农服务状态的变化,可以在合适的阶段执行工作,下面的左图展示了当服务通过startService()被创建时的生命周期,右图则显示了当服务通过bindService()被创建时的生命周期:
要创建服务,你需要创建一个继承自Service基类或者它的已知子类的Java类。Serviece基类定义了不同的回调方法和多数重要方法。你不需要实现所有的回调方法,但是理解这些方法还是非常重要的。
- onStartCommand() 其他组件通过调用startService()请求来启动服务时,系统调用该方法。
- onBind() 当其他组件想要通过bindService()来绑定服务时,系统调用该方法。
- onUnbind() 当客户中断所有服务发布的特殊接口时,系统调用该方法。
- onRebind() 当新的客户端与服务链接,且此前它已经通过onUnbind通知断开连接时,系统调用该方法。
- onCreate() 当服务通过onStartCommand()和onBind()被第一次创建的时候,系统调用该方法。
- onDestroy() 当服务不再有用或者被销毁时,系统调用该方法。
七、Android广播接收器(Broadcast Receivers)
广播接收器用于响应来自其他应用程序或者系统的广播消息。这些消息有时被称为事件。