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,在sdk\extras\intel\Hardware_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()用于程序被销毁时恢复临时信息、比如程序遇到锁屏或者被系统中断,但是它们都不是生命周期的时间回调函数。

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=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=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的清单

猜你喜欢

转载自www.cnblogs.com/guomc/p/10188724.html