android_and_eclipse
Posted guomc
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了android_and_eclipse相关的知识,希望对你有一定的参考价值。
目录
二、生命周期
三、用户界面UI
四、组件通信与广播
五、后台服务
六、数据存储与访问
七、位置和地图
八、Widget组件开发
九、android NDK
十、特效
十一、 附录
正文
一、构建Android开发环境
- 用eclipse做Android的开发
(1) 下载JDK的可执行文件并执行
(2) 下载adt的zip压缩包
(3) 下载较新的SDK并解压SDK
(4) 下载eclipse并运行,选择help->install new software->add->archive->下载完毕的adt压缩文件
(5) 重启eclipse后选择SDK解压后的位置
(6) Windows系统利用上vt技术的话,AVD的反应速度要快很多:启动BOIS启动vt,在sdkextrasintelHardware_Accelerated_Execution_Manager下安装intel加速器,在此基础上建立一个intel驱动的AVD。
(7) 创建新项目
- 用手机做虚拟设备
下面用的是SUMSUNG手机,这种办法只能看到当前应用的信息
(1)About phone->Software information
(2)连续点击Build number3次
(3)在Developer options中打开USB debugging,并选择适当设置
(4)用USB连接手机,就可以通过IDE选择这个手机做模拟设备,运行需要调试的应用
二、生命周期
程序在Android系统中从启动到终止的所有过程,程序不能控制自身的生命周期而受系统的调度和控制。
- 用于调度和控制的事件回调函数
onSaveInstanceStae()用于保存activity界面的临时信息、信息一般放在Bundle中,onRestoreInstanceState()用于程序被销毁时恢复临时信息、比如程序遇到锁屏或者被系统中断,但是它们都不是生命周期的时间回调函数。
onCreate() |
用于activity的初始化、创建连接、绑定数据等,是第一个被调用的函数 |
onStart() |
activity显示在屏幕上时被调用 |
onRestart() |
activity重新启动时调用、之后调用onResume()继续和用户交互 |
onResume() |
获取屏幕焦点、接收用户输入时被调用 |
onPause() |
程序被其他窗口覆盖,系统调用函数“暂停”程序、之后调用onSaveInstanceStae()保存临时信息 |
onStop() |
用户不可见时,进入停止对activity更新 |
onDestroy() |
程序调用finish()函数或者被系统终结的时候调用 |
- 参考的调用顺序
- 软件测试方法
(1) 日志点
比如Log.i(String TAG,String cnt);,还可以选.w、.e等不同的日志信息等级,查看日志的方法是在Logcat中建立过滤器,输入Filter Name、Tag的内容(即字符串TAG),选择日志的级别确定即可。
(2) 应用程序提示
比如Toast.makeText(MainActivity.this, "服务未绑定", Toast.LENGTH_SHORT).show();
(3) DevTools
作为前两种办法的补充,如果前面的办法还不能分析出错误原因,再考虑DevTools提供的信息。
三、用户界面UI
- MVC模型
模型、视图、控制器,控制器加工用户输入的数据、交给处理核心“模型”,最终由“模型”来更新视图。
- 界面控件
用eclipse的layout设计界面制作静态的UI,用java控制动态的内容、先声明一个控件变量然后用findViewById引用xml中的资源进行初始化。具体的函数可以查阅android的API文档。
控件的属性在设计界面中有,也可以查阅android的手册。
(1)显示和编辑字符的控件
设计界面中双击控件,可以进入控件的xml文件
<TextView android:id=”@+id/TextView0”
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:text=”TextView0”/>
(2)按钮控件
Button、ImageButton
(3)提供选择的控件
CheckBox用于多选、RadioGroup和RadioButton用于单选。
(4)微调选框
Spinner是一个类似下拉列表的东西,因为可能有不同的选项、存在动态的内容,需要java写适配器将要显示的内容和底层的数据统一起来。一个可行的例子是:
//spinner初始化
spinner = (Spinner) findViewById(R.id.spinner1);
//要显示的数据
List<String> li=new ArrayList<String>();
li.add("cnt0");
li.add("cnt1");
li.add("cnt2");
li.add("cnt3");
//适配器初始化
ArrayAdapter<String> ad=new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item,li);
//适配器样式
ad.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
//给spinner设置适配器ad
spinner.setAdapter(ad);
(4)垂直显示的列表控件
ListView中如果内容很多,就会出现滚动条;如果没有内容,将不显示控件。
(4)设置监听器
监听器属于控件的方法,将使用内部类、如果出现错误可能是没有加上View.,在android_api.chm中也有具体的说明。比如OnClickListener、
① 控件独占一个监听器
比如列表控件中给每个子项设置监听器,listView.setOnItemClickListener(new AdapterView.OnIOnItemClickListener(){…});
② 多个控件共享一个监听器
方法是定义一个监听器,然后用v.getId()区分各个控件写上需要的代码,最后控件绑定这个监听器。如果一种类型的控件多次出现,尽量用这种方法设置监听器,消除一些不必要的冗余,。
- 界面布局
布局之间可以相互嵌套,按常用的程度分为:
(1)线性布局
LinearLayout可以选择水平也可以选择垂直,还可以像html中table的行列组合使用、这样就灵活多了。
(4) 相对布局
RelativeLayout使用相对的位置以适应不同的屏幕尺寸,灵活而且比较稳定。
(5) 网格布局
和表格布局类似,但是网格布局中的元素可以占用多个网格,而表格布局中的元素不能跨行跨列。
(6) 表格布局
TableLayout默认控件独占一行,TableRow默认控件尽量放在一行。
(7) 绝对布局
在layout设计界面中已经找不到,但是在手动创建布局的xml文件的时候有这样一种布局,部件的位置像坐标一样严格的受到数值的控制、不同的设备上效果不一定好。
- 菜单(操作栏,由菜单组成)
可以在onCreate函数中用getActionBar().hide();隐藏操作栏的菜单,也可以通过修改app的主题styles做到同样的效果
(1)菜单资源
在menu目录中用layout设计菜单、onCreateOptionsMenu函数中用getMenuInflater().inflate方法映射成Menu对象,之后在onOptionsItemSelected函数中写入动态交互的内容即可;也可以用纯代码的方式实现,比如:
一级菜单 |
menu.add(0, menu0, 0, "打印").setIcon(R.drawable.ic_launcher); |
多级菜单 |
menu.addSubMenu(0, menu0, 0, "新建").setIcon(R.drawable.ic_launcher); |
说明:menu0是int对象要提前用Menu.FIRST初始化 |
(2)快捷菜单
具有快捷菜单的元素,如果按住它超过两秒,就会启动它的快捷菜单;和菜单资源类似,不同的是需要重载onCreateContextMenu函数,最后对需要的元素注册快捷菜单,方法是registerForContextMenu。
- Fragment可重用模块
把页面中可能重复使用的部分做成Fragment,在一个activity中调用、提高了代码的可重用性。
(1)Fragment生命中的事件回调函数
(2)使用方法
① layout设计界面中添加需要的Fragment、创建继承自Fragment的类
② 设计Fragment对应的xml界面
③ 重载Fragment类中的函数onCreateView、改写return inflater.inflate(R.layout.bfragment, container, false);即可。
- 事件监听
(1) 键盘事件setOnKeyListener
监听器中的函数的返回值为true将阻止事件传递给界面元素,界面元素就不会更新;程序中和事件有关的变量,它的信息可以类的声明中找到。
(2) 触摸事件setOnTouchListener
比较典型的函数 |
值的说明 |
函数的说明 |
getAction() |
ACTION_DOWN、ACTION_UP、ACTION_MOVE等 |
获取动作 |
getX()、getY() |
|
获取相对坐标,相对前一个位置 |
getRawX()、getRawY() |
|
获取绝对坐标 |
getPressure() |
|
触点的压力 |
getSize() |
|
触点的尺寸 |
getHistorical…() |
|
获取历史数据中的第几个数据 |
四、组件通信与广播
- Intent
不论这些组件是否在一个应用程序中都可以用Intent进行通信,显式通信需要指明组件具体的类,隐式通信发出动作即可、信息的接收方由系统决定。
(1) 显式通信,比如用Intent启动一个activity(这两个activity都已经在Manifest中注册):
Intent intent=new Intent(IntentDemoActivity.this,NewActivity.class);
startActivity(intent);
(2) 隐式通信,由动作触发:
Internt intent=new Intent(Intent.ACTION_VIEW,Uri.parse(“http://cn.bing.com/”));
startActivity(intent);
动作 |
说明 |
ACTION_VIEW |
提供浏览的activity,Uri“http://...”表示网页地址、“tel:..”是电话号码 |
|
|
(3) 获取子activity的返回值
① 父activity中设置子activity的标签,之后发送消息,比如:
SubActivity1就是一个用于区分不同子activity的标签
Intent intent=new Intent(MainActivity.this, Activity1.class);
startActivityForResult(intent,SubActivity1);
② 子activity封装Uri信息,并设置结果,比如:
finish()可有可无
Uri data=Uri.parse(editText.getText().toString());
Intent result=new Intent(null, data);
setResult(RESULT_OK, result);
finish();
③ 父activity接收消息,需要重载函数onActivityResult:
函数的参数依次是标签、设置的结果标记、Uri数据;在函数中写需要的代码
- Intent过滤器
这是隐式启动的匹配机制:当应用安装到Android系统的时候,会注册自己组件和Intent过滤器,这样系统就可以通过Intent过滤器映射每一个Intent请求到相应的组件上;可以在Manifest配置文件中、特定的组件下定义<intent-filter>节点,得到组件的Intent过滤器
(1) Intent过滤器的标签
标签 |
属性 |
说明 |
|
<action> |
android:name |
动作,VIEW视图、包名 |
|
<category> |
android:category |
分类,LAUNCHER启动时最先被显示、DEFAULT默认 |
|
<data> |
android:host |
数据 |
指定主机名 |
android:mimetype |
指定activity能处理的文档类型 |
||
android:path |
Uri路径 |
||
android:port |
端口号 |
||
android:scheme |
指定的协议 |
(3) 使用Intent过滤器
如果一个activity的过滤器是这样定义的:
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="schemodemo" android:host="edu.hrbeu" />
</intent-filter>
那么可以用Intent这样调用activity:
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("schemodemo://edu.hrbeu/"));
startActivity(intent);
- 广播
(1)发出信号
需要一个区别于其他全局消息的标志,可以是程序包的名称,之后发送键值对形式的信号:
Intent intent=new Intent("com.example.demo0");
intent.putExtra("key", editText.getText().toString());
sendBroadcast(intent);
(2)接收信号
①Manifest文件下添加receiver,并声明它的过滤器(可以接收的消息类型),比如:
<receiver android:name=".Activity1">
<intent-filter>
<action android:name="com.example.demo0"/>
</intent-filter>
</receiver>
②定义一个activity,比如是Activity1、它继承自BroadcastReceiver,之后重载onReceive函数用来处理接收到的数据:
String value=intent.getStringExtra("key");
Toast.makeText(context, value, Toast.LENGTH_SHORT).show();
五、后台服务
指的是没有界面且长时间在后台运行的应用功能,很典型的是Service服务组件,比如MP3播放器,界面关闭后音乐还在播放,这就需要用到Service,此外Service还可以用于进程间的通信。
- java和CC++易混淆的语法
boolean是java中的布尔值 |
java类中的变量声明马上就可以初始化,这点和CC++不同 |
null相当于CC++中的NULL |
- Service的生命周期
- 本地服务
(1) 显式使用Service
① Manifest中注册Service:
<service android:name=".RandomService"></service>
② 定义一个activity继承自Service,可以在onStart函数中、也可以其他合理的地方写需要的功能
③ 显式调用、停止Service:
final Intent intent=new Intent(MainActivity.this, RandomService.class);
startService(intent);
stopService(intent);
(2) 隐式使用Service
① Manifest中注册Service,不同的是需要添加过滤器(声明可以接收的数据类型,甚至可以精确到Service类的名字):
<service android:name=".RandomService">
<intent-filter>
<action android:name="com.example.demo0"/>
</intent-filter>
</service>
② 定义一个activity继承自Service,可以在onStart函数中、也可以其他合理的地方写需要的功能
③ 隐式调用、停止Service,隐式调用的时候发出动作action即可:
final Intent intent=new Intent("com.example.demo0");
startService(intent);
stopService(intent);
- 多线程
Android系统中如果一个线程处理的时间过长,会降低用户界面的响应速度、甚至使界面失去响应,将耗时的处理过程分解到子线程上是一个可行的解决办法。
(1) 在主线程activity中定义Handle变量,用来接收服务线程Runable中时刻变化的数据:
static Handle handle;
public static void updateGUI(服务线程传入的新数据){
handle.post(refreshLabel);
}
static Runable refreshLabel=new Runable(){
@Override
public void run() {
// TODO Auto-generated method stub
用新数据更新UI界面
}
}
(2) Service中运用多线程:
① 定义用于事务处理的线程:
Thread serviceThread;
Runnable backgroundWork = new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
try {
while (!Thread.interrupted()) {
//过程代码,用于提供服务
double randNum = Math.random();
MainActivity.updateGUI(randNum);
Thread.sleep(1000);
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
② onCreate函数初始化这个线程:
serviceThread = new Thread(null, backgroundWork, "serviceThread");
③ onStart函数检查线程是否正常工作:
if (!serviceThread.isAlive()) {
serviceThread.start();
}
④ onDestory函数终止线程:
serviceThread.interrupt();
- 绑定服务
最简单的Service不接收参数也不返回参数,只接受调用;多线程的Service不接收参数自己产生变化,并通过调用主线程中的某些函数达到更新UI的目的;绑定服务的Service可以接收参数也可以返回参数,有Service的作用(避免界面失去响应、提供服务)、又可以像函数一样方便使用,这是很有意义的。
(1) 新建一个继承自service的类,比如MathService并在类中写入需要提供服务的函数
(2) 新建一个IBinder对象,重载onBind()和onUnbind()函数:
IBinder mBinder=new LocalBinder();
class LocalBinder extends Binder{
MathService getService() {
return MathService.this;
}
}
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return mBinder;
}
@Override
public boolean onUnbind(Intent intent) {
// TODO Auto-generated method stub
return false;
}
(3) 主线程的activity中声明一个服务类的变量,重载一个ServiceConnection变量:
MathService mathService = null;
ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
//服务意外断开的时候,系统调用的函数
mathService = null;
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub
mathService = ((MathService.LocalBinder) service).getService();
}
};
(4) 绑定服务
Intent serviceIntent = new Intent(MainActivity.this, MathService.class);
bindService(serviceIntent, mConnection, Context.BIND_AUTO_CREATE);
(5) 取消绑定
//这个函数未必有用
unbindService(mConnection);
mathService = null;
(6) 提供服务
int res = mathService.add(a, b);
- 远程服务
这是除Intent外的另一种进程间的通信方式,可以将服务和调用者以不同应用的方式在一个系统中独立起来。
(1) 建立一个Service,之后用AIDL定义远程服务的接口,即写一个.aidl文件,比如:
AIDL即安卓接口定义语言,语法上类似java,但是AIDL允许参数有方向
package com.example.demo0;
interface IMathService{
int add(int a,int b);
}
(2) Service中需要一个Binder对象:
//也是这个Service提供的服务
IMathService.Stub mBinder=new IMathService.Stub() {
@Override
public int add(int a, int b) throws RemoteException {
// TODO Auto-generated method stub
return a+b;
}
};
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return mBinder;
}
@Override
public boolean onUnbind(Intent intent) {
// TODO Auto-generated method stub
return false;
}
(3) 新建一个调用者的工程,将Service中的AIDL连同包复制过来
(4) 需要一个ServiceConnection:
// 能够提供服务的对象
IMathService mathService;
ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
mathService = null;
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub
mathService = IMathService.Stub.asInterface(service);
}
};
(5) 绑定服务
Intent serviceIntent = new Intent();
serviceIntent.setAction("top.guomc.demo0.MathService");
bindService(serviceIntent, mConnection, Context.BIND_AUTO_CREATE);
(6) 取消绑定
unbindService(mConnection);
mathService = null;
(7) 提供服务
int res = 0;
try {
res = mathService.add(a, b);
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
- 自定义数据的传输
在远程服务中,java基本数据类型的打包过程是自动完成的,但是自定义的数据(类)需要重载Parcelable接口来完成打包的过程
(1) 自定义数据的.aidl文件,AllResult.aidl:
package top.guomc.demo0;
parcelable AllResult;
(2) 提供服务函数的.aidl文件,IMathService.aidl:
package top.guomc.demo0;
import top.guomc.demo0.AllResult;
interface IMathService{
AllResult computeAll(int a,int b);
}
(3) 自定义的类,这个类重载了Parcelable接口,AllResult.java
定义内部数据
//序列化
static Parcelable.Creator<AllResult> CREATOR = new Creator<AllResult>() {
@Override
public AllResult[] newArray(int size) {
// TODO Auto-generated method stub
return new AllResult[size];
}
@Override
public AllResult createFromParcel(Parcel source) {
// TODO Auto-generated method stub
return new AllResult(source);
}
};
定义构造函数
//内部数据写到包
@Override
public void writeToParcel(Parcel dest, int flags) {
// TODO Auto-generated method stub
dest.writeInt(addRes);
dest.writeInt(subRes);
dest.writeInt(mulRes);
dest.writeDouble(divRes);
}
(4) 定义Service,MathService.java:
IMathService.Stub mBinder = new IMathService.Stub() {
@Override
public AllResult computeAll(int a, int b) throws RemoteException {
// TODO Auto-generated method stub
int addRes = a + b;
int subRes = a - b;
int mulRes = a * b;
double divRes = (double) a / b;
AllResult res = new AllResult(addRes, subRes, mulRes, divRes);
return res;
}
};
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return mBinder;
}
@Override
public boolean onUnbind(Intent intent) {
// TODO Auto-generated method stub
return false;
}
(5) 将服务方的自定义类型连同.aidl、目录复制到接收方
(6) ServiceConnection、绑定服务、取消服务和上面一样
(7) 提供服务
AllResult allResult = null;
try {
allResult = mService.computeAll(a, b);
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
用定义过的getter函数将allResult的内部数据获取出来
六、数据存储与访问
七、位置和地图
八、Widget组件开发
九、Android NDK
十、特效
1.tab标签页
继承自Activity的类可以管理这些标签页,如果要实际使用,还需要在AndroidManifest<application/>下面注册这个类。
(1)在layout设计界面中制作tab标签页,并将标签页加入R的id资源中
(2)创建继承自TabActivity的类作为入口,用getTabHost()初始化tabHost
(3)将tab标签页转为java管理的对象,比如LayoutInflater.from(this).inflate(R.layout.tab1, tbHost.getTabContentView());
(4)tabHost添加上这些标签页,比如tbHost.addTab(tbHost.newTabSpec("tab3").setIndicator("FrameLayout").setContent(R.id.layout3));,其中“tab3”是程序中的标记,而“FrameLayout”是标签将显示的标题。
十一、 附录
1.参考网址
www.oracle.com/ |
下载JDK |
|
|
|
|
2.eclipse快捷键
alt+shfit+n |
新建工程 |
alt+shift+r |
重命名 |
alt+shift+s |
选择内置函数,比如继承某些内置的方法 |
ctrl+d |
删除一行或者选中块 |
alt+/ |
关键字提示 |
alt+上下键 |
移动选中块代码 |
选中文件alt+shift+r |
重命名 |
ctrl+alt+上下键 |
复制选中块,可以在preference中设置 |
ctrl+shift+f |
快速格式化 |
选中,ctrl+shift+/或者 |
注释、反注释 |
ctrl+/ |
快速注释、反注释一行 |
ctrl+l |
快速到某一行 |
ctrl+f11 |
运行代码 |
ctrl+点击 |
查看更详细的定义 |
3.adb命令
adb即Android Debug Bridge安卓调试桥,用于管理android设备或模拟器的工具;用命令行工具进入platform,下面的命令都需要在前面加上adb,才会有效
install .apk的完整路径 |
安装某个安卓文件 |
help |
帮助命令 |
version |
adb的版本信息 |
shell 命令 |
执行shell命令 |
push 本地文件 目标路径 |
上传本地文件 |
pull 目标路径 [本地路径] |
将设备上的文件下载下来,本地路径默认是adb的路径 |
4.avd命令
avd即安卓虚拟设备,进入tools目录下,可以用命令行创建和编译安卓程序;
android list targets |
镜像文件清单 |
android list avds |
avd的清单 |
|
|
以上是关于android_and_eclipse的主要内容,如果未能解决你的问题,请参考以下文章