android_and_eclipse

幼敏悟过人,读书辄成诵。这篇文章主要讲述android_and_eclipse相关的知识,希望能为你提供帮助。
目录
一、构建Android开发环境
二、生命周期
三、用户界面UI
四、组件通信与广播
五、后台服务
六、数据存储与访问
七、位置和地图
八、Widget组件开发
九、android NDK
十、特效
十一、            附录
 
正文
一、构建Android开发环境

  1. 用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)      创建新项目
  1. 用手机做虚拟设备
下面用的是SUMSUNG手机,这种办法只能看到当前应用的信息
(1)About phone-> Software information
(2)连续点击Build number3次
(3)在Developer options中打开USB debugging,并选择适当设置
(4)用USB连接手机,就可以通过IDE选择这个手机做模拟设备,运行需要调试的应用
 
二、生命周期
程序在Android系统中从启动到终止的所有过程,程序不能控制自身的生命周期而受系统的调度和控制。
  1. 用于调度和控制的事件回调函数
onSaveInstanceStae()用于保存activity界面的临时信息、信息一般放在Bundle中,onRestoreInstanceState()用于程序被销毁时恢复临时信息、比如程序遇到锁屏或者被系统中断,但是它们都不是生命周期的时间回调函数。
【android_and_eclipse】onCreate()
用于activity的初始化、创建连接、绑定数据等,是第一个被调用的函数
onStart()
activity显示在屏幕上时被调用
onRestart()
activity重新启动时调用、之后调用onResume()继续和用户交互
onResume()
获取屏幕焦点、接收用户输入时被调用
onPause()
程序被其他窗口覆盖,系统调用函数“暂停”程序、之后调用onSaveInstanceStae()保存临时信息
onStop()
用户不可见时,进入停止对activity更新
onDestroy()
程序调用finish()函数或者被系统终结的时候调用
  1. 参考的调用顺序
 
  1. 软件测试方法
(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
  1. MVC模型
模型、视图、控制器,控制器加工用户输入的数据、交给处理核心“模型”,最终由“模型”来更新视图。
  1. 界面控件
用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. 界面布局
布局之间可以相互嵌套,按常用的程度分为:
(1)线性布局
LinearLayout可以选择水平也可以选择垂直,还可以像html中table的行列组合使用、这样就灵活多了。
(4)      相对布局
RelativeLayout使用相对的位置以适应不同的屏幕尺寸,灵活而且比较稳定。
(5)      网格布局
和表格布局类似,但是网格布局中的元素可以占用多个网格,而表格布局中的元素不能跨行跨列。
(6)      表格布局
TableLayout默认控件独占一行,TableRow默认控件尽量放在一行。
(7)      绝对布局
在layout设计界面中已经找不到,但是在手动创建布局的xml文件的时候有这样一种布局,部件的位置像坐标一样严格的受到数值的控制、不同的设备上效果不一定好。
  1. 菜单(操作栏,由菜单组成)
可以在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。
  1. Fragment可重用模块
把页面中可能重复使用的部分做成Fragment,在一个activity中调用、提高了代码的可重用性。
(1)Fragment生命中的事件回调函数
 
(2)使用方法
①        layout设计界面中添加需要的Fragment、创建继承自Fragment的类
②        设计Fragment对应的xml界面
③        重载Fragment类中的函数onCreateView、改写return inflater.inflate(R.layout.bfragment, container, false); 即可。
  1. 事件监听
(1)      键盘事件setOnKeyListener
监听器中的函数的返回值为true将阻止事件传递给界面元素,界面元素就不会更新;程序中和事件有关的变量,它的信息可以类的声明中找到。
(2)      触摸事件setOnTouchListener
比较典型的函数
值的说明
函数的说明
getAction()
ACTION_DOWN、ACTION_UP、ACTION_MOVE等
获取动作
getX()、getY()
 
获取相对坐标,相对前一个位置
getRawX()、getRawY()
 
获取绝对坐标
getPressure()
 
触点的压力
getSize()
 
触点的尺寸
getHistorical…()
 
获取历史数据中的第几个数据
 
四、组件通信与广播
  1. 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=https://www.songbingjia.com/android/Uri.parse(editText.getText().toString());
Intent result=new Intent(null, data);
setResult(RESULT_OK, result);
finish();
③        父activity接收消息,需要重载函数onActivityResult:
函数的参数依次是标签、设置的结果标记、Uri数据;在函数中写需要的代码
  1. 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. 广播
(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=https://www.songbingjia.com/android/intent.getStringExtra("key");
Toast.makeText(context, value, Toast.LENGTH_SHORT).show();
 
五、后台服务
指的是没有界面且长时间在后台运行的应用功能,很典型的是Service服务组件,比如MP3播放器,界面关闭后音乐还在播放,这就需要用到Service,此外Service还可以用于进程间的通信。
  1. java和CC++易混淆的语法
boolean是java中的布尔值
java类中的变量声明马上就可以初始化,这点和CC++不同
null相当于CC++中的NULL
  1. Service的生命周期
 
  1. 本地服务
(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);
  1. 多线程
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();
  1. 绑定服务
最简单的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);
  1. 远程服务
这是除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();
}
  1. 自定义数据的传输
在远程服务中,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的清单
 
 

    推荐阅读