目录

一、构建Android开发环境... 4

SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。

1.用eclipse做Android的开发... 4

2.用手机做虚拟设备... 4

二、生命周期... 4

1.用于调度和控制的事件回调函数... 4

2.参考的调用顺序... 5

3.软件测试方法... 5

(1)日志点... 5

(2)应用程序提示... 6

(3)DevTools 6

三、用户界面UI 6

1.MVC模型... 6

2.界面控件... 6

(1)显示和编辑字符的控件... 6

(2)按钮控件... 6

(3)提供选择的控件... 6

(4)微调选框... 6

(5)垂直显示的列表控件... 7

(6)设置监听器... 7

3.界面布局... 7

(1)线性布局... 7

(2)相对布局... 8

(3)网格布局... 8

(4)表格布局... 8

(5)绝对布局... 8

(6)帧布局... 8

4.菜单(操作栏,由菜单组成)... 8

(1)菜单资源... 8

(2)快捷菜单... 8

5.Fragment可重用模块... 8

(1)Fragment生命中的事件回调函数... 9

(2)使用方法... 9

6.事件监听... 9

(1)键盘事件setOnKeyListener 9

(2)触摸事件setOnTouchListener 9

四、组件通信与广播... 10

1.Intent 10

2.Intent过滤器... 11

2.广播... 12

(1)发出信号... 12

(2)接收信号... 12

五、后台服务... 12

1.java和CC++易混淆的语法... 12

2.Service的生命周期... 13

3.本地服务... 13

(1)显式使用Service. 13

(2)隐式使用Service. 13

4.多线程... 14

5.绑定服务... 15

6.自定义数据的传输... 19

六、数据存储与访问... 22

1.SharedPreferences 22

七、位置和地图... 23

八、Widget组件开发... 23

九、Android NDK.. 23

十、特效... 23

1.tab标签页... 23

十一、附录... 23

1.参考网址... 23

2.eclipse快捷键... 23

3.adb命令... 24

4.avd命令... 24

正文

一、构建Android开发环境

1.用eclipse做Android的开发

(1) 下载JDK的可执行文件并执行

(2) 下载adt的zip压缩包

(3) 下载较新的SDK并解压SDK

(4) 下载eclipse并运行,选择help->install new software->add->archive->下载完毕的adt压缩文件

(5) 去掉“contact all update sites during install to find required software”选项,提高安装速度

(6) 重启eclipse后选择SDK解压后的位置

(7) Windows系统利用上vt技术的话,AVD的反应速度要快很多:启动BOIS启动vt,在sdk\extras\intel\Hardware_Accelerated_Execution_Manager下安装intel加速器,在此基础上建立一个intel驱动的AVD并启动

(8) 创建新项目

2.用手机做虚拟设备

下面用的是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()函数或者被系统终结的时候调用

2.参考的调用顺序

当用户离开当前页面又重新回到这个页面时,会调用onStart()、onStop()

使用eclipse开发Android 随笔 第1张使用eclipse开发Android 随笔 第2张

3.软件测试方法

(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模型

模型、视图、控制器,控制器加工用户输入的数据、交给处理核心“模型”,最终由“模型”来更新视图。

2.界面控件

用eclipse的layout设计界面制作静态的UI,用java控制动态的内容、先声明一个控件变量然后用findViewById引用xml中的资源进行初始化。具体的函数可以查阅android的API文档。

控件的属性在设计界面中有,也可以查阅android的手册。

(1)显示和编辑字符的控件

TextView

设计界面中双击控件,可以进入控件的xml文件

<TextView android:id=”@+id/TextView0”

android:layout_width=”wrap_content”

android:layout_height=”wrap_content”

android:text=”TextView0”/>

EditText常用函数

getText().toString()

获取文本内容

setText()

设置文本内容

selectAll()

选中全部

findFocus()

获取输入的焦点

(2)按钮控件

Button、ImageButton

(3)提供选择的控件

CheckBox用于多选、RadioGroup和RadioButton用于单选。

常用函数

isChecked()

控件是否被选中

(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);

(5)垂直显示的列表控件

ListView中如果内容很多,就会出现滚动条;如果没有内容,将不显示控件。

(6)设置监听器

监听器属于控件的方法,将使用内部类、如果出现错误可能是没有加上View.,在android_api.chm中也有具体的说明。比如OnClickListener、

① 控件独占一个监听器

比如列表控件中给每个子项设置监听器,listView.setOnItemClickListener(new AdapterView.OnIOnItemClickListener(){…});

② 多个控件共享一个监听器

方法是定义一个监听器,然后用v.getId()区分各个控件写上需要的代码,最后控件绑定这个监听器。如果一种类型的控件多次出现,尽量用这种方法设置监听器,消除一些不必要的冗余,。

3.界面布局

布局之间可以相互嵌套,按常用的程度分为:

(1)线性布局

LinearLayout可以选择水平也可以选择垂直,还可以像html中table的行列组合使用、这样就灵活多了。

(2)相对布局

RelativeLayout使用相对的位置以适应不同的屏幕尺寸,灵活而且比较稳定。

(3)网格布局

和表格布局类似,但是网格布局中的元素可以占用多个网格,而表格布局中的元素不能跨行跨列。

(4)表格布局

TableLayout默认控件独占一行,TableRow默认控件尽量放在一行。

(5)绝对布局

在layout设计界面中已经找不到,但是在手动创建布局的xml文件的时候有这样一种布局,部件的位置像坐标一样严格的受到数值的控制、不同的设备上效果不一定好。

(6)帧布局

一种类似坐标的自由布局FrameLayout

4.菜单(操作栏,由菜单组成)

可以在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。

5.Fragment可重用模块

把页面中可能重复使用的部分做成Fragment,在一个activity中调用、提高了代码的可重用性。

(1)Fragment生命中的事件回调函数

使用eclipse开发Android 随笔 第3张

(2)使用方法

① layout设计界面中添加需要的Fragment、创建继承自Fragment的类

② 设计Fragment对应的xml界面

③ 重载Fragment类中的函数onCreateView、改写return inflater.inflate(R.layout.bfragment, container, false);即可。

6.事件监听

(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数据;在函数中写需要的代码

2.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

指定的协议

(2)使用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);

2.广播

(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

2.Service的生命周期

使用eclipse开发Android 随笔 第4张

3.本地服务

(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);

4.多线程

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();

5.绑定服务

最简单的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);

2. 远程服务

这是除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();

}

6.自定义数据的传输

在远程服务中,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的内部数据获取出来

六、数据存储与访问

SharedPreferences用于存取应用临时产生的数据、文件用于存取应用的非结构化数据、资源用于存取应用的内置数据、数据库用于存取应用的结构化数据,数据库可以完成以上目标

1.SharedPreferences

简单的键值对读写,xml文件将保存在/data/data/包名/shared_prefs/下;如果面对的是复杂类型的数据或是要保存到SD卡上,这种方式还是有缺陷的

(1)声明SharedPreferenes的名字和模式:

static final String PREF_NAME="person";

static final int MODE=Context.MODE_WORLD_READABLE+Context.MODE_WORLD_WRITEABLE;

访问模式:

MODE_PRIVATE

私有

MODE_WORLD_READABLE

全局读

MODE_WORLD_WRITEABLE

全局写

(2)在onStart()中获取一个SharedPreferences,读取用户个性化的数据来做初始化(一般程序都会这么做):

SharedPreferences sp=getSharedPreferences(PREF_NAME, MODE);

editText1.setText(sp.getString("name", "Tom"));

(3)在onStop()中获取一个SharedPreferences,用来保存数据到xml

SharedPreferences sp=getSharedPreferences(PREF_NAME, MODE);

SharedPreferences.Editor editor=sp.edit();

editor.putString("name", editText1.getText().toString());

2.文件存储

打开文件准备写数据

FileOutputStream fos(String filename,Context.mode);

mode的选择是:

MODE_PRIVATE

私有

MODE_APPEND

追加

MODE_WORLD_READABLE

全局可读

MODE_WORLD_WRITEABLE

全局可写

写文件

String str=”Some data啊”;

fos.write(str.getBytes());

fos.flush();

fos.close();

打开文件准备读数据

FileInputStream fis=openFileInput(String filename);

读文件

byte[] readBytes=new byte[fis.available()];

while(fis.read(readBytes)!=-1);

String str=new String(readBytes);

3.外部存储

在SD卡T-Flash上存储的数据是没有访问权限的控制的,但是可以保存一些大文件而不占用内部存储器的空间,模拟器启动时会自动加载SD卡出现新的路径/mnt/sdcard/,文件会被存储在/storage/sdcard/下

在AndroidManifest.xml中设置加载卸载文件系统、向外部存储器读写数据的权限

<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

写数据

String tmpFileName = "SdcardFile-" + System.currentTimeMillis() + ".txt";

File dir = new File("/sdcard/");

if (dir.exists() && dir.canWrite()) {

fileName = dir.getAbsolutePath() + "/" + tmpFileName;

File newFile = new File(fileName);

try {

newFile.createNewFile();

if (newFile.exists() && newFile.canWrite()) {

FileOutputStream fos = new FileOutputStream(newFile);

// str是要写入的String类型数据

fos.write(randNum.getBytes());

fos.flush();

fos.close();

stateView.setText(tmpFileName + "已写入SD卡");

randNumView.setText("");

}

} catch (Exception e) {

Toast.makeText(MainActivity.this, e.toString(), Toast.LENGTH_LONG).show();

}

}

读数据

File dir = new File("/sdcard/");

if (dir.exists() && dir.canWrite()) {

File newFile = new File(fileName);

try {

newFile.createNewFile();

if (newFile.exists() && newFile.canRead()) {

FileInputStream fis = new FileInputStream(newFile);

byte[] readBytes = new byte[fis.available()];

while (fis.read(readBytes) != -1);

String str = new String(readBytes);

randNumView.setText("读取的对应内容是:\n" + str);

}

} catch (Exception e) {

e.printStackTrace();

}

}

4.资源文件

视频、音乐、图片等原始文件放置在项目的/res/raw/下、在应用打包编译的时候不允许修改;xml作数据的文件放置在/res/xml/下,在打包编译的时候会被转换为二进制文件、以提高访问的效率;在项目中可以直接新建得到

(1)读取原始文件

Resources res=MainActivity.this.getResources();

try{

//raw_file是对应的原始文件名、不含后缀

InputStream ips=res.openRawResource(R.raw.raw_file);

byte[] readBytes=new byte[ips.available()];

while(ips.read(readBytes)!=-1);

ips.close();

//str是读出的String类型变量

String str=new String(readBytes,"utf-8");

}catch(Exception e){

e.printStackTrace();

}

读取二级xml文件,比如

<people>

<person name=”李” age=”21” height=”1.81”/>

<person name=”王” age=”25” height=”1.76”/>

<person name=”张” age=”20” height=”1.69”/>

</people>

//people是对应目录下的xml文件名、不含后缀

XmlPullParser parser = MainActivity.this.getResources().getXml(R.xml.people);

String str = "";

try {

while (parser.next() != XmlPullParser.END_DOCUMENT) {

//用于接收键值对中键的信息

String tmp = parser.getName(), name = null, age = null, height = null;

if (tmp != null && tmp.equals("person")) {

int i, count = parser.getAttributeCount();

for (i = 0; i < count; ++i) {

//获取键值对的信息

String attrName = parser.getAttributeName(i);

String attrValue = parser.getAttributeValue(i);

if (attrName != null && attrName.equals("name"))

name = attrValue;

if (attrName != null && attrName.equals("age"))

age = attrValue;

if (attrName != null && attrName.equals("height"))

height = attrValue;

if(name!=null && age!=null && height!=null)

str += "姓名:" + name + ",年龄:" + age + ",身高:" + height + "\r\n";

}

}

}

displayView.setText(str);

} catch (Exception e) {

Log.e("ResourceFileDemo", e.getMessage(), e);

}

5. 数据库存储

数据保存在/data/data/包名/databases/下,默认是私有的;sqlite3在sdk/platform-tools/下,可以通过同目录的adb.exe连接模拟器的Linux系统做进一步的shell操作

(1)手工建库

可以通过adb的shell命令创建对应目录下的文件夹databases、再创建.db文件,但是在shell状态下不能输入中文等unicode字符;也可以通过eclipse的DDMS创建对应的文件夹、再上传.db文件

(2)代码建库

使用多个DBAdapter就可以实现多数据集多表、单数据集单表的操作

①DBAdapter

//包名

package edu.hrbeu.SQLiteDemo;

import android.content.ContentValues;

import android.content.Context;

import android.database.Cursor;

import android.database.sqlite.SQLiteDatabase;

import android.database.sqlite.SQLiteException;

import android.database.sqlite.SQLiteOpenHelper;

import android.database.sqlite.SQLiteDatabase.CursorFactory;

public class DBAdapter {

// 数据库的名称

private static final String DB_NAME = "people.db";

// 表的名称

private static final String DB_TABLE = "peopleinfo";

private static final int DB_VERSION = 1;

// 表中各属性的名称

public static final String KEY_ID = "_id";

public static final String KEY_NAME = "name";

public static final String KEY_AGE = "age";

public static final String KEY_HEIGHT = "height";

private SQLiteDatabase db;

private final Context context;

private DBOpenHelper dbOpenHelper;

public DBAdapter(Context _context) {

context = _context;

}

/** Close the database */

public void close() {

if (db != null) {

db.close();

db = null;

}

}

/** Open the database */

public void open() throws SQLiteException {

dbOpenHelper = new DBOpenHelper(context, DB_NAME, null, DB_VERSION);

try {

db = dbOpenHelper.getWritableDatabase();

} catch (SQLiteException ex) {

db = dbOpenHelper.getReadableDatabase();

}

}

// 添加新数据,People对数据进行了封装、返回-1表示失败否则成功

public long insert(People people) {

ContentValues newValues = new ContentValues();

// put可以接收不同类型的参数、显然用到了函数重载

newValues.put(KEY_NAME, people.Name);

newValues.put(KEY_AGE, people.Age);

newValues.put(KEY_HEIGHT, people.Height);

return db.insert(DB_TABLE, null, newValues);

}

// 查询所有的数据项

public People[] queryAllData() {

Cursor results = db.query(DB_TABLE, new String[] { KEY_ID, KEY_NAME, KEY_AGE, KEY_HEIGHT }, null, null, null,

null, null);

return ConvertToPeople(results);

}

// 查询指定的数据项,如果条件是ID返回值应该只是一个值、取下标为0的数据即可,换成其他条件就不见得是一个数据了

public People[] queryOneData(long id) {

Cursor results = db.query(DB_TABLE, new String[] { KEY_ID, KEY_NAME, KEY_AGE, KEY_HEIGHT }, KEY_ID + "=" + id,

null, null, null, null);

return ConvertToPeople(results);

}

// 将查询到的一个项转换为自定义的类

private People[] ConvertToPeople(Cursor cursor) {

int resultCounts = cursor.getCount();

if (resultCounts == 0 || !cursor.moveToFirst()) {

return null;

}

People[] peoples = new People[resultCounts];

for (int i = 0; i < resultCounts; i++) {

peoples[i] = new People();

peoples[i].ID = cursor.getInt(0);

peoples[i].Name = cursor.getString(cursor.getColumnIndex(KEY_NAME));

peoples[i].Age = cursor.getInt(cursor.getColumnIndex(KEY_AGE));

peoples[i].Height = cursor.getFloat(cursor.getColumnIndex(KEY_HEIGHT));

cursor.moveToNext();

}

return peoples;

}

// 删除所有数据

public long deleteAllData() {

return db.delete(DB_TABLE, null, null);

}

// 删除指定数据

public long deleteOneData(long id) {

return db.delete(DB_TABLE, KEY_ID + "=" + id, null);

}

// 对指定项进行更新

public long updateOneData(long id, People people) {

ContentValues updateValues = new ContentValues();

updateValues.put(KEY_NAME, people.Name);

updateValues.put(KEY_AGE, people.Age);

updateValues.put(KEY_HEIGHT, people.Height);

return db.update(DB_TABLE, updateValues, KEY_ID + "=" + id, null);

}

// 执行特定的SQL语句

public void DBAexecSQL(String sql) {

db.execSQL(sql);

}

/** 静态Helper类,用于建立、更新和打开数据库,初始化的时候会用到 */

private static class DBOpenHelper extends SQLiteOpenHelper {

public DBOpenHelper(Context context, String name, CursorFactory factory, int version) {

super(context, name, factory, version);

}

private static final String DB_CREATE = "create table " + DB_TABLE + " (" + KEY_ID

+ " integer primary key autoincrement, " + KEY_NAME + " text not null, " + KEY_AGE + " integer,"

+ KEY_HEIGHT + " float);";

@Override

public void onCreate(SQLiteDatabase _db) {

_db.execSQL(DB_CREATE);

}

@Override

public void onUpgrade(SQLiteDatabase _db, int _oldVersion, int _newVersion) {

_db.execSQL("DROP TABLE IF EXISTS " + DB_TABLE);

onCreate(_db);

}

}

}

②People

//包名

package edu.hrbeu.SQLiteDemo;

public class People {

//属性

public int ID = -1;

public String Name;

public int Age;

public float Height;

@Override

public String toString(){

String result = "";

result += "ID:" + this.ID + ",";

result += "姓名:" + this.Name + ",";

result += "年龄:" + this.Age + ", ";

result += "身高:" + this.Height + ",";

return result;

}

}

七、位置和地图

八、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安卓调试桥,用于连接Linux系统、管理android设备或模拟器;用命令行工具进入platform,下面的命令都需要在前面加上adb,才会有效

install .apk的完整路径

安装某个安卓文件

help

帮助命令

version

adb的版本信息

devices

正在运行的模拟器

shell 命令

执行shell命令

shell

进入shell模式

push 本地文件 目标路径

上传本地文件

pull 目标路径 [本地路径]

将设备上的文件下载下来,本地路径默认是adb的路径

4.avd命令

avd即安卓虚拟设备,进入tools目录下,可以用命令行创建和编译安卓程序;

android list targets

镜像文件清单

android list avds

avd的清单

5.模拟器设置中文

设置->语言和输入法;

语言,选择中文(中国);

键盘和输入法,选择谷歌拼音输入法;

默认,选择谷歌拼音输入法;

关闭硬件物理键盘

扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄