导图社区 Android应用程序开发笔记
Android应用程序开发笔记,详细的总结了开发环境配置,开发工具介绍,常用调试程序的方法,菜单,储存策略,多媒体操作,开发中的常见问题。
编辑于2022-06-23 21:27:13Android应用程序开发笔记(4.*版本)
 www.fkjava.org 讲师:李韩飞 Q:1783322568 overfly09@gmail.com www.overfly09.com 红色部分需要重点掌握! 本班课程使用的是Android 4.*版本的  应用程序层、应用程序框架层、系统运行库层、Linux内核层
1-开发环境配置
1-安装方式
无论什么方式安装最好都设置环境变量 安装好后就可以获取SDK 了
A-集成环境安装
1-android SDK获得
android 相关的下载 http://developer.android.com/sdk/index.html 步骤1:  步骤2:  下载文件的名称: 以前是:installer_r20.0.1-windows.exe 现在是:adt-bundle-windows-x86.zip
B-离线安装
1-eclipse安装
建议单独使用一个可以开发web应用(因为以后可以进行PC和移动端的开发)的eclipse来开发android程序 统一eclipse的设置 1,设置eclipse工作空间编码 -- utf-8 2, 设置字体
2-离线安装方式获取 ADT
ADT 是Eclipse 中一个android开发插件。 
3-安装ADT
1.eclipse ----help --- install new software--      选择yes 重新启动eclipse  eclipse 有没有 下面选择的项目,有表示安装成功  windows--prefeences -- android 
在线安装
 
离线安装

设置环境变量
因为以后要使用到sdk中的一些工具,所以需要配置sdk到环境变量中,配置步骤与JDK类似 例如:我的sdk 是放在 androidj1203目录中的android-sdk-2.2-4.1  配置platform-tools到path中  配置tools到path中 
2-创建android项目
     
3-运行android项目
1-创建模拟器
 选择需要启动的模拟器    
2-发布android项目
先启动模拟器,然后点击需要运行的项目,选择Run As -- Android Application 运行  
1-程序修改
RelativeLayoutxmlns: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:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:text="@string/hello_world" tools:context=".MainActivity"/> Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_marginRight="22dp" android:layout_marginTop="68dp" android:layout_toLeftOf="@+id/textView1" android:text="@string/btn"/> RelativeLayout> --------------------------------------- package org.fkjava.hello; import android.app.Activity; import android.os.Bundle; import android.util.Log; importandroid.view.Menu; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; publicclass MainActivity extends Activity { protectedstaticfinal String TAG = "MainActivity"; TextView tv = null; @Override publicvoid onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //加载指定的布局文件 setContentView(R.layout.activity_main); //获得布局文件上的文本组件 tv = (TextView)findViewById(R.id.textView1); //获得布局文件上的按钮组件 Button btn = (Button)findViewById(R.id.button1); //按钮组件事件注册(和swing一样) btn.setOnClickListener( new OnClickListener() { publicvoid onClick(View v) { //不推荐使用sysout //System.out.println("00000000000000"); //推荐使用Log类 Log.i(TAG, "---------onClick--------------"+v); //设置textview显示内容 tv.setText("大家好,欢迎来学习android!"); } }); } }
3-android工程结构

4-AndroidManifest.xml
AndroidManifest.xml 是一个应用程序的清单文件 在这个文件中可以配置,本应用程序的需要的 权限 , 风格,样式,第一个启动的activity类 ....  
2-开发工具介绍
1-Devices

2-Emulator control

3-内存监控

3-常用调试程序的方法
1,使用Eclipse开发平台调试; debug 2,结合Android SDK调试; Log 3,使用JUnit调试; Junit
debug

Log日志
结合Android SDK调试; Log Log.v(Verbose) 详细信息 Log.d(Debug) 调试信息 Log.i(Info) 通知信息 Log.w(Warn) 警告信息 Log.e(Error) 错误信息
Junit测试
 package test; import junit.framework.TestCase; import org.fkjava.hello.MainActivity; /** * 运行的时候选择 Android junit test * @authorhanfeili * */ publicclass TestMainActivity extends TestCase { MainActivity ma = null; /** * 测试的时候初始化操作 */ @Override protectedvoid setUp() throws Exception { super.setUp(); ma = new MainActivity(); } publicvoid testShow(){ assertEquals(ma.show(), false); } /** * 测试完毕释放资源 */ @Override protectedvoid tearDown() throws Exception { super.tearDown(); ma = null; } }
Monkey自动测试
Monkey Monkey是一个命令行工具,可以运行在模拟器里或实际设备中。它向系统发送伪随机的用户事件流,实现对正在开发的应用程序进行压力测试。 Monkey大致分为4大类: · 基本配置选项,如设置尝试的事件数量。 · 运行约束选项,如设置只对单独的一个包进行测试。 · 事件类型和频率。 · 调试选项。 例如: adb shell monkey -p com.overfly09.hello -v 500 F:\android\android-sdk-windows\platform-tools>adb shell# monkey -v -p org.facejava.contact 500
Monkey参数说明

4-Layout
布局就是控制一个界面的组件排列 摆放的位置 可以通过下面的命令进一步查看详细的布局结构图 D:\java-dev\Android_SDK_HOME\tools\hierarchyviewer.bat
1-FrameLayout帧布局
是所有布局的基础布局 
布局
FrameLayoutxmlns: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:id="@+id/a" android:layout_width="350px" android:layout_height="350px" android:layout_gravity="center" android:background="#ff0000" android:text="A"/> TextView android:id="@+id/b" android:layout_width="330px" android:layout_height="330px" android:layout_gravity="center" android:background="#33ff00" android:text="B"/> TextView android:id="@+id/c" android:layout_width="300px" android:layout_height="300px" android:layout_gravity="center" android:background="#0000ff" android:text="C"/> TextView android:id="@+id/d" android:layout_width="270px" android:layout_height="270px" android:layout_gravity="center" android:background="#ff33cc" android:text="D"/> Buttonandroid:id="@+id/start" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="开始" android:layout_gravity="bottom|right" android:onClick="onStart"/> FrameLayout>
代码
package org.fkjava.framelayout; import java.util.Random; import android.app.Activity; import android.graphics.Color; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.view.View; import android.widget.Button; import android.widget.TextView; public class MainActivity extends Activity { int[] ids = {R.id.a,R.id.b,R.id.c,R.id.d}; int[] colors = {Color.BLACK,Color.GREEN,Color.RED,Color.CYAN,Color.YELLOW,Color.GRAY}; TextView[] tvs =new TextView[ids.length]; Button start =null; /** * Handler一般用于子线程和主线程通信 * 子线程通知主线程更新 UI组件 */ Handler handler = new Handler(){ Random random = new Random(); /** * 通常进行组件更新 * 子线程调用 主线程执行 * sendEmptyMessage 方法一执行将执行handleMessage 进行UI组件更新 * */ @Override public void handleMessage(Message msg) { //判断发送的消息标识 进行操作 if(msg.what==0){ //循环更新组件背景颜色 for(TextView tv : tvs){ tv.setBackgroundColor(colors[random.nextInt(5)]); } /** * 更新完毕再发送一个延迟消息 * 参数1:消息标识 * 参数2:延迟时间(1000 = 1秒) */ handler.sendEmptyMessageDelayed(0, 500); }else{ /** * 删除消息 */ handler.removeMessages(0); } } }; /** * 程序以启动先执行onCreate 进行初始化操作(布局的加载) */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //加载布局文件,并创建布局文件中定义的对象 setContentView(R.layout.activity_main); //通过组件的id标识符获得组件对象 /*TextView a = (TextView) findViewById(R.id.a); TextView b = (TextView) findViewById(R.id.b); TextView c = (TextView) findViewById(R.id.c); TextView d = (TextView) findViewById(R.id.d); //动态设置组件的背景颜色 d.setBackgroundColor(Color.GREEN);*/ start = (Button)findViewById(R.id.start); for(int i=0;i tvs[i] = (TextView)findViewById(ids[i]); } } int flag = 0; /** * 如果在xml创建Button组件的时候指定了onClick属性,那么在代码中必须有一个对应的方法,来处理点击事件 * 并且这个方法一定要有一个 View参数 * @param view 表示 事件源 */ public void onStart(View view){ Button btn = (Button)view; if(flag == 0){ //handler发送一个空消息通知组件更新 handler.sendEmptyMessage(0); //设置事件源的Text内容 btn.setText("停止"); flag++; }else{ handler.sendEmptyMessage(1); btn.setText("开始"); flag--; } } }
2-LinearLayout 线性布局
包含垂直布局和水平布局,可以放置多个控件,但是一行(列)只能放置一个组件。所有组件都是按由上到下的排队排成的 设置布局方式 android:orientation="vertical" vertical 垂直布局 horizontal 水平布局 android:layout_width="fill_parent" android:layout_height="fill_parent">
嵌套布局
LinearLayoutxmlns: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" android:orientation="vertical"> LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal"> TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="用户名:" tools:context=".MainActivity"/> EditText android:id="@+id/name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:hint="请输入用户名"/> LinearLayout> LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal"> TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="密 码:" tools:context=".MainActivity"/> EditText android:id="@+id/password" android:layout_width="wrap_content" android:layout_height="wrap_content" android:hint="请输入登录密码"/> LinearLayout> LinearLayout>
3-AbsoluteLayout绝对布局(不推荐使用)
通过 X Y 坐标指定位置,当屏幕大小变化,可能显示就会有非常大的差异!
4-RelativeLayout相对布局
组件与组件之间有一个依赖关系 如果一个组件变化 可能 会影响整个布局 android:layout_above="@id/tv" 将组件的底部至于指定组件的上面 android:layout_below 将组件的顶部至于指定组件的下面 android:layout_toLeftOf 将组件的右边缘与指定组件左边缘对齐 android:layout_toRightOf 将组件的左边缘与指定组件右边缘对齐 android:layout_alignBaseline 将组件的baseline与指定组件baseline对齐android:layout_alignBottom 将组件的底部边缘与指定组件底部边缘对齐 android:layout_alignLeft 将组件的左边缘与指定组件右边缘对齐 android:layout_alignRight 将组件的右边缘与指定组件左边缘对齐 android:layout_alignTop 将组件的顶部边缘与指定组件顶部边缘对齐 android:alignParentBottom 设置为true 表示将组件的底部与父组件的底部对齐android:layout_alignParentLeft 设置为true 表示将组件的左边与父组件的左边对齐android:layout_alignParentRight 设置为true 表示将组件的右边与父组件的右边对齐android:layout_alignParentTop 设置为true 表示将组件的顶部与父组件的顶部对齐android:layout_conterHorizontal 设置为true 表示将组件至于水平方向中间android:layout_conterInParent 设置为true 表示将组件至于父组件水平方向和垂直方向中间android:layout_conterVertical 设置为true 表示将组件至于垂直方向中间------------------------------------------------------------------------------------------------------ android:id="@+id/label" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="允许子元素指定他们相对于其它元素或父元素的位置(通过ID指定)。"/>
5-TableLayout表格布局
 xmlversion="1.0"encoding="utf-8"?> TableLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:stretchColumns="1"> TableRow> TextViewandroid:text="学号"android:padding="3dip"android:background="#aa0000"/> TextViewandroid:text="姓名"android:padding="3dip"android:gravity="center"/> TextViewandroid:text="年龄"android:padding="3dip"/> TextViewandroid:text="性别"android:padding="3dip"android:gravity="center"/> TableRow> Viewandroid:layout_height="1dip"android:background="#FF909090"/> TableRow> EditTextandroid:text="28"/> EditTextandroid:text="李韩飞"/> EditTextandroid:text="30"/> EditTextandroid:text="男"/> TableRow> Viewandroid:layout_height="1dip"android:background="#FF909090"/> TableRow> EditTextandroid:text="29"/> EditTextandroid:text="李s"/> EditTextandroid:text="31"/> EditTextandroid:text="男"/> TableRow> TableLayout>
6-GridLayout
andorid 4.1新增的网格布局  xmlversion="1.0"encoding="utf-8"?> GridLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:rowCount="6" android:columnCount="4" android:id="@+id/root" > TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_columnSpan="4" android:textSize="50sp" android:layout_marginLeft="4px" android:layout_marginRight="4px" android:padding="5px" android:layout_gravity="right" android:background="#eee" android:textColor="#000" android:text="0"/> Button android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_columnSpan="4" android:text="清除"/> GridLayout> ------------------------------------------ import android.os.Bundle; import android.app.Activity; import android.view.Gravity; import android.widget.Button; import android.widget.GridLayout; publicclass GridLayoutTest extends Activity { GridLayout gridLayout; // 定义16个按钮的文本 String[] chars = new String[] { "7", "8", "9", "÷", "4", "5", "6", "×", "1", "2", "3", "-", ".", "0", "=", "+" }; @Override publicvoid onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); gridLayout = (GridLayout) findViewById(R.id.root); for (int i = 0; i chars.length; i++) { Button bn = new Button(this); bn.setText(chars[i]); // 设置该按钮的字体大小 bn.setTextSize(40); // 指定该组件所在的行 GridLayout.Spec rowSpec = GridLayout.spec(i / 4 + 2); // 指定该组件所在列 GridLayout.Spec columnSpec = GridLayout.spec(i % 4); GridLayout.LayoutParams params = new GridLayout.LayoutParams( rowSpec, columnSpec); // 指定该组件占满父容器 params.setGravity(Gravity.FILL); gridLayout.addView(bn, params); } } }
7-ViewStub延迟加载布局资源
  LinearLayoutxmlns: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" android:orientation="vertical"> TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="ViewStub测试"/> ViewStubandroid:id="@+id/myviewstub" android:inflatedId="@+id/other_id" android:layout="@layout/other" android:layout_width="wrap_content" android:layout_height="wrap_content"/> Button android:id="@+id/btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="执行测试"/> LinearLayout> -------------------------------------- LinearLayout 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" android:orientation="vertical"> EditText android:id="@+id/username" android:layout_width="wrap_content" android:layout_height="wrap_content" android:hint="请输入用户名!"/> Button android:id="@+id/login" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="登录"/> LinearLayout> -------------------------- package org.fkjava.viewstub; import android.app.Activity; import android.os.Bundle; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewStub; import android.widget.Button; import android.widget.EditText; publicclass MainActivity extends Activity { @Override publicvoid onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button btn = (Button)findViewById(R.id.btn); btn.setOnClickListener(new OnClickListener() { EditText username =null; publicvoid onClick(View v) { //获得布局中定义的ViewStub对象 ViewStub vs = (ViewStub)findViewById(R.id.myviewstub); //infalte()方法表示填充或者说加载(实例化)ViewStub中通过android:layout="@layout/other" 引入的对应的布局资源 View other = vs.inflate(); //和上面的代码一样的效果 //View other = ((ViewStub)findViewById(R.id.myviewstub)).inflate(); username =(EditText)other.findViewById(R.id.username); Button login = (Button)other.findViewById(R.id.login); login.setOnClickListener(new OnClickListener() { publicvoid onClick(View v) { Log.i("Other-----", username.getText().toString()); } }); } }); } }
8-代码方式创建对象
package org.fkjava.codeview; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.Button; import android.widget.LinearLayout; import android.widget.TextView; /** * 代码方式创建对象 * @author hanfeili * */ public class CodeView extends Activity { // 当第一次创建该Activity时回调该方法 @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 创建一个线性布局管理器 LinearLayout layout = new LinearLayout(this); // 设置该Activity显示Layout super.setContentView(layout); //设置布局为垂直布局 layout.setOrientation(LinearLayout.VERTICAL); // 创建一个TextView final TextView show = new TextView(this); // 创建一个按钮 Button btn = new Button(this); btn.setText("测试"); btn.setLayoutParams(new ViewGroup.LayoutParams( ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)); // 向Layout容器中添加TextView layout.addView(show); // 向Layout容器中添加按钮 layout.addView(btn); // 为按钮绑定一个事件监听器 btn.setOnClickListener(new OnClickListener() { public void onClick(View v) { show.setText("欢迎进入Android的世界" + new java.util.Date().toLocaleString()); } }); } }
5-UI

1-实例1

布局界面
LinearLayoutxmlns: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" android:background="@drawable/bg_login" android:orientation="vertical"> TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:text="@string/title_activity_main" android:textColor="#ff0000" android:textSize="50dp"/> LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" android:paddingLeft="20dp"> TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/nameLabel"/> EditText android:id="@+id/name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:drawableLeft="@drawable/user" android:ems="10" android:hint="@string/namehint"/> LinearLayout> LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" android:paddingLeft="20dp"> TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/passwordLabel"/> EditText android:id="@+id/password" android:layout_width="wrap_content" android:layout_height="wrap_content" android:drawableLeft="@drawable/busy" android:ems="8" android:hint="@string/passwordhint" android:inputType="numberPassword" android:password="true"/> CheckBox android:id="@+id/show" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/showLabel"/> LinearLayout> RadioGroup android:id="@+id/sexGroup" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" android:paddingLeft="20dp"> TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/sexLabel"/> RadioButton android:id="@+id/radioButton1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:checked="true" android:text="@string/manLabel"/> RadioButton android:id="@+id/radioButton2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/womanLabel"/> RadioGroup> TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/hobbyLabel" android:paddingLeft="20dp"/> LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" android:paddingLeft="20dp"> CheckBox android:id="@+id/hobby1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/hobby1"/> CheckBox android:id="@+id/hobby2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/hobby2"/> CheckBox android:id="@+id/hobby3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/hobby3"/> LinearLayout> TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/infoLabel" android:paddingLeft="20dp"/> EditText android:id="@+id/info" android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="textMultiLine" android:hint="@string/infohint"/> LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" android:paddingLeft="20dp" android:layout_gravity="center_horizontal"> Button android:id="@+id/submit" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/submitLabel"/> Button android:id="@+id/reset" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/resetLabel"/> LinearLayout> LinearLayout>
代码
package org.fkjava.ui; import android.app.Activity; import android.os.Bundle; import android.text.method.HideReturnsTransformationMethod; import android.text.method.PasswordTransformationMethod; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.CheckBox; import android.widget.CompoundButton; import android.widget.EditText; import android.widget.RadioButton; import android.widget.RadioGroup; import android.widget.RadioGroup.OnCheckedChangeListener; import android.widget.Toast; publicclass MainActivity extends Activity implements OnClickListener{ EditText name,password,info; CheckBox show,hobby1,hobby2,hobby3; RadioGroup sexGroup; @Override publicvoid onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //用户名输入框 name = (EditText) findViewById(R.id.name); //密码输入框 password = (EditText) findViewById(R.id.password); //自我介绍输入框 info = (EditText) findViewById(R.id.info); //密码回显复选框 show = (CheckBox) findViewById(R.id.show); //绑定密码回显复选框进行密码隐藏和回显处理 show.setOnCheckedChangeListener(new android.widget.CompoundButton.OnCheckedChangeListener() { /** * 当复选框状态关闭的时候触发 * 参数1:事件源 * 参数2:状态值(选择返回true) */ publicvoid onCheckedChanged(CompoundButton buttonView, boolean isChecked) { if(isChecked){ //设置将密码输入框中数据回显成明文 password.setTransformationMethod(new HideReturnsTransformationMethod()); }else{ //设置将密码输入框中明文数据显示成密码状态 password.setTransformationMethod(new PasswordTransformationMethod()); } } }); //性别单选框 sexGroup = (RadioGroup) findViewById(R.id.sexGroup); //单选框组的状态事件处理 sexGroup.setOnCheckedChangeListener(new OnCheckedChangeListener() { /** * 一个单选框组中的某个单项选择状态改变将触发 * 参数1:单选框组 * 参数2:单选框组中被选中的单项选择的id值 */ publicvoid onCheckedChanged(RadioGroup group, int checkedId) { //在单选框组中根据id获取组中的一个单项选择对象 RadioButton rb = (RadioButton)group.findViewById(checkedId); Toast.makeText(MainActivity.this, "您选择的性别是:"+rb.getText().toString(), Toast.LENGTH_SHORT).show(); } }); //爱好复选框 hobby1 = (CheckBox) findViewById(R.id.hobby1); hobby2 = (CheckBox) findViewById(R.id.hobby2); hobby3 = (CheckBox) findViewById(R.id.hobby3); //组件绑定单击事件 findViewById(R.id.submit).setOnClickListener(this); Button reset = (Button) findViewById(R.id.reset); reset.setOnClickListener(this); } publicvoid onClick(View v) { if(v.getId() == R.id.submit){ String n = name.getText().toString(); String pass = password.getText().toString(); String in = info.getText().toString(); int rbid = sexGroup.getCheckedRadioButtonId(); RadioButton rb = (RadioButton)sexGroup.findViewById(rbid); String sex = rb.getText().toString(); String ho = hobby1.getText().toString(); //显示一个会自动隐藏的提示框 /** * 参数1:上下文 * 参数2:需要显示的数据 * 参数3:显示的时间长度 * show()方法一定要调用,否则不显示 */ Toast.makeText(this, n+"-"+pass+"-"+in+"-"+rbid+"-"+sex+"-"+ho, Toast.LENGTH_LONG).show(); }elseif(v.getId()== R.id.reset){ name.setText(""); password.setText(""); info.setText(""); show.setChecked(false); } } }
2-ProgressBar
 LinearLayoutxmlns: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" android:orientation="vertical"> TextView android:id="@+id/tv" android:layout_width="wrap_content" android:layout_height="wrap_content"/> ProgressBar android:id="@+id/myprogressbar" android:layout_width="match_parent" android:layout_height="wrap_content"/> ProgressBar android:id="@+id/myprogressbar2" style="?android:attr/progressBarStyleHorizontal" android:layout_width="match_parent" android:layout_height="wrap_content"/> Buttonandroid:id="@+id/start" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="下载"/> LinearLayout> ----------------------------------------- package org.fkjava.progressbar; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.ProgressBar; import android.widget.TextView; /** * 进度条实例 * @authorhanfeili * */ publicclass MainActivity extends Activity implements OnClickListener { Button start; TextView tv; ProgressBar bar1, bar2; @Override publicvoid onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv = (TextView) findViewById(R.id.tv); start = (Button) findViewById(R.id.start); start.setOnClickListener(this); bar1 = (ProgressBar) findViewById(R.id.myprogressbar); bar2 = (ProgressBar) findViewById(R.id.myprogressbar2); bar2.setMax(100);//设置进度条 最大值 //bar2.setProgress(40);//设置进度条当前值 } Handlerhandler = new Handler(){ /** * 消息处理方法,一般在这个方法中进行UI组件的更新 */ publicvoid handleMessage(Message msg) { if(msg.what bar2.setProgress(msg.what); bar2.setSecondaryProgress(msg.what+10);//设置次级进度条(看网络电影的时候那个缓冲条状态) handler.sendEmptyMessageDelayed(++msg.what, 200); if(msg.what == 50){ bar1.setVisibility(View.GONE); } tv.setText(msg.what+"%"); }else{ handler.removeMessages(msg.what); bar2.setVisibility(View.GONE); bar2.setProgress(0); tv.setText("下载完毕"); } }; }; publicvoid onClick(View v) { bar1.setVisibility(View.VISIBLE); bar2.setVisibility(View.VISIBLE); //发送一个空消息 //handler.sendEmptyMessage(1); /*通常一般不建议自己创建Message Message msg2 = new Message(); */ Message msg = Message.obtain(); msg.what = 1; handler.sendMessage(msg); } }
SeekBar
LinearLayoutxmlns: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" android:orientation="vertical"> TextView android:id="@+id/tv" android:layout_width="wrap_content" android:layout_height="wrap_content"/> SeekBar android:id="@+id/seekbar" android:layout_width="match_parent" android:layout_height="wrap_content"/> LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal"> Button android:id="@+id/start" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="播放"/> Button android:id="@+id/stop" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="停止"/> LinearLayout> LinearLayout> ------------------------------------- package org.fkjava.seekbar; import android.app.Activity; import android.media.MediaPlayer; import android.os.Bundle; import android.os.Handler; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.SeekBar; import android.widget.SeekBar.OnSeekBarChangeListener; import android.widget.TextView; public class MainActivity extends Activity implements OnClickListener { Button start, stop; SeekBar seekbar; TextView tv; MediaPlayer player = null; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv = (TextView) findViewById(R.id.tv); start = (Button) findViewById(R.id.start); stop = (Button) findViewById(R.id.stop); start.setOnClickListener(this); stop.setOnClickListener(this); seekbar = (SeekBar) findViewById(R.id.seekbar); //创建一个MediaPlayer 实现音频播放 //参数1:上下文,参数2:需要播放的音频资源(对应 res-->raw目录) player = MediaPlayer.create(this, R.raw.yydd); //获得音频文件播放的总长度 int length = player.getDuration(); seekbar.setMax(length);//设置给拖动进度条的最大长度 //设置拖动进度条事件监听器 seekbar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() { /** * 开始拖动的时候执行 * @param seekBar */ public void onStartTrackingTouch(SeekBar seekBar) {} /** * 进度改变的时候执行 * @param seekBar * @param progress * @param fromUser */ public void onProgressChanged(SeekBar seekBar, int progress,boolean fromUser) { player.seekTo(progress); tv.setText(progress+"/"+player.getDuration()); } /** * 拖动结束的时候执行 * @param seekBar */ public void onStopTrackingTouch(SeekBar seekBar) {} }); } Handler handler = new Handler() { public void handleMessage(android.os.Message msg) { if(player.isPlaying()){ seekbar.setProgress(player.getCurrentPosition()); handler.sendEmptyMessage(0); tv.setText(seekbar.getProgress()+"/"+player.getDuration()); } }; }; public void onClick(View v) { if (v.getId() == R.id.start) { try { player.prepare(); } catch (Exception e) { e.printStackTrace(); } player.start(); handler.sendEmptyMessage(0); } else if (v.getId() == R.id.stop) { player.stop(); player.release(); } } }
3-Toast
RelativeLayoutxmlns: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:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:text="@string/hello_world" tools:context=".MainActivity"/> Button android:id="@+id/start" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_marginRight="16dp" android:layout_marginTop="68dp" android:layout_toLeftOf="@+id/textView1" android:text="Toast测试"/> RelativeLayout> ---------------------------------------- RelativeLayoutxmlns: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:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:text="自定义Toast"/> ImageView android:id="@+id/imageView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentRight="true" android:layout_alignParentTop="true" android:layout_marginTop="38dp" android:src="@drawable/cls"/> RelativeLayout> --------------------------------- package org.fkjava.toast; import android.app.Activity; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.widget.Toast; publicclass MainActivity extends Activity { @Override publicvoid onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findViewById(R.id.start).setOnClickListener(new OnClickListener() { publicvoid onClick(View v) { Toast.makeText(MainActivity.this, "开始测试", Toast.LENGTH_LONG).show(); //创建一个Toast对象 Toast toast = new Toast(MainActivity.this); //填充的布局对象 View view = LayoutInflater.from(MainActivity.this).inflate(R.layout.other, null); //将一个自定义的布局对象设置到Toast中 toast.setView(view); //设置Toast显示持续时间 toast.setDuration(Toast.LENGTH_LONG); //显示Toast toast.show(); } }); } }
4-Dialog
Dialog API file:///E:/Android/android-sdk-2.2-4.1/docs/reference/android/app/Dialog.html  RelativeLayoutxmlns: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:text="@string/hello_world" tools:context=".MainActivity"/> Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:text="dialog1"/> Button android:id="@+id/button2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_below="@+id/button1" android:layout_marginTop="24dp" android:text="dialog2"/> RelativeLayout> --------------------------------------- login.xml LinearLayoutxmlns: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" android:background="#0066cc" android:orientation="vertical"> TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" android:text="疯狂登录" android:textColor="#ff0000" android:textSize="20dip"/> EditText android:id="@+id/username" android:layout_width="match_parent" android:layout_height="wrap_content" android:drawableLeft="@drawable/bq2" android:hint="请输入用户名" android:singleLine="true"/> LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> EditText android:id="@+id/pass" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="2" android:hint="请输入密码" android:inputType="number" android:password="true" android:singleLine="true"/> CheckBox android:id="@+id/isshow" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:text="回显"/> LinearLayout> LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center_horizontal" android:orientation="horizontal"> Button android:id="@+id/login" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="登录"/> Button android:id="@+id/reset" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="取消"/> LinearLayout> LinearLayout> ------------------------------------- package org.fkjava.ui2; import android.app.Activity; import android.app.AlertDialog; importandroid.app.Dialog; import android.content.DialogInterface; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; publicclass MainActivity extends Activity implements OnClickListener { Button btn1, btn2 = null; @Override publicvoid onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btn1 = (Button) findViewById(R.id.button1); btn2 = (Button) findViewById(R.id.button2); btn1.setOnClickListener(this); btn2.setOnClickListener(this); } publicvoid onClick(View v) { if (v == btn1) { //创建对话框 AlertDialog.Builder dialog= new AlertDialog.Builder(this); dialog.setIcon(R.drawable.bq2);//设置对话框的图标 dialog.setTitle("疯狂提示");//设置标题 dialog.setMessage(R.string.dialogmsg);//设置显示内容 //设置按钮 确定 dialog.setPositiveButton("ok", new DialogInterface.OnClickListener() { publicvoid onClick(DialogInterface dialog, int which) { dialog.dismiss();//隐藏对话框 } }); //设置按钮 取消 dialog.setNegativeButton("喔", new DialogInterface.OnClickListener() { publicvoid onClick(DialogInterface dialog, int which) { Toast.makeText(MainActivity.this, "美女少了", Toast.LENGTH_LONG).show(); } }); dialog.setNeutralButton("no", null); dialog.show(); }elseif(v == btn2){ Dialog dialog = newDialog(this); dialog.setTitle("登录对话框"); //自己填充 布局 View view = LayoutInflater.from(this).inflate(R.layout.login, null); dialog.setContentView(view); //与上面的自己填充 布局是一样的意思 //dialog.setContentView(R.layout.login); //因为我们R.layout.login对应的布局已经和Dialog关联在一起了,使用可以通过dialog获得布局上的组件,并进行操作 final EditText loginName =(EditText) dialog.findViewById(R.id.username); Button login =(Button) dialog.findViewById(R.id.login); login.setOnClickListener(new OnClickListener() { publicvoid onClick(View v) { Toast.makeText(MainActivity.this, "欢迎["+loginName.getText().toString()+"]登录", Toast.LENGTH_LONG).show(); } }); dialog.show(); } } }
activity 定义成对话框效果
在AndroidManifest.xml 文件中定义一个Activity为对话框模式 android:theme="@android:style/Theme.Dialog" android:label="Dialog">
代码
package org.fkjava.dialog; import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; import android.content.DialogInterface; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; /** * 对话框实例 * @authorhanfeili * */ publicclass MainActivity extends Activity implements android.view.View.OnClickListener { protectedstaticfinal String TAG = "MainActivity"; Button btn1; @Override publicvoid onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btn1 = (Button) findViewById(R.id.button1); btn1.setOnClickListener(this); } publicvoid onClick(View v) { //创建一个对话框对象 AlertDialog.Builder dialog = new AlertDialog.Builder(this); //设置对话框的标题 dialog.setTitle("温馨提示"); //设置对话框的信息 dialog.setMessage("天气凉大家注意身体健康!"); //设置对话框的确认按钮 /** * 参数1:按钮上显示的文字 * 参数2:按钮点击处理事件(注意引入的包是android.content.DialogInterface) */ dialog.setPositiveButton("好", new android.content.DialogInterface.OnClickListener() { publicvoid onClick(DialogInterface dialog, int which) { Log.i(TAG, "-----------好-----------"); } }); dialog.setNegativeButton("不好", new android.content.DialogInterface.OnClickListener() { publicvoid onClick(DialogInterface dialog, int which) { Log.i(TAG, "-----------不好-----------"); } }); //让对话框显示出来 dialog.show(); } publicvoid myOnClick(View v){ //创建一个 自定义 对话框对象 Dialog dialog = new Dialog(this); //设置对话框的标题 dialog.setTitle("注册"); //方式1:设置对话框绑定的布局文件(布局文件中实现自定义对话框的内容) //dialog.setContentView(R.layout.dialog); //方式2: 通过自己创建一个自定义对话框布局的对象,进行自定义对话框填充 //inflate() 参数1:需要填充的布局资源id(就是一个普通的布局资源) //inflate() 参数2:根资源,没有就给一个null View dialogLayout = LayoutInflater.from(this).inflate(R.layout.dialog, null); //将自己创建的资源对象关联到dialog中 dialog.setContentView(dialogLayout); //获得对话框中显示的资源数据,通过对话框来根据id获取 final EditText n = (EditText) dialog.findViewById(R.id.name); final EditText p = (EditText) dialog.findViewById(R.id.password); Button submit = (Button)dialog.findViewById(R.id.submit); submit.setOnClickListener(new android.view.View.OnClickListener() { publicvoid onClick(View v) { //getApplicationContext() 表示获得一个全局的上下文(如果当前上下文获取不了就可以使用) Toast.makeText(getApplicationContext(),"您的登录名称是:"+n.getText().toString()+"-密码是:"+p.getText().toString() ,Toast.LENGTH_LONG).show(); } }); //显示对话框 dialog.show(); } } -------------------------------------------- RelativeLayoutxmlns: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:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:text="@string/hello_world" tools:context=".MainActivity"/> Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentLeft="true" android:layout_marginBottom="60dp" android:layout_marginLeft="22dp" android:text="普通对话框实例"/> Button android:id="@+id/button2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBottom="@+id/button1" android:layout_marginLeft="14dp" android:layout_toRightOf="@+id/textView1" android:text="自定义对话框实例" android:onClick="myOnClick"/> RelativeLayout> -------------------------------------------- LinearLayoutxmlns: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" android:background="#ccffff" android:orientation="vertical"> ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/bq1"/> LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" android:paddingLeft="20dp"> TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="用户名"/> EditText android:id="@+id/name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:ems="10" android:hint="请输入用户名"/> LinearLayout> LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" android:paddingLeft="20dp"> TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="密码"/> EditText android:id="@+id/password" android:layout_width="wrap_content" android:layout_height="wrap_content" android:ems="10" android:hint="请输入密码" android:inputType="numberPassword" android:password="true"/> LinearLayout> LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:orientation="horizontal" android:paddingLeft="20dp"> Button android:id="@+id/submit" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="登录"/> Button android:id="@+id/reset" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="重置"/> LinearLayout> LinearLayout>
5-下拉列表
效果图   适配器类型分三种, BaseAdapter 基础适配器 ArrayAdapter 只能展示一行字 SimpleAdapter 最好的扩充性 SimpleCursorAdapter 对数据库的简单结合,可以方便将数据库的内容以列表的形式展示。
常规使用方式代码
package org.fkjava.sprinner; import java.util.ArrayList; import java.util.List; import android.annotation.SuppressLint; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.widget.AdapterView; import android.widget.AdapterView.OnItemSelectedListener; import android.widget.ArrayAdapter; import android.widget.Spinner; import android.widget.TextView; //执行下面的代码将在最新的api中运行 @SuppressLint("NewApi") public class MainActivity extends Activity { Spinner spinner; TextView show; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); show = (TextView) findViewById(R.id.textView1); spinner = (Spinner) findViewById(R.id.spinner1); /* * 创建一个数据适配器(给下拉列表填充数据的对象) * 参数1:上下文 * 参数2:下拉列表显示的风格(就是一个布局中带一个显示数据的资源,也可以自定义) * 系统提供的一些下拉列表样式(android.R表示系统提供资源) * android.R.layout.simple_spinner_dropdown_item 显示一个基本的数据 * android.R.layout.simple_list_item_checked 显示一个数据+一个checked效果 * android.R.layout.simple_list_item_multiple_choice 显示一个数据+一个checked效果2 */ ArrayAdapter adapter = new ArrayAdapter(this,android.R.layout.simple_spinner_dropdown_item); //方式1:填充下拉列表需要显示的数据(字符串数组) //adapter.addAll(new String[]{"小学","中学","中专","大专","本科"}); List xl = new ArrayList(); xl.add("小学"); xl.add("中学"); xl.add("中专"); xl.add("大专"); xl.add("本科"); //方式2:填充下拉列表需要显示的数据(List集合) adapter.addAll(xl); //下拉列表绑定adapter spinner.setAdapter(adapter); //绑定下拉列表事件(下拉列表项目被选择了触发事件) spinner.setOnItemSelectedListener(new OnItemSelectedListener(){ /** * 下拉列表项目被选择了触发执行 * 参数1:适配器adapter(包含了所有数据) * 参数2:事件源 -被选择下拉列表项目 * 参数3:被选择的项目的下标(从0开始) * 参数4:一个id标识目前与参数3一致 */ public void onItemSelected(AdapterView parent, View view, int position, long id) { //根据选择的项目的下标获取对应的数据 Object o = parent.getItemAtPosition(position); show.setText("下标-"+position+"-id-"+id+"-数据-"+o.toString()); } /** * 没有被选择的时候执行(目前没用) */ public void onNothingSelected(AdapterView parent) {} }); } } ------------------------------------- RelativeLayoutxmlns: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:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:text="@string/hello_world" tools:context=".MainActivity"/> Spinner android:id="@+id/spinner1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_marginTop="75dp"/> RelativeLayout>
自定义下拉列表项目代码
代码
package org.fkjava.spinner; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.widget.AdapterView; import android.widget.AdapterView.OnItemSelectedListener; import android.widget.ArrayAdapter; import android.widget.Spinner; import android.widget.TextView; publicclass MainActivity extends Activity { Spinner spinner; TextView show; @Override publicvoid onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); show = (TextView) findViewById(R.id.textView1); spinner = (Spinner) findViewById(R.id.spinner1); // 需要填充的数据 String[] data = { "小学", "中学", "中专", "大专", "本科" }; /** * 创建ArrayAdapter适配器(只能一行一行的显示数据) * 参数1:上下文 * 参数2:显示数据的布局资源ID(当前例子是自定义的布局资源) * 参数3:布局资源中用来显示数据项的组件ID * 参数4: 需要显示的数据对象(数组或者List) */ ArrayAdapter adapter = new ArrayAdapter(this, R.layout.item, R.id.item_value, data); spinner.setAdapter(adapter); //注意 Sprinner不能使用setOnItemClickListener()事件 spinner.setOnItemSelectedListener(new OnItemSelectedListener() { publicvoid onItemSelected(AdapterView parent, View view, int position, long id) { Object obj = parent.getItemAtPosition(position); show.setText("您的学历是:"+obj.toString()); } publicvoid onNothingSelected(AdapterView parent) {} }); } }
XML资源
RelativeLayoutxmlns: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:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" android:text="@string/hello_world" tools:context=".MainActivity"/> Spinner android:id="@+id/spinner1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/textView1" android:layout_marginRight="50dp" android:layout_marginTop="90dp" android:layout_toLeftOf="@+id/textView1"/> RelativeLayout> ------------------------------------------- item.xml LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" android:background="@android:color/darker_gray"> TextView android:id="@+id/item_value" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="#ff0000"/> LinearLayout>
6-ListView
典型的MVC架构 通过变更adapter来改变列表呈现逻辑 复用Item控件 缓加载 适配器类型分三种, BaseAdapter 基础适配器 ArrayAdapter 只能展示一行字 SimpleAdapter 最好的扩充性 SimpleCursorAdapter 对数据库的简单结合,可以方便将数据库的内容以列表的形式展示。 实现ListView方式有2种: 1:Activity继承ListActivity 2:在XML布局文件中定义ListView组件
实例
 package org.fkjava.listview; import java.util.ArrayList; import java.util.HashMap; importjava.util.Map; import android.app.Activity; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.AdapterView.OnItemSelectedListener; importandroid.widget.ListView; import android.widget.SimpleAdapter; import android.widget.Toast; publicclass MainActivity extends Activity { ListViewlistView = null; @Override publicvoid onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); listView = (ListView)findViewById(R.id.myListView); ArrayList> data = new ArrayList>(); HashMap map = new HashMap(); map.put("id", 1+""); map.put("name", "李四"); map.put("sex", "男"); map.put("phone", "18664858734"); data.add(map); map = new HashMap(); map.put("id", 2+""); map.put("name", "李四2"); map.put("sex", "女"); map.put("phone", "18622258734"); data.add(map); String[] mapkey = {"id","name","sex","phone"}; int[] resId = {R.id.id,R.id.name,R.id.sex,R.id.phone}; /** * 如果需要listView显示多列,可以使用SimpleAdapter 或者自定义Adapter * 参数1:上下文 * 参数2:需要显示的数据,数据的结构是 List> ArrayList> * 其实List中的Map就是存放需要显示的数据 * 参数3:ListView中显示项的布局 * 参数4:需要显示的数据的key * 参数5:参数4对应的数据显示在参数3的什么组件上 */ SimpleAdapter adapter = new SimpleAdapter(this,data,R.layout.listview_item,mapkey,resId); listView.setAdapter(adapter); //listView滚动选择项事件处理 listView.setOnItemSelectedListener(new OnItemSelectedListener() { publicvoid onItemSelected(AdapterView parent, View view, int position, long id) { Log.i("8888", "---------------"); HashMap map = (HashMap)parent.getItemAtPosition(position); Toast.makeText(MainActivity.this,map.get("name")+"--"+map.get("phone"), Toast.LENGTH_SHORT).show(); } publicvoid onNothingSelected(AdapterView parent) {} }); //listView点击事件处理 listView.setOnItemClickListener(new OnItemClickListener() { publicvoid onItemClick(AdapterView parent, View view, int position, long id) { HashMap map = (HashMap)parent.getItemAtPosition(position); Toast.makeText(MainActivity.this,"点击了--"+map.get("name")+"--"+map.get("phone"), Toast.LENGTH_SHORT).show(); } }); } } ---------------------------------- LinearLayoutxmlns: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" android:orientation="vertical"> LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center_horizontal" android:text="id"/> TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center_horizontal" android:text="姓名"/> TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center_horizontal" android:text="性别"/> TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center_horizontal" android:text="电话"/> LinearLayout> ListView android:id="@+id/myListView" android:layout_width="match_parent" android:layout_height="wrap_content"/> LinearLayout> -------------listview_itme.xml---------------------------- LinearLayoutxmlns: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" android:orientation="vertical"> LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> TextViewandroid:id="@+id/id" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center_horizontal" /> TextViewandroid:id="@+id/name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center_horizontal" /> TextViewandroid:id="@+id/sex" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center_horizontal" /> TextViewandroid:id="@+id/phone" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center_horizontal" /> LinearLayout> LinearLayout>
自定义Adapter
 package org.fkjava.listview; import java.util.ArrayList; import java.util.HashMap; import java.util.Random; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ListView; import android.widget.Toast; public class MainActivity extends Activity { ListView listView = null; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); listView = (ListView) findViewById(R.id.myListView); ArrayList> data = loadData(); //使用自定义Adapter MyAdapter adapter = new MyAdapter(this, data ); listView.setAdapter(adapter); // listView点击事件处理 listView.setOnItemClickListener(new OnItemClickListener() { public void onItemClick(AdapterView parent, View view, int position, long id) { HashMap map = (HashMap) parent .getItemAtPosition(position); Toast.makeText(MainActivity.this, "点击了--" + map.get("name") + "--" + map.get("phone"), Toast.LENGTH_SHORT).show(); } }); } int[] images={R.drawable.bq1,R.drawable.bq2,R.drawable.bq3,R.drawable.bq4,R.drawable.bq5,R.drawable.bq6}; /** * 测试数据填充方法 * @return */ private ArrayList> loadData() { ArrayList> data = new ArrayList>(); HashMap map = null; Random random = new Random(); for (int i = 0; i map = new HashMap(); map.put("head",images[random.nextInt(5)]+""); map.put("name", "李四_"+i); map.put("phone", "1866485873"+i); data.add(map); } return data; } } --------------------------------------------- package org.fkjava.listview; import java.util.ArrayList; import java.util.HashMap; import android.content.Context; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.TextView; /** * 自定义Adapter类,实现更加丰富的和高效的数据加载效果 * @author hanfeili * */ public class MyAdapter extends BaseAdapter { private static final String TAG = "MyAdapter"; Context context ; ArrayList> data; public MyAdapter(Context context , ArrayList> data){ this.context = context; this.data = data; } //实现View的缓存,提高效率 class ViewHolder{ public ImageView headImage; public TextView name; public TextView phone; } /** * 自定义Adapter 重写getView()提供listView显示的项 */ ViewHolder hold = null; public View getView(int position, View convertView, ViewGroup parent) { Log.i(TAG,"----getView----"+position); if(convertView == null){//如果是第一次创建listView项,将创建对应的布局,并获得对应的组件 Log.i(TAG,"---convertView == null-----"); hold = new ViewHolder(); convertView = LayoutInflater.from(this.context).inflate(R.layout.listview_item, null); hold.headImage = (ImageView)convertView.findViewById(R.id.headImg); hold.name = (TextView)convertView.findViewById(R.id.name); hold.phone = (TextView)convertView.findViewById(R.id.phone); convertView.setTag(hold); }else{//获取已经存在的View对象,重用 Log.i(TAG,"---convertView != null-----"); hold =(ViewHolder)convertView.getTag(); } HashMap map = data.get(position); hold.headImage.setBackgroundResource(Integer.parseInt(map.get("head"))); hold.name.setText(map.get("name")); hold.phone.setText(map.get("phone")); return convertView; } /** * 返回需要显示的数据长度 */ public int getCount() { return data.size(); } public Object getItem(int position) { return position; } public long getItemId(int position) { return position; } } --------------------------------- LinearLayoutxmlns: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" android:orientation="vertical"> ListView android:id="@+id/myListView" android:layout_width="match_parent" android:layout_height="wrap_content"/> LinearLayout> ------------------------------------------- xmlversion="1.0"encoding="utf-8"?> LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="horizontal"> ImageView android:id="@+id/headImg" android:layout_width="50dip" android:layout_height="50dip" android:layout_margin="5px"/> LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical"> TextView android:id="@+id/name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="#000000" android:textSize="22px"/> TextView android:id="@+id/phone" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="#000000" android:textSize="13px"/> LinearLayout> LinearLayout>
7-AutoCompleteTextView
 package org.fkjava.autocompletetextview; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.widget.AdapterView; import android.widget.AdapterView.OnItemSelectedListener; import android.widget.ArrayAdapter; import android.widget.AutoCompleteTextView; import android.widget.TextView; import android.widget.Toast; public class MainActivity extends Activity { AutoCompleteTextView autocompleteTextView ; TextView tv; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv = (TextView)findViewById(R.id.tv); autocompleteTextView = (AutoCompleteTextView)findViewById(R.id.autoCompleteTextView); ArrayAdapter adapter = new ArrayAdapter(this,R.layout.autoitem); adapter.add("AAA"); adapter.add("BBB"); adapter.add("BBCCB"); adapter.add("BBKKBBB"); adapter.add("KBBB"); autocompleteTextView.setAdapter(adapter); autocompleteTextView.setOnItemSelectedListener(new OnItemSelectedListener() { public void onItemSelected(AdapterView parent, View view, int position, long id) { String itemStr = (String)parent.getItemAtPosition(position); Toast.makeText(MainActivity.this, id+"---"+position+"--"+itemStr, Toast.LENGTH_SHORT).show(); tv.setText(itemStr); } public void onNothingSelected(AdapterView parent) {} }); } } ----------------------------------- LinearLayoutxmlns: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"> TextViewandroid:id="@+id/tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="请输入关键字" /> AutoCompleteTextViewandroid:id="@+id/autoCompleteTextView" android:layout_width="match_parent" android:layout_height="wrap_content"/> LinearLayout> ----------------------------------------- xmlversion="1.0"encoding="utf-8"?> TextView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:padding="10dp" android:textSize="15sp" android:textColor="#FF9966"/>
8-GridView

实例
package org.fkjava.gridview; import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.GridView; import android.widget.ImageView; /** * GridView 实例 * @authorhanfeili * */ publicclass GridViewTest extends Activity { private GridView gv; publicvoid onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 通过findViewById方法获得GridView对象 gv = (GridView) findViewById(R.id.gridView); // 设置GridView的行数 gv.setNumColumns(3); gv.setAdapter(new MyAdapter(this)); } // 自定义适配器 class MyAdapter extends BaseAdapter { // 图片资源id 数组 private Integer[] imgs = { R.drawable.img01, R.drawable.img02, R.drawable.img03, R.drawable.img04, R.drawable.img05, R.drawable.img06, R.drawable.img07, R.drawable.img08, R.drawable.img01, R.drawable.img02, R.drawable.img03, R.drawable.img04, R.drawable.img05, R.drawable.img06, R.drawable.img07, R.drawable.img08 }; // 上下文对象 Context context; // 构造方法 MyAdapter(Context context) { this.context = context; } // 获得数量 publicint getCount() { returnimgs.length; } // 获得当前选项 public Object getItem(int item) { return item; }// 获得当前选项id publiclong getItemId(int id) { return id; } // 创建View方法 public View getView(int position, View convertView, ViewGroup parent) { ImageView imageView; if (convertView == null) { // 实例化ImageView对象 imageView = new ImageView(context); // 设置ImageView对象布局 imageView.setLayoutParams(new GridView.LayoutParams(100, 150)); // 设置边界对齐 imageView.setAdjustViewBounds(false); // 设置刻度类型 imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); // 设置间距 imageView.setPadding(5, 5, 5, 5); } else { imageView = (ImageView) convertView; } // 为ImageView设置图片资源 imageView.setImageResource(imgs[position]); return imageView; } } } ------------------------------------ LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> GridView android:id="@+id/gridView" android:layout_width="wrap_content" android:layout_height="wrap_content"/> LinearLayout>
9-Gallery
效果图

代码
package org.fkjava.gallery; import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.BaseAdapter; import android.widget.Gallery; import android.widget.ImageView; import android.widget.Toast; /** * Gallery实例 * * @author hanfeili * */ public class MainActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Gallery gallery = (Gallery) findViewById(R.id.gallery1); gallery.setAdapter(new ImageAdapter(this)); gallery.setOnItemClickListener(new OnItemClickListener() { public void onItemClick(AdapterView parent, View view, int position, long id) { Toast.makeText(MainActivity.this, position + "", Toast.LENGTH_LONG).show(); } }); } private Integer[] imgs = { R.drawable.pic1, R.drawable.pic2, R.drawable.pic3, R.drawable.pic4, R.drawable.pic6, R.drawable.pic7, R.drawable.pic8, R.drawable.pic9, R.drawable.pic10, R.drawable.pic11, R.drawable.pic12, R.drawable.pic16, R.drawable.pic17, R.drawable.pic18, R.drawable.pic19, R.drawable.pic20 }; private class ImageAdapter extends BaseAdapter { private Context context = null; public ImageAdapter(Context context) { this.context = context; } public View getView(int position, View convertView, ViewGroup parent) { ImageView iv; if (convertView == null) { iv = new ImageView(this.context); } else { iv = (ImageView) convertView; } iv.setImageResource(imgs[position]); return iv; } public int getCount() { return imgs.length; } public Object getItem(int position) { return position; } public long getItemId(int position) { return position; } } }
布局文件
LinearLayoutxmlns: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" android:orientation="vertical"> TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:text="Gallery 实例" tools:context=".MainActivity"/> Gallery android:id="@+id/gallery1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1"/> LinearLayout> 
10-样式和主题
如果在应用使用了主题,同时应用下的view也使用了样式,那么当主题与样式属性发生冲突时, 样式的优先级比主题高。 单位 px:是屏幕的像素点 in:英寸 mm:毫米 pt:磅,1/72 英寸 dp:一个基于density的抽象单位,如果一个160dpi的屏幕,1dp=1px dip:等同于dp sp:同dp相似,但还会根据用户的字体大小偏好来缩放。 建议使用sp作为文本的单位,其它用dip
样式
样式可以用于单独的View,如:EditText、TextView等;  先在res/values/styles.xml文件中定义如下内容: 24px #CCFF00 然后在布局文件中使用已经定义出来的myStyle样式设置一个组件的style属性: ------------------------------------------------- 样式继承:  当前样式可以继承父样式中定义的值,并可以根据自己的需求进行新增样式属性和覆盖父样式中定义的样式属性。 24px #CCFF00 #FF0000
主题
主题通过AndroidManifest.xml中的和作用于整个应用或某个Activity,主题对整个应用或某个Activity存在全局性影响。  主题用于为应用定义显示风格,定义方式和样式定义大致相同 true ?android:windowNoTitle “?android:windowNoTitle”中的问号用于引用在当前主题中定义过的资源的值。设置使用主题方式1:在AndroidManifest.xml文件中设置使用定义的主题:
11-selector
自定义按钮点击或者获得焦点响应的图片效果  ------------mybutton.xml------------------------ btn_rating_star_off_normal"/> btn_rating_star_on_normal"/> btn_rating_star_on_selected"/> -----------------main.xml--------------------------------------------------- android:background="@layout/mybutton“ android:text="mybtu1"android:padding="10dp"/>
6-菜单

代码
package org.fkjava.meun; import android.os.Bundle; import android.app.Activity; import android.view.Menu; import android.view.MenuItem; import android.widget.Toast; public class MainActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } /** * 表示加载res/emnu目录下的菜单配置文件 * * 推荐通过 xml来配置菜单 * 在新的ADT工具中已经,包含在创建android项目中了 * */ @Override public boolean onCreateOptionsMenu(Menu menu) { //填充xml菜单文件 getMenuInflater().inflate(R.menu.main_menu, menu); return true; } /** * 进行菜单项的事件操作 * 参数 MenuItem 表示选择的 菜单项 */ @Override public boolean onOptionsItemSelected(MenuItem item) { switch(item.getItemId()){//获得选择的菜单项目的id case R.id.menu_save: Toast.makeText(this, "保存", Toast.LENGTH_LONG).show(); break; case R.id.menu_about: Toast.makeText(this, "关于", Toast.LENGTH_LONG).show(); break; case R.id.menu_select: Toast.makeText(this, "查询", Toast.LENGTH_LONG).show(); break; case R.id.menu_update: Toast.makeText(this, "更新", Toast.LENGTH_LONG).show(); break; case R.id.menu_exit: System.exit(0);//退出应用程序 break; case R.id.menu_save_admin: Toast.makeText(this, "新增管理员", Toast.LENGTH_LONG).show(); break; case R.id.menu_save_user: Toast.makeText(this, "新增用户", Toast.LENGTH_LONG).show(); break; } return super.onOptionsItemSelected(item); } } ------------------------------------------- menuxmlns:android="http://schemas.android.com/apk/res/android"> item android:id="@+id/menu_settings" android:orderInCategory="6" android:showAsAction="never" android:title="@string/menu_settings"/> item android:id="@+id/menu_save" android:icon="@drawable/ic_launcher" android:orderInCategory="1" android:title="添加"> menu> item android:id="@+id/menu_save_user" android:orderInCategory="0" android:title="添加用户"/> item android:id="@+id/menu_save_admin" android:orderInCategory="1" android:title="添加管理员"/> menu> item> item android:id="@+id/menu_update" android:orderInCategory="2" android:title="更新"/> item android:id="@+id/menu_delete" android:orderInCategory="3" android:title="删除"/> item android:id="@+id/menu_select" android:orderInCategory="4" android:title="查询"/> item android:id="@+id/menu_about" android:orderInCategory="5" android:title="关于"/> item android:id="@+id/menu_exit" android:orderInCategory="6" android:title="退出"/> menu>
实例2
代码方式创建菜单
package org.fkjava.ui; import android.app.Activity; import android.graphics.Color; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.view.SubMenu; import android.widget.EditText; import android.widget.Toast; /** * 代码方式创建菜单实例 * 如果菜单比较简单,或者没有复用的要求,可以使用代码方式创建菜单 * @author hanfeili * */ public class MenuTest extends Activity { // 定义字体大小菜单项的标识 final int FONT_10 = 0x111; final int FONT_12 = 0x112; final int FONT_14 = 0x113; final int FONT_16 = 0x114; final int FONT_18 = 0x115; // 定义普通菜单项的标识 final int PLAIN_ITEM = 0x11b; // 定义字体颜色菜单项的标识 final int FONT_RED = 0x116; final int FONT_BLUE = 0x117; final int FONT_GREEN = 0x118; private EditText edit; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); edit = (EditText) findViewById(R.id.txt); } // 当用户单击MENU键时触发该方法 @Override public boolean onCreateOptionsMenu(Menu menu) { // -------------向menu中添加字体大小的子菜单------------- SubMenu fontMenu = menu.addSubMenu("字体大小"); // 设置菜单的图标 fontMenu.setIcon(R.drawable.font); // 设置菜单头的图标 fontMenu.setHeaderIcon(R.drawable.font); // 设置菜单头的标题 fontMenu.setHeaderTitle("选择字体大小"); /** * 设置子菜单 * 参数1:菜单的组(相同功能模块的分一组) * 参数2:菜单项ID(每一项的编号) * 参数3:菜单排序(如果都是0,就按照添加的顺序来排序) * 参数4:菜单显示文字 */ fontMenu.add(0, FONT_10, 0, "10号字体"); fontMenu.add(0, FONT_12, 0, "12号字体"); fontMenu.add(0, FONT_14, 0, "14号字体"); fontMenu.add(0, FONT_16, 0, "16号字体"); fontMenu.add(0, FONT_18, 0, "18号字体"); // -------------向menu中添加普通菜单项------------- menu.add(0, PLAIN_ITEM, 0, "普通菜单项"); // -------------向menu中添加文字颜色的子菜单------------- SubMenu colorMenu = menu.addSubMenu("字体颜色"); colorMenu.setIcon(R.drawable.color); // 设置菜单头的图标 colorMenu.setHeaderIcon(R.drawable.color); // 设置菜单头的标题 colorMenu.setHeaderTitle("选择文字颜色"); colorMenu.add(0, FONT_RED, 0, "红色"); colorMenu.add(0, FONT_GREEN, 0, "绿色"); colorMenu.add(0, FONT_BLUE, 0, "蓝色"); return super.onCreateOptionsMenu(menu); } @Override // 选项菜单的菜单项被单击后的回调方法 public boolean onOptionsItemSelected(MenuItem mi) { // 判断单击的是哪个菜单项,并针对性的作出响应。 switch (mi.getItemId()) { case FONT_10: edit.setTextSize(10 * 2); break; case FONT_12: edit.setTextSize(12 * 2); break; case FONT_14: edit.setTextSize(14 * 2); break; case FONT_16: edit.setTextSize(16 * 2); break; case FONT_18: edit.setTextSize(18 * 2); break; case FONT_RED: edit.setTextColor(Color.RED); break; case FONT_GREEN: edit.setTextColor(Color.GREEN); break; case FONT_BLUE: edit.setTextColor(Color.BLUE); break; case PLAIN_ITEM: Toast toast = Toast.makeText(MenuTest.this, "您单击了普通菜单项", Toast.LENGTH_SHORT); toast.show(); break; } return true; } }
XML方式创建菜单
src代码
package org.fkjava.ui; import android.app.Activity; import android.graphics.Color; import android.os.Bundle; import android.view.ContextMenu; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.widget.TextView; import android.widget.Toast; /** * XML创建菜单实例 * * @author hanfeili * */ public class MenuResTest extends Activity { private TextView txt; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); txt = (TextView) findViewById(R.id.txt); // 为文本框注册上下文菜单 registerForContextMenu(txt); } /** * 菜单的创建 */ @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflator = new MenuInflater(this); // 状态R.menu.context对应的菜单,并添加到menu中 inflator.inflate(R.menu.my_menu, menu); return super.onCreateOptionsMenu(menu); } // 创建上下文菜单时触发该方法 @Override public void onCreateContextMenu(ContextMenu menu, View source, ContextMenu.ContextMenuInfo menuInfo) { // 状态R.menu.context对应的菜单,并添加到menu中 new MenuInflater(this).inflate(R.menu.context, menu); menu.setHeaderIcon(R.drawable.tools); menu.setHeaderTitle("请选择背景色"); } // 上下文菜单中菜单项被单击时触发该方法。 @Override public boolean onContextItemSelected(MenuItem mi) { mi.setChecked(true); switch (mi.getItemId()) { case R.id.red: mi.setChecked(true); txt.setBackgroundColor(Color.RED); break; case R.id.green: mi.setChecked(true); txt.setBackgroundColor(Color.GREEN); break; case R.id.blue: mi.setChecked(true); txt.setBackgroundColor(Color.BLUE); break; } return true; } @Override // 选项菜单的菜单项被单击后的回调方法 public boolean onOptionsItemSelected(MenuItem mi) { if (mi.isCheckable()) { mi.setChecked(true); } // 判断单击的是哪个菜单项,并针对性的作出响应。 switch (mi.getItemId()) { case R.id.font_10: txt.setTextSize(10 * 2); break; case R.id.font_12: txt.setTextSize(12 * 2); break; case R.id.font_14: txt.setTextSize(14 * 2); break; case R.id.font_16: txt.setTextSize(16 * 2); break; case R.id.font_18: txt.setTextSize(18 * 2); break; case R.id.red_font: txt.setTextColor(Color.RED); mi.setChecked(true); break; case R.id.green_font: txt.setTextColor(Color.GREEN); mi.setChecked(true); break; case R.id.blue_font: txt.setTextColor(Color.BLUE); mi.setChecked(true); break; case R.id.plain_item: Toast toast = Toast.makeText(MenuResTest.this, "您单击了普通菜单项", Toast.LENGTH_SHORT); toast.show(); break; } return true; } }
xml
my_menu.xml
xmlversion="1.0"encoding="utf-8"?> menuxmlns:android="http://schemas.android.com/apk/res/android"> item android:icon="@drawable/font" android:title="@string/font_size"> menu> groupandroid:checkableBehavior="single"> item android:id="@+id/font_10" android:title="@string/font_10"/> item android:id="@+id/font_12" android:title="@string/font_12"/> item android:id="@+id/font_14" android:title="@string/font_14"/> item android:id="@+id/font_16" android:title="@string/font_16"/> item android:id="@+id/font_18" android:title="@string/font_18"/> group> menu> item> item android:id="@+id/plain_item" android:title="@string/plain_item"> item> item android:icon="@drawable/color" android:title="@string/font_color"> menu> group> item android:id="@+id/red_font" android:title="@string/red_title"/> item android:id="@+id/green_font" android:title="@string/green_title"/> item android:id="@+id/blue_font" android:title="@string/blue_title"/> group> menu> item> menu>
context.xml
xmlversion="1.0"encoding="utf-8"?> menuxmlns:android="http://schemas.android.com/apk/res/android"> groupandroid:checkableBehavior="single"> item android:id="@+id/red" android:alphabeticShortcut="r" android:title="@string/red_title"/> item android:id="@+id/green" android:alphabeticShortcut="g" android:title="@string/green_title"/> item android:id="@+id/blue" android:alphabeticShortcut="b" android:title="@string/blue_title"/> group> menu>
7-Activity
Activity: Activity可以理解为Swing(AWT) 面板panle Activity 上就是放一些 组件(View),比如有 button,TextView.... Activity 本身是不能显示的,显示出来的是放在他上面的组件 在屏幕进行横竖屏切换的时候是重新创建Activity的过程
1-创建
package org.fkjava.activity; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; /** * Activity的创建过程: * 1,一个类继承 Activity * 2,重写onCreate() 进行初始化操作 * 3,在AndroidManifest.xml中进行新增Activity的注册 * 4, 获得对应的组件,并进行操作。 * @authorhanfeili * */ publicclass MainActivity extendsActivity{ publicvoidonCreate(Bundle bundle){ super.onCreate(bundle); //设置本Activity的布局(组件怎么排放) setContentView(R.layout.main); //通过组件的id获得组件对象 final TextView tv = (TextView)findViewById(R.id.textView1); Button myBtn =(Button)findViewById(R.id.mybtn); myBtn.setOnClickListener(new OnClickListener() { publicvoid onClick(View v) { tv.setText("测试成功!"); } }); } }
2-注册
xmlns:android="http://schemas.android.com/apk/res/android" package="org.fkjava.activity" android:versionCode="1" android:versionName="1.0"> uses-sdkandroid:minSdkVersion="8"android:targetSdkVersion="15"/> applicationandroid:label="@string/app_name" android:icon="@drawable/ic_launcher" android:theme="@style/AppTheme"> activityandroid:name=".MainActivity" > intent-filter> actionandroid:name="android.intent.action.MAIN"/> categoryandroid:name="android.intent.category.LAUNCHER"/> intent-filter> activity> application> manifest>
3-Activity生命周期
Android 程序的生命周期是由系统控制而非程序自身控制。
程序重要性
 1前台进程: 在和用户交互的进程。这样的程序重要性最高,只会在系统内存非常低,迫不得已时才会被结束。 2可见进程: 在屏幕上显示,但没有办法和用户交互。这样的进程也很重要,只会在系统没有足够内存运行所有前台进程时,才会被结束。 3服务进程: 在后台持续运行(Service),如后台音乐播放。这样的进程对用户来说一般很有用,所以只有当系统没有足够内存来维持所有的前台和可见进程时,才会被结束。 4后台进程: 用户不可见的activity。这样的程序在系统内存不足时,会被结束。(最近使用的列表中,最近使用的最后关闭。) 5空进程: 不含任何活动的程序组件。系统可能随时关闭这类进程。 提供缓存机制,方便下次启动加速。
生命周期图
 仔细观察Log日子输出是不是与上图一致
实例代码
 MainActivity代码: package org.fkjava.activitylife; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.util.Log; import android.view.View; public class MainActivity extends Activity { private static final String TAG = "MainActivity"; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Log.i(TAG, "----------onCreate------------"); } /** * 可以在组件的配置文件上定义 onClick 来指定执行Activity类中的某个方法作为事件处理方法 * 注意这个方法可以有返回值,但是这个方法一定要有一个View参数 ,view参数表示事件源 * android:text="生命周期 测试" android:onClick="myClick"/> * @param v */ public void myClick(View v){ Intent intent =null; if(v.getId() == R.id.button1){ intent = new Intent(this,OtherActivity.class); }else if(v.getId() == R.id.button2){ intent = new Intent(this,DialogActivity.class); } startActivity(intent); } @Override protected void onStart() { Log.i(TAG, "----------onStart------------"); super.onStart(); } @Override protected void onRestart() { Log.i(TAG, "----------onRestart------------"); super.onRestart(); } @Override protected void onResume() { Log.i(TAG, "----------onResume------------"); super.onResume(); } @Override protected void onPause() { Log.i(TAG, "----------onPause------------"); super.onPause(); } @Override protected void onStop() { Log.i(TAG, "----------onStop------------"); super.onStop(); } @Override protected void onDestroy() { Log.i(TAG, "----------onDestroy------------"); super.onDestroy(); } } OtherActivity代码: package org.fkjava.activitylife; import android.os.Bundle; import android.app.Activity; import android.util.Log; import android.view.Menu; public class OtherActivity extends Activity { private static final String TAG = "OtherActivity"; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.other); Log.i(TAG, "----------onCreate------------"); } @Override protected void onStart() { Log.i(TAG, "----------onStart------------"); super.onStart(); } @Override protected void onRestart() { Log.i(TAG, "----------onRestart------------"); super.onRestart(); } @Override protected void onResume() { Log.i(TAG, "----------onResume------------"); super.onResume(); } @Override protected void onPause() { Log.i(TAG, "----------onPause------------"); super.onPause(); } @Override protected void onStop() { Log.i(TAG, "----------onStop------------"); super.onStop(); } @Override protected void onDestroy() { Log.i(TAG, "----------onDestroy------------"); super.onDestroy(); } } DialogActivity代码 : package org.fkjava.activitylife; import android.os.Bundle; import android.app.Activity; import android.util.Log; import android.view.Menu; public class DialogActivity extends Activity { private static final String TAG = "DialogActivity"; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.dialog); Log.i(TAG, "----------onCreate------------"); } @Override protected void onStart() { Log.i(TAG, "----------onStart------------"); super.onStart(); } @Override protected void onRestart() { Log.i(TAG, "----------onRestart------------"); super.onRestart(); } @Override protected void onResume() { Log.i(TAG, "----------onResume------------"); super.onResume(); } @Override protected void onPause() { Log.i(TAG, "----------onPause------------"); super.onPause(); } @Override protected void onStop() { Log.i(TAG, "----------onStop------------"); super.onStop(); } @Override protected void onDestroy() { Log.i(TAG, "----------onDestroy------------"); super.onDestroy(); } } activityandroid:name=".DialogActivity"android:theme="@android:style/Theme.Dialog"/>
4-数据保存与恢复
package org.fkjava.activitysavedata; import android.os.Bundle; import android.app.Activity; import android.util.Log; import android.view.Menu; import android.widget.EditText; public class MainActivity extends Activity { private static final String TAG = "MainActivity"; EditText firstName,lastName=null; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.i(TAG, "----------onCreate------------"); setContentView(R.layout.activity_main); firstName= (EditText)this.findViewById(R.id.firstname); lastName= (EditText)this.findViewById(R.id.lastname); } /** * 保存实例状态 */ @Override protected void onSaveInstanceState(Bundle outState) { //super.onSaveInstanceState(outState); Log.i(TAG, "----------onSaveInstanceState------------"); //保存数据 outState.putString("first", firstName.getText().toString()); outState.putString("last", lastName.getText().toString()); } /** * 恢复实例状态 * 这个方法并不会与保存方法永远成对调用 * 本类实例本关闭了才会调用进行数据恢复 * 注意 回退是 会 关闭程序的  home是 不会 关闭程序的 横竖屏切换是会重新创建 实例的 */ @Override protected void onRestoreInstanceState(Bundle savedInstanceState) { //super.onRestoreInstanceState(savedInstanceState); Log.i(TAG, "----------onRestoreInstanceState------------"); //获得保存的数据 String first = savedInstanceState.getString("first"); String last = savedInstanceState.getString("last"); firstName.setText(last); lastName.setText(first); } @Override protected void onStart() { Log.i(TAG, "----------onStart------------"); super.onStart(); } @Override protected void onRestart() { Log.i(TAG, "----------onRestart------------"); super.onRestart(); } @Override protected void onResume() { Log.i(TAG, "----------onResume------------"); super.onResume(); } @Override protected void onPause() { Log.i(TAG, "----------onPause------------"); super.onPause(); } @Override protected void onStop() { Log.i(TAG, "----------onStop------------"); super.onStop(); } @Override protected void onDestroy() { Log.i(TAG, "----------onDestroy------------"); super.onDestroy(); } } LinearLayoutxmlns: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" android:orientation="vertical"> TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="数据保存和恢复实例"/> EditTextandroid:id="@+id/firstname" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="请输入用户姓!"/> EditTextandroid:id="@+id/lastname" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="请输入用户名!"/> LinearLayout>
5-Activity实例化策略
standard (默认模式 ) standard 的加载模式就是每次都创建一个Activity的新实例。 singleTop 如果在栈顶存在目标Activity的实例,则将intent发送给该实例,否则创建新的实例并发送给新的实例。 singleTask 系统会先在栈中搜索是否存在目标Activity的实例,如果存在就直接将Intent发送给它。否则创建一个新实例再将Intent发送给它。 singleInstance singleInstance模式是将一个Activity实例共享给多个Task使用。
1-standard 默认常量
standard 每次启动都是创建一个新的Activity实例。 
2-singleTop
singleTop 当启动一个Activity的时候, 如果这个目标Activity在栈顶 将直接使用栈顶的目标实例. 如果不在栈顶,将创建一个新的Activity实例,并将Intent传递给新的实例 activityandroid:name=".OtherActivity"android:launchMode="singleTop"/> 
3-singleTask
singleTask 当启动一个Activity的时候, 如果这个目标Activity在栈 将直接使用栈中的目标实例. 如果不在栈中,将创建一个新的Activity实例,并将Intent传递给新的实例 activityandroid:name=".OtherActivity"android:launchMode="singleTask"/> 
4-singleInstance
singleInstance模式是将一个Activity实例共享给多个Task使用。 
Fragment
Android是在Android 3.0(API level 11)开始引入Fragment的。 可以把Fragment想成Activity中的模块,这个模块有自己的布局,有自己的生命周期,单独处理自己的输入,在Activity运行的时候可以加载或者移除Fragment模块。 可以把Fragment设计成可以在多个Activity中复用的模块。 当开发的应用程序同时适用于平板电脑和手机时,可以利用Fragment实现灵活的布局,改善用户体验。 
Fragment的生命周期
因为Fragment必须嵌入在Acitivity中使用,所以Fragment的生命周期和它所在的Activity是保持一致的。 如果Activity是 暂停 状态,其中所有的Fragment都是暂停状态; 如果Activity是 停止 状态,这个Activity中所有的Fragment都不能被启动; 如果Activity被 销毁 ,那么它其中的所有Fragment都会被销毁。 如果Activity在激活状态,可以独立控制Fragment的状态,比如添加或者删除某个Fragment。 当这样进行fragment transaction的时候,可以把fragment放入Activity的back stack中,这样用户就可以进行返回操作。
一图胜千言

一图胜千言2

8-Intent和Intent Filter
Intent 就是为了降低组件与组件之间的耦合度的。 Intent 表示 意图(想要什么) Intent: 显示Intent (一般应用于 本应用程序 中的组件(Activity,Service...)之间的调用) 隐式Intent (一般应用于 多个应用程序 之间的组件(Activity,Service...)之间的调用)
Intent应用范围
启动Activity 1 Context.startActivity() 2 Context.startActivityForResult() 启动服务 1 Context.startService() 启动服务(建立和服务的连接) 2 Context.bindService() 绑定服务 发送广播 通过广播机制发送出去的Intent将会传给所 有监听 此Intent的Broadcast Receivers
Intent使用方式
通过Intent 显示启动组件的方式: Intent intent =null; publicvoid onClick(View v) { switch (v.getId()) { case R.id.button1: //创建Intent的时候指定 启动 目标组件 intent = new Intent(this,OtherActivity.class); break; case R.id.button2: intent = new Intent(); //通过setClass方法设置 启动 目标组件 intent.setClass(this, OtherActivity.class); break; case R.id.button3: intent = new Intent(); //通过setComponent方法设置 启动 目标组件 intent.setComponent(new ComponentName(this,OtherActivity.class)); break; case R.id.button4: intent = new Intent(); //通过setClassName方法设置 启动 目标组件 //参数1:本应用程序的包名 //参数2:目标组件的包名+类名 intent.setClassName("org.fkjava.intent", "org.fkjava.intent.OtherActivity"); break; } startActivity(intent); }
参数传递
在组件之间进行携带参数跳转有2种方式: 1:使用Bundle携带(底层就是一个Map的操作) 2: 直接使用Intent携带(底层就是一个Map的操作)
Bundle
Bundle类用作携带数据,它类似于Map,用于存放key-value名值对形式的值。 key同名的数据会被替换 //携带数据类 Bundle bundle = new Bundle(); //绑定参数 bundle.putString(“name”, “疯狂java"); //绑定到intent上 intent.putExtras(bundle); ----------------------------------------- Bundle bundle = this.getIntent().getExtras(); String name = bundle.getString(“name");
设置传递的参数
publicvoid onClick(View v) { String name = username.getText().toString(); int pass = Integer.parseInt(password.getText().toString()); String ph = phone.getText().toString(); //创建Intent的时候指定 启动 目标组件 Intent intent = new Intent(this,OtherActivity.class); //参数传递方式1: //创建应该Bundle进行传递参数的绑定(Bundle就是应该Map) Bundle bundle = new Bundle(); //putXxx()Xxx对应传入相应的类型 bundle.putString("uname", name); bundle.putInt("pass", pass); bundle.putString("phone", ph); //将带参数的Bundle对象与intent进行关联 intent.putExtras(bundle); //参数传递方式2: //直接使用intent的putExtra方法进行参数的传递其实也是类似Map的操作 intent.putExtra("key", 168); intent.putExtra("key2", "fkjava"); startActivity(intent); }
获得参数
publicclass OtherActivity extends Activity { EditText showusername,showpassword,showphone; @Override publicvoid onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.other); showusername = (EditText) findViewById(R.id.showusername); showpassword = (EditText) findViewById(R.id.showpassword); showphone = (EditText) findViewById(R.id.showphone); //获得MainActivity发送的intent对象 Intent intent = this.getIntent(); //从Bundle中获得传递的参数 Bundle bundle = intent.getExtras();//对应MainActivity 类代码中intent.putExtras(bundle); String un = bundle.getString("uname");// bundle.putString("uname", name); int pass = bundle.getInt("pass",0); String phone = bundle.getString("phone"); //获得Intent中包含的传递的参数 intkey = intent.getIntExtra("key", 0); String key2 = intent.getStringExtra("key2"); Toast.makeText(this, "通过Intent本身传递的参数:"+key+"--"+key2, Toast.LENGTH_LONG).show(); showusername.setText(un); showpassword.setText(pass+""); showphone.setText(phone); }
复合类型参数传递
1、实现Serializable接口 通过串行化技术,实现Serializable接口,Parcelable和Serializable原理相似,都是先转换为基本的类型如字节数组。 putExtra(String name, Serializable value) 。 2、实现Parcelable接口 对于Android来说传递复杂类型,主要是将自己的类转换为基础的字节数组,Activity之间传递数据是通过Intent实现的,对于二进制数据,传递的参数为 putExtra(String name, Parcelable value) , putExtra(String name, Parcelable[] value)比如Bitmap类就实现了Parcelable接口,如果需要在Activity中传递图片,可以直接用Bitmap类型,当然如果本身是Drawable你可以先转化为Bitmap。 同时Parcelable效率比标准的Java Serializable 序列化更高,也可以在AIDL中使用进行交换数据。
带返回的Activity操作
返回处理: 1:可以自己直接返回 2:可以手动点击返回
请求
package org.fkjava.intent; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; public class MainActivity extends Activity implements OnClickListener { private static final String TAG = "MainActivity"; Button btn1; EditText key,key2,result; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btn1 = (Button) findViewById(R.id.button1); btn1.setOnClickListener(this); key = (EditText) findViewById(R.id.key); key2 = (EditText) findViewById(R.id.key2); result = (EditText) findViewById(R.id.result); } public void onClick(View v) { int k = Integer.parseInt(key.getText().toString()); int k2 = Integer.parseInt(key2.getText().toString()); //创建Intent的时候指定 启动 目标组件 Intent intent = new Intent(this,OtherActivity.class); intent.putExtra("key", k); intent.putExtra("key2", k2); //启动一个带返回的Activity //参数1:intent //参数2:请求码(确定什么地方发起的请求) this.startActivityForResult(intent, 168); } /** * 返回调用 * 参数1:请求码 * 参数2:响应码(确定什么地方返回的) * 参数3:返回的数据 */ @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { Log.i(TAG, "------onActivityResult-:"+requestCode+"----"+resultCode); //获得data中返回的数据 int msg = data.getIntExtra("msg", 0); result.setText(msg+""); } }
返回
publicclass OtherActivity extends Activity { @Override publicvoid onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.other); Intent intent = this.getIntent(); int i = intent.getIntExtra("key", 0); int j = intent.getIntExtra("key2", 0); int msg = i*j; intent.putExtra("msg", msg); //设置返回数据 //参数1:响应码 //参数2:需要返回的数据 this.setResult(888, intent); this.finish();//记得一定调用finish()否则不会返回 } }
隐式Intent
 通常是方便应用程序之间相互 对应 categoryandroid:name="android.intent.category.DEFAULT"/>
Intent中的六类数据

Action
Category
categoryandroid:name="android.intent.category.DEFAULT"/>
Data
data android:scheme="http" android:host="www.fkjava.org" android:port="8080" android:path="/index.html" android:mimeType="text/html"/> //intent 携带指定格式的数据 //intent.setData(Uri.parse("http://www.fkjava.org:8080/index.html")); //给intent加一个数据类型 //intent.setType("text/html"); //如果需要给intent设置data和type 必须使用setDataAndType方法,而不能单独setType()和setData();因为这两个方法会互相清除对方配置 intent.setDataAndType(Uri.parse("http://www.fkjava.org:8080/index.html"), "text/html");
完整代码
AndroidManifestxml配置
manifestxmlns:android="http://schemas.android.com/apk/res/android" package="org.fkjava.intent" android:versionCode="1" android:versionName="1.0"> uses-sdk android:minSdkVersion="8" android:targetSdkVersion="15"/> 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> actionandroid:name="android.intent.action.MAIN"/> categoryandroid:name="android.intent.category.LAUNCHER"/> intent-filter> activity> ".OtherActivity" > "org.fkjava.myaction" /> "org.fkjava.myaction2" /> "org.fkjava.mycategory" /> "org.fkjava.mycategory2" /> android:scheme="http" android:host="www.fkjava.org" android:port="8080" android:path="/index.html" android:mimeType="text/html"/> "android.intent.category.DEFAULT" /> application> manifest>
类代码
package org.fkjava.intent; import android.app.Activity; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; public class MainActivity extends Activity implements OnClickListener { private static final String TAG = "MainActivity"; Button btn1; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btn1 = (Button) findViewById(R.id.button1); btn1.setOnClickListener(this); } public void onClick(View v) { //创建Intent的时候指定 启动 目标组件 //Intent intent = new Intent(this,OtherActivity.class); //隐式Intent Intent intent = new Intent(); //给Intent设置一个自定义的Action,动作描述(就是一个字符串) //intent.setAction("org.fkjava.myaction"); intent.setAction("org.fkjava.myaction2"); //给Intent设置一个自定义的Category intent.addCategory("org.fkjava.mycategory"); intent.addCategory("org.fkjava.mycategory2"); //intent 携带指定格式的数据 //intent.setData(Uri.parse("http://www.fkjava.org:8080/index.html")); //给intent加一个数据类型 //intent.setType("text/html"); //如果需要给intent设置data和type 必须使用setDataAndType方法,而不能单独setType()和setData();因为这两个方法会互相清除对方配置 intent.setDataAndType(Uri.parse("http://www.fkjava.org:8080/index.html"), "text/html"); startActivity(intent); } } ------------------------------------------------- package org.fkjava.intent; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.widget.EditText; import android.widget.Toast; public class OtherActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.other); } }
常用代码
隐式Intent用法实例 //显示网页 Uri uri = Uri.parse("http://google.com"); Intent it = new Intent(Intent.ACTION_VIEW, uri); startActivity(it); //显示地图 Uri uri = Uri.parse("geo:38.899533,-77.036476"); Intent it = new Intent(Intent.ACTION_VIEW, uri); startActivity(it); //其他 geo URI 範例 //geo:latitude,longitude //geo:latitude,longitude?z=zoom //geo:0,0?q=my+street+address //geo:0,0?q=business+near+city //google.streetview:cbll=lat,lng&cbp=1,yaw,,pitch,zoom&mz=mapZoom //路径规划 Uri uri = Uri.parse("http://maps.google.com/maps?f=d&saddr=startLat%20startLng&daddr=endLat%20endLng&hl=en"); Intent it = new Intent(Intent.ACTION_VIEW, uri); startActivity(it); //where startLat, startLng, endLat, endLng are a long with 6 decimals like: 50.123456 //打电话 //叫出拨号程序 Uri uri = Uri.parse("tel:10086"); Intent it = new Intent(Intent.ACTION_DIAL, uri); startActivity(it); //直接打电话出去 Uri uri = Uri.parse("tel:10086"); Intent it = new Intent(Intent.ACTION_CALL, uri); startActivity(it); //发送打电话权限 //传送SMS/MMS //调用短信程序 Intent it = new Intent(Intent.ACTION_VIEW, uri); it.putExtra("sms_body", "The SMS text"); it.setType("vnd.android-dir/mms-sms"); startActivity(it); //发送短信权限: //传送消息 Uri uri = Uri.parse("smsto://10086"); Intent it = new Intent(Intent.ACTION_SENDTO, uri); it.putExtra("sms_body", "The SMS text"); startActivity(it); //传送 MMS Uri uri = Uri.parse("content://media/external/images/media/23"); Intent it = new Intent(Intent.ACTION_SEND); it.putExtra("sms_body", "some text"); it.putExtra(Intent.EXTRA_STREAM, uri); it.setType("image/png"); startActivity(it); //传送 Email Uri uri = Uri.parse("mailto:xxx@abc.com"); Intent it = new Intent(Intent.ACTION_SENDTO, uri); startActivity(it); Intent it = new Intent(Intent.ACTION_SEND); it.putExtra(Intent.EXTRA_EMAIL, "me@abc.com"); it.putExtra(Intent.EXTRA_TEXT, "The email body text"); it.setType("text/plain"); startActivity(Intent.createChooser(it, "Choose Email Client")); Intent it=new Intent(Intent.ACTION_SEND); String[] tos={"me@abc.com"}; String[] ccs={"you@abc.com"}; it.putExtra(Intent.EXTRA_EMAIL, tos); it.putExtra(Intent.EXTRA_CC, ccs); it.putExtra(Intent.EXTRA_TEXT, "The email body text"); it.putExtra(Intent.EXTRA_SUBJECT, "The email subject text"); it.setType("message/rfc822"); startActivity(Intent.createChooser(it, "Choose Email Client")); //传送附件 Intent it = new Intent(Intent.ACTION_SEND); it.putExtra(Intent.EXTRA_SUBJECT, "The email subject text"); it.putExtra(Intent.EXTRA_STREAM, "file:///sdcard/mysong.mp3"); sendIntent.setType("audio/mp3"); startActivity(Intent.createChooser(it, "Choose Email Client")); //播放多媒体 Uri uri = Uri.parse("file:///sdcard/song.mp3"); Intent it = new Intent(Intent.ACTION_VIEW, uri); it.setType("audio/mp3"); startActivity(it); Uri uri = Uri.withAppendedPath(MediaStore.Audio.Media.INTERNAL_CONTENT_URI, "1"); Intent it = new Intent(Intent.ACTION_VIEW, uri); startActivity(it); //Market 相关 //寻找某个应用 Uri uri = Uri.parse("market://search?q=pname:pkg_name"); Intent it = new Intent(Intent.ACTION_VIEW, uri); startActivity(it); //where pkg_name is the full package path for an application //显示某个应用的相关信息 Uri uri = Uri.parse("market://details?id=app_id"); Intent it = new Intent(Intent.ACTION_VIEW, uri); startActivity(it); //where app_id is the application ID, find the ID //by clicking on your application on Market home //page, and notice the ID from the address bar //Uninstall 应用程序 Uri uri = Uri.fromParts("package", strPackageName, null); Intent it = new Intent(Intent.ACTION_DELETE, uri); startActivity(it); //定位sdcard上的资源 File file = new File("mnt/sdcard/fkjava.png"); Intent intent = new Intent(Intent.ACTION_VIEW); intent.setDataAndType(Uri.fromFile(file), "image/*"); startActivity(intent);
10-存储策略

1-SharedPreferences
SharedPreferences是轻量级存储类,只能存放基本数据类型,且只能在本程序中使用,一般用于存放软件的配置参数(字体,颜色,位置,默认参数等),整体效率不是特别的高,但是对于常规的轻量级而言,比SQLite要好不少。 SharedPreferences是以键值对来存储应用程序的配置信息的一种方式,基本上和J2SE(java.util.prefs.Preferences)中的用法一样。存放的数据在底层是以xml文件的格式存储在设备中的,存放于/data/data/PACKAGE_NAME/shared_prefs目录下面。 SharedPreferences进行配置信息保存 例如应用程序的: 配置 ,风格 ,主题 
布局xml
LinearLayoutxmlns: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" android:background="@drawable/bg_login" android:orientation="vertical"> TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:text="登录" android:textColor="#ff0000" android:textSize="50dp"/> LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" android:paddingLeft="10dp"> TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/nameLabel"/> EditText android:id="@+id/name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:drawableLeft="@drawable/user" android:ems="8" android:hint="@string/namehint"/> CheckBox android:id="@+id/autoLogin" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="记住我"/> LinearLayout> LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" android:paddingLeft="10dp"> TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/passwordLabel"/> EditText android:id="@+id/password" android:layout_width="wrap_content" android:layout_height="wrap_content" android:drawableLeft="@drawable/busy" android:ems="8" android:hint="@string/passwordhint" android:inputType="numberPassword" android:password="true"/> CheckBox android:id="@+id/show" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/showLabel"/> LinearLayout> LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" android:paddingLeft="20dp" android:layout_gravity="center_horizontal"> Button android:id="@+id/submit" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/submitLabel"/> Button android:id="@+id/reset" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/resetLabel"/> LinearLayout> LinearLayout>
代码
package org.fkjava.ui; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.os.Bundle; import android.text.method.HideReturnsTransformationMethod; import android.text.method.PasswordTransformationMethod; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.CheckBox; import android.widget.CompoundButton; import android.widget.EditText; import android.widget.Toast; /** * 通过自动登录实例学习 SharedPreferenes组件的使用 * @author hanfeili * */ public class Login extends Activity implements OnClickListener{ EditText name,password; CheckBox show,isAutoLogin; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.login); SharedPreferences sp = this.getSharedPreferences("LoginInfo",Context.MODE_PRIVATE); //通过SharedPreferences中保存的isAutoLogin值判断是否进行自动登录 if(sp.getBoolean("isAutoLogin", false)){ //根据key获取SharedPreferences对应存储文件中的数据 String userName = sp.getString("userName", ""); int pass = sp.getInt("password", 0); Toast.makeText(this, "自动登录中..."+userName+"-"+pass, Toast.LENGTH_LONG).show(); Intent intent = new Intent(this,Main.class); startActivity(intent); }else{ //用户名输入框 name = (EditText) findViewById(R.id.name); //密码输入框 password = (EditText) findViewById(R.id.password); //密码回显复选框 show = (CheckBox) findViewById(R.id.show); //绑定密码回显复选框进行密码隐藏和回显处理 show.setOnCheckedChangeListener(new android.widget.CompoundButton.OnCheckedChangeListener() { /** * 当复选框状态关闭的时候触发 * 参数1:事件源 * 参数2:状态值(选择返回true) */ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { if(isChecked){ //设置将密码输入框中数据回显成明文 password.setTransformationMethod(new HideReturnsTransformationMethod()); }else{ //设置将密码输入框中明文数据显示成密码状态 password.setTransformationMethod(new PasswordTransformationMethod()); } } }); //是否自动登录复选框 isAutoLogin = (CheckBox) findViewById(R.id.autoLogin); //组件绑定单击事件 findViewById(R.id.submit).setOnClickListener(this); Button reset = (Button) findViewById(R.id.reset); reset.setOnClickListener(this); } } public void onClick(View v) { if(v.getId() == R.id.submit){ String n = name.getText().toString(); String pass = password.getText().toString(); SharedPreferences sp = this.getSharedPreferences("LoginInfo",Context.MODE_PRIVATE); //如果数据需要保存(编辑,删除)到SharedPreferences存储文件中,需要获得Editor对象 //才可以编辑 Editor sped = sp.edit(); if(isAutoLogin.isChecked()){ /** * 获得本应用程序的SharedPreferences存储文件 * 参数1:文件名(如果文件名对应的文件不存在将自动创建 * data/data/app_package(org.fkjava.ui)/shared_prefs/LoginInfo.xml * 参数2:文件的访问模式(MODE_PRIVATE 私有模式,只能本应用程序操作) */ //存储数据,按key-value方式 sped.putString("userName", n); sped.putInt("password", Integer.parseInt(pass)); sped.putBoolean("isAutoLogin", true); //一定要记得commit()否则数据是不会保存的 sped.commit(); }else{ //如果没有选择将清空原来保存的数据 sped.clear(); } Intent intent = new Intent(this,Main.class); startActivity(intent); }else if(v.getId()== R.id.reset){ name.setText(""); password.setText(""); show.setChecked(false); isAutoLogin.setChecked(false); } } }
2-文件操作
android 的文件数据保存支持 A:本应用程序包保存 B:外部设备SDcard保存 
本应用程序文件读写
本应用操作存储的位置在: data/data/应用程序的包/files/ package org.fkjava.file; import java.io.FileInputStream; import java.io.FileOutputStream; import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; publicclass MainActivity extends Activity implements OnClickListener{ EditText content,fileName; Button input ,output,sdcardInput,sdcardoutput,claer; @Override publicvoid onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); content = (EditText)findViewById(R.id.content); fileName = (EditText)findViewById(R.id.filename); input = (Button)findViewById(R.id.input); output = (Button)findViewById(R.id.output); sdcardInput = (Button)findViewById(R.id.sdcardInput); sdcardoutput = (Button)findViewById(R.id.sdcardoutput); claer = (Button)findViewById(R.id.claer); input.setOnClickListener(this); output.setOnClickListener(this); sdcardInput.setOnClickListener(this); sdcardoutput.setOnClickListener(this); claer.setOnClickListener(this); } publicvoid onClick(View v) { switch(v.getId()){ case R.id.output://保存到本应用 try { //通过android系统提供的openFileOutput()获得一个对本应用程序进行文件输出的文件输出流 //参数1:指定输出到什么文件的文件名(不能有路径) //参数2:指定文件操作模式(MODE_PRIVATE 私有模式) FileOutputStream fos =this.openFileOutput(fileName.getText().toString(), Context.MODE_PRIVATE); String msg = content.getText().toString(); //写出数据到文件 fos.write(msg.getBytes()); fos.close(); } catch (Exception e) { e.printStackTrace(); } break; case R.id.input://从本应用读入 try{ FileInputStream fis = this.openFileInput(fileName.getText().toString()); byte[] buffer = newbyte[1024*2]; intlen = 0; StringBuilder sb = new StringBuilder(); while((len = fis.read(buffer))!=-1){ sb.append(new String(buffer)); } content.setText(sb.toString()); fis.close(); }catch(Exception e){ e.printStackTrace(); } break; case R.id.sdcardoutput://保存到sdcard break; case R.id.sdcardInput://从sdcard读入 break; case R.id.claer://清空数据 content.setText(""); fileName.setText(""); break; } } } -------------------------------------- LinearLayoutxmlns: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" android:orientation="vertical"> TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="文件读写"/> EditText android:id="@+id/content" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:ems="10" android:hint="输入需要保存的内容"> requestFocus/> EditText> EditText android:id="@+id/filename" android:layout_width="match_parent" android:layout_height="wrap_content" android:ems="10" android:hint="输入文件名" android:inputType="textPersonName"/> LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal"> Button android:id="@+id/output" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="保存到本应用"/> Button android:id="@+id/input" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="从本应用读入"/> LinearLayout> LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal"> Button android:id="@+id/sdcardoutput" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="保存到sdcard"/> Button android:id="@+id/sdcardInput" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="从sdcard读入"/> LinearLayout> Button android:id="@+id/claer" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="清空"/> LinearLayout>
SDCard文件读写
case R.id.sdcardoutput:// 保存到sdcard //文件写sdcard操作需要注意: //步骤1:需要先判断机器有没有配置sdcard //步骤2: 需要添加sdcard操作权限 //AndroidManifest.xml配置 /** * */ //步骤3:获得需要操作的文件路径 //可以使用new File("mnt/sdcard")和Environment.getExternalStorageDirectory(),推荐使用后面的方式,更加方便 // 判断本机器有没有 配置sdcard if (Environment.getExternalStorageState().equals( Environment.MEDIA_MOUNTED)) { // File file = new File("mnt/sdcard"); // sdcard的根路径 // Environment.getExternalStorageDirectory(); // 创建文件输出流指向sdcard根路径 FileOutputStream fos2 = new FileOutputStream(new File( Environment.getExternalStorageDirectory(), fileName.getText().toString())); String msg2 = content.getText().toString(); // 写出数据到文件 fos2.write(msg2.getBytes()); fos2.close(); } break; case R.id.sdcardInput:// 从sdcard读入 if (Environment.getExternalStorageState().equals( Environment.MEDIA_MOUNTED)) { FileInputStream fis2 = new FileInputStream(new File(Environment.getExternalStorageDirectory()+File.separator+fileName.getText().toString())); byte[] buffer2 = newbyte[1024 * 2]; intlen2 = 0; StringBuilder sb2 = new StringBuilder(); while ((len2 = fis2.read(buffer2)) != -1) { sb2.append(new String(buffer2)); } content.setText(sb2.toString()); fis2.close(); } break; -------------------------------- uses-permissionandroid:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
图片读
 package org.fkjava.file2; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.Bundle; import android.os.Environment; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.ImageView; /** * 获得sdcard上的图片数据, 并显示出来 因为是读sdcard上的数据所有可以不需要配置sdcard权限 * @authorhanfeili * */ publicclass MainActivity extends Activity { ImageView imageview; Button load; @Override publicvoid onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); imageview = (ImageView) findViewById(R.id.imageView1); load = (Button) findViewById(R.id.load); load.setOnClickListener(new OnClickListener() { publicvoid onClick(View v) { try { if (Environment.getExternalStorageState().equals( Environment.MEDIA_MOUNTED)) { //获得sdcard上的图片路径 InputStream input = new FileInputStream(new File( Environment.getExternalStorageDirectory() + File.separator + "7.jpg")); //通过BitmapFactory方法将一个流中数据转换成Bitmap图片 Bitmap image= BitmapFactory.decodeStream(input); //设置imageView组件需要显示的bitmap数据 imageview.setImageBitmap(image); } } catch (Exception e) { e.printStackTrace(); } } }); } } ---------------------------------------------------------- LinearLayoutxmlns: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" android:orientation="vertical"> ImageView android:id="@+id/imageView1" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1"/> Button android:id="@+id/load" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="获得sdcard图片"/> LinearLayout>
3-网络操作
如果手机没有
注意
1:进行网络操作的时候需要配置网络操作权限 uses-permissionandroid:name="android.permission.INTERNET"/> 2:如果我们进行网络操作测试的时候,不能写127.0.0.1或localhost ,需要写具体的ip地址 java.net.ConnectException: failed to connect to localhost/127.0.0.1 (port 8080): connect failed: ECONNREFUSED (Connection refused) 3:如果你的设备是android4.0系统,进行网络操作必须放在一个子线程中完成。否则报错。android.os.NetworkOnMainThreadException
1-URLConnection
URL
package org.fkjava.file2; import java.io.InputStream; import java.net.URL; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.ImageView; /** * 获得网络上的图片数据, 并显示出来 * @authorhanfeili * */ publicclass MainActivity extends Activity { ImageView imageview; Button load; @Override publicvoid onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); imageview = (ImageView) findViewById(R.id.imageView1); load = (Button) findViewById(R.id.load); load.setOnClickListener(new OnClickListener() { publicvoid onClick(View v) { //因为现在我们的代码是针对4.0以后的系统开发的,所以网络操作必须在子线程中操作 new Thread(){ publicvoid run(){ try { URL url = new URL("http://www.baidu.com/img/baidu_sylogo1.gif"); InputStream input = url.openStream(); Bitmap bitmap = BitmapFactory.decodeStream(input); Log.i("TEST", "-----Thread.run()-----------"); //在子线程中不能操作在主线程中创建的ImageView组件,所以必须在主线程中操作,我们就使用了我们以前学习的Handler来实现 //子线程与主线程的通信 //imageview.setImageBitmap(bitmap); Message msg = Message.obtain(); msg.obj = bitmap; handler.sendMessage(msg); } catch (Exception e) { e.printStackTrace(); } } }.start(); } }); } Handlerhandler = new Handler(){ @Override publicvoid handleMessage(Message msg) { Log.i("handler", "-----handleMessage-----------"); Bitmap bitmap = (Bitmap)msg.obj; imageview.setImageBitmap(bitmap); } }; }
HttpURLConnection
package org.fkjava.file2; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.ImageView; /** * 获得网络上的图片数据, 并显示出来 * @author hanfeili * */ public class MainActivity extends Activity { ImageView imageview; Button load; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); imageview = (ImageView) findViewById(R.id.imageView1); load = (Button) findViewById(R.id.load); load.setOnClickListener(new OnClickListener() { public void onClick(View v) { //因为现在我们的代码是针对4.0以后的系统开发的,所以网络操作必须在子线程中操作 new Thread(){ public void run(){ try { URL url = new URL("http://www.baidu.com/img/baidu_sylogo1.gif"); //通过url的openConnnection获得一个HttpURLConnection 网络连接 HttpURLConnection conn = (HttpURLConnection)url.openConnection(); //获得网络连接对应的网络资源的输入流 InputStream input = conn.getInputStream(); //通过输入流转换一个Bitmap图片对象 Bitmap bitmap = BitmapFactory.decodeStream(input); Log.i("TEST", "-----Thread.run()-----------"); //在子线程中不能操作在主线程中创建的ImageView组件,所以必须在主线程中操作,我们就使用了我们以前学习的Handler来实现 //子线程与主线程的通信 //imageview.setImageBitmap(bitmap); Message msg = Message.obtain(); msg.obj = bitmap; handler.sendMessage(msg); } catch (Exception e) { e.printStackTrace(); } } }.start(); } }); } Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { Log.i("handler", "-----handleMessage-----------"); Bitmap bitmap = (Bitmap)msg.obj; imageview.setImageBitmap(bitmap); } }; }
提交请求和获得响应
package org.fkjava.file2; import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; import android.app.Activity; import android.graphics.Bitmap; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; /** * 获得网络上的图片数据, 并显示出来 * @author hanfeili * */ public class MainActivity extends Activity { TextView tv; Button load; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv = (TextView) findViewById(R.id.textView1); load = (Button) findViewById(R.id.load); load.setOnClickListener(new OnClickListener() { public void onClick(View v) { //因为现在我们的代码是针对4.0以后的系统开发的,所以网络操作必须在子线程中操作 new Thread(){ public void run(){ try { URL url = new URL("http://192.168.10.222:8080/AndroidWeb/helloServlet?name=admin&pass=123456"); //通过url的openConnnection获得一个HttpURLConnection 网络连接 HttpURLConnection conn = (HttpURLConnection)url.openConnection(); //获得网络连接对应的网络资源的输入流 BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream())); StringBuilder sb = new StringBuilder(); String len = null; while((len = br.readLine())!= null){ sb.append(len); } br.close(); conn.disconnect(); Message msg = Message.obtain(); msg.obj = sb.toString(); handler.sendMessage(msg); } catch (Exception e) { e.printStackTrace(); } } }.start(); } }); } Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { String reMsg = (String)msg.obj; tv.setText(reMsg); } }; }
2-HttpClient
HTTP 协议可能是现在 Internet 上使用得最多、最重要的协议了,越来越多的 Java 应用程序需要直接通过 HTTP 协议来访问网络资源。虽然在 JDK 的 java.net包中已经提供了访问 HTTP 协议的基本功能,但是对于大部分应用程序来说,JDK 库本身提供的功能还不够丰富和灵活。 HttpClient 是 Apache Jakarta Common 下的子项目,用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议。HttpClient 已经应用在很多的项目中,最新版本为 HttpClient 4.2 (GA) 使用步骤: 1. 创建 HttpClient 的实例。 2. 创建某种连接方法的实例,例如HttpPost(HttpGet)的构造函数中传入待连接的地址 3. 调用第一步中创建好的实例的 execute 方法来执行第二步中创建好的 method 实例 4. 读 response响应信息。 5. 释放连接。无论执行方法是否成功,都必须释放连接。 6. 对得到后的内容进行处理。
GET方式
 package org.fkjava.httpclient; import java.io.BufferedReader; import java.io.InputStreamReader; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.DefaultHttpClient; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.view.View; import android.view.View.OnClickListener; import android.widget.TextView; /** * 通过HttpClent 的get方式发送请求 * @authorhanfeili * */ publicclass MainActivity extends Activity implements OnClickListener{ TextView tv; @Override publicvoid onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv = (TextView)findViewById(R.id.tv); findViewById(R.id.get).setOnClickListener(this); } Handlerhandler = new Handler(){ publicvoid handleMessage(Message msg) { tv.setText((String)msg.obj); } }; publicvoid onClick(View v) { new Thread(){ publicvoid run(){ //创建一个HttpClient实例 HttpClient client = new DefaultHttpClient(); //创建一个请求方式对象(GET方式) HttpGet get = new HttpGet("http://www.webxml.com.cn/webservices/weatherwebservice.asmx/getSupportCity?byProvinceName=广东"); try { //执行请求,返回HttpResponse HttpResponse response = client.execute(get); //判断是否正常响应 (是不是 等于 200 ok) if(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK){ //通过响应获得服务器端 写出的数据 HttpEntity entity = response.getEntity(); //IO操作 BufferedReader br = new BufferedReader(new InputStreamReader(entity.getContent())); StringBuilder sb = new StringBuilder(); String len = null; while((len = br.readLine())!= null){ sb.append(len); } br.close(); //操作完成,释放连接 get.abort(); Message msg = Message.obtain(); msg.obj = sb.toString(); handler.sendMessage(msg); } } catch (Exception e) { e.printStackTrace(); } } }.start(); } }
POST方式
 package org.fkjava.httpclient; import java.io.BufferedReader; import java.io.InputStreamReader; import java.util.ArrayList; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.NameValuePair; import org.apache.http.client.HttpClient; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpPost; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.message.BasicNameValuePair; import org.apache.http.protocol.HTTP; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.view.View; import android.view.View.OnClickListener; import android.widget.TextView; /** * 通过HttpClent 的Post方式发送请求 * @authorhanfeili * */ publicclass MainActivity extends Activity implements OnClickListener{ TextView tv; @Override publicvoid onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv = (TextView)findViewById(R.id.tv); findViewById(R.id.get).setOnClickListener(this); } Handlerhandler = new Handler(){ publicvoid handleMessage(Message msg) { tv.setText((String)msg.obj); } }; publicvoid onClick(View v) { new Thread(){ publicvoid run(){ //创建一个HttpClient实例 HttpClient client = new DefaultHttpClient(); //创建一个请求方式对象(POST方式) HttpPost post =new HttpPost("http://www.webxml.com.cn/webservices/weatherwebservice.asmx/getSupportCity"); //创建一个参数包装对象 ArrayList params = new ArrayList(); //设置请求参数 params.add(new BasicNameValuePair("byProvinceName", "湖南")); try { //将参数进行编码,并绑定到post对象中 post.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8)); //执行请求,返回HttpResponse HttpResponse response = client.execute(post); //判断是否正常响应 (是不是 等于 200 ok) if(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK){ //通过响应获得服务器端 写出的数据 HttpEntity entity = response.getEntity(); //IO操作 BufferedReader br = new BufferedReader(new InputStreamReader(entity.getContent())); StringBuilder sb = new StringBuilder(); String len = null; while((len = br.readLine())!= null){ sb.append(len); } br.close(); //操作完成,释放连接 post.abort(); Message msg = Message.obtain(); msg.obj = sb.toString(); handler.sendMessage(msg); } } catch (Exception e) { e.printStackTrace(); } } }.start(); } }
EntityUtils的使用
package org.fkjava.httpclient; import java.io.BufferedReader; import java.io.InputStreamReader; import java.util.ArrayList; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.NameValuePair; import org.apache.http.client.HttpClient; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpPost; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.message.BasicNameValuePair; import org.apache.http.protocol.HTTP; import org.apache.http.util.EntityUtils; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.view.View; import android.view.View.OnClickListener; import android.widget.TextView; /** * 通过HttpClent 的Post方式发送请求 * @author hanfeili * */ public class MainActivity extends Activity implements OnClickListener{ TextView tv; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv = (TextView)findViewById(R.id.tv); findViewById(R.id.get).setOnClickListener(this); } Handler handler = new Handler(){ public void handleMessage(Message msg) { tv.setText((String)msg.obj); } }; public void onClick(View v) { new Thread(){ public void run(){ //创建一个HttpClient实例 HttpClient client = new DefaultHttpClient(); //创建一个请求方式对象(POST方式) HttpPost post =new HttpPost("http://www.webxml.com.cn/webservices/weatherwebservice.asmx/getSupportCity"); //创建一个参数包装对象 ArrayList params = new ArrayList(); //设置请求参数 params.add(new BasicNameValuePair("byProvinceName", "湖南")); try { //将参数进行编码,并绑定到post对象中 post.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8)); //执行请求,返回HttpResponse HttpResponse response = client.execute(post); //判断是否正常响应 (是不是 等于 200 ok) if(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK){ //使用EntityUtils将response响应中的数据转换成字符串返回 String sb = EntityUtils.toString(response.getEntity()); post.abort(); Message msg = Message.obtain(); msg.obj = sb; handler.sendMessage(msg); } } catch (Exception e) { e.printStackTrace(); } } }.start(); } }
文件上传
 package org.fkjava.httpclient; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.InputStreamReader; import java.util.ArrayList; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.NameValuePair; import org.apache.http.client.HttpClient; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.FileEntity; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.message.BasicNameValuePair; import org.apache.http.protocol.HTTP; import org.apache.http.util.EntityUtils; import android.app.Activity; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.os.Message; import android.view.View; import android.view.View.OnClickListener; import android.widget.TextView; /** * 通过HttpClent 的Post方式进行文件上传 * * @author hanfeili * */ public class MainActivity extends Activity implements OnClickListener { TextView tv; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv = (TextView) findViewById(R.id.tv); findViewById(R.id.get).setOnClickListener(this); } Handler handler = new Handler() { public void handleMessage(Message msg) { tv.setText((String) msg.obj); } }; public void onClick(View v) { new Thread() { public void run() { // 创建一个HttpClient实例 HttpClient client = new DefaultHttpClient(); // 创建一个请求方式对象(POST方式) HttpPost post = new HttpPost("http://192.168.10.222:8080/AndroidWeb/upServlet"); //需要上传的文件 File upFile = new File(Environment.getExternalStorageDirectory()+ File.separator + "7.jpg"); //包装需要上传的文件,并指定数据类型 FileEntity fileEntity = new FileEntity(upFile, "binary/octet-stream"); post.setEntity(fileEntity); try { // 执行请求,返回HttpResponse HttpResponse response = client.execute(post); // 判断是否正常响应 (是不是 等于 200 ok) if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { // 使用EntityUtils将response响应中的数据转换成字符串返回 String sb = EntityUtils.toString(response.getEntity()); post.abort(); Message msg = Message.obtain(); msg.obj = sb; handler.sendMessage(msg); } } catch (Exception e) { e.printStackTrace(); } } }.start(); } }
服务器端代码
package org.fkjava.myweb; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.OutputStream; import java.nio.file.Files; import java.nio.file.Paths; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * 移动端访问web服务实例 web服务器端代码 * 文件上传服务器接收数据 */ @WebServlet("/fileUpload") public class FileUploadServlet extends HttpServlet { private static final long serialVersionUID = 1L; protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("---------文件上传开始-----------"); String savePath = this.getServletContext().getRealPath("images"); //jdk 1.7的方式进行文件保存 //参数1:输入流 //参数2:将输入流中数据保存的Paths指定的位置 Files.copy(request.getInputStream(), Paths.get(savePath+File.separator+"mm.jpg")); response.getWriter().println("ok"); System.out.println("---------文件上传结束-----------"); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } }
3-Socket
和java开发一模一样
4-SQLite数据库
SQLite大量的被用于手机,PDA,MP3播放器以及机顶盒设备。 下面列举了一些使用SQLite作为嵌入式服务器的应用: Mozilla Firefox使用SQLite作为数据库。 Mac计算机中的包含了多份SQLite的拷贝,用于不同的应用。 PHP将SQLite作为内置的数据库。 Skype客户端软件在内部使用SQLite。 SymbianOS(智能手机操作平台的领航)内置SQLite。 AOL邮件客户端绑定了SQLite。 Solaris 10在启动过程中需要使用SQLite。 McAfee杀毒软件使用SQLite。 iPhones使用SQLite。 嵌入式关系型SQLite介绍
字段类型
SQLite3支持 NULL、 INTEGER、 REAL(浮点数字)、 TEXT(字符串文本)和 BLOB(二进制对象)数据类型,虽然它支持的类型只有五种, 但实际上sqlite3也接受varchar(n)、char(n)、decimal(p,s) 等数据类型,但是在运算或保存时会转成对应的五种数据类型。 SQLite3最大的特点是你可以保存任何类型的数据到任何字段中。 例如:可以在Integer字段中存放字符串,或在布尔型字段中存放浮点数,或在字符型字段中存放日期型值。 但有一种情况例外:定义为INTEGER PRIMARY KEY的字段只能存储64位整数。另外, SQLite3在解析CREATE TABLE 语句时,会忽略 CREATE TABLE 语句中跟在字段名后面的数据类型信息。
数据库存储位置
 默认存储在 data/data//databases/ 也可以指定存储位置(例如sdcard)
SQLite-API方式增删改查
使用Android 提供的API进行操作 简单,方便 但是复杂的操作比较麻烦,(子查询...) 插入 SQLiteDatabase.insert(); 查询 SQLiteDatabase.query(); 更新 SQLiteDatabase.update(); 删除 SQLiteDatabase.delete();
布局文件
 LinearLayoutxmlns: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" android:orientation="vertical"> TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:text="学员管理程序(API)" android:textColor="#ff0000" android:textSize="30dip" tools:context=".MainActivity"/> EditText android:id="@+id/id" android:layout_width="match_parent" android:layout_height="wrap_content" android:ems="10" android:hint="请输入学员id进行查询" android:inputType="number"/> EditText android:id="@+id/name" android:layout_width="match_parent" android:layout_height="wrap_content" android:ems="10" android:hint="请输入学员姓名" android:inputType="textPersonName"> requestFocus/> EditText> EditText android:id="@+id/phone" android:layout_width="match_parent" android:layout_height="wrap_content" android:ems="10" android:hint="请输入学员电话" android:inputType="phone"/> EditText android:id="@+id/address" android:layout_width="match_parent" android:layout_height="wrap_content" android:ems="10" android:hint="请输入学员家庭地址" android:inputType="textPostalAddress"/> EditText android:id="@+id/birthday" android:layout_width="match_parent" android:layout_height="wrap_content" android:ems="10" android:hint="请输入学员生日" android:inputType="date"/> LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal"> Button android:id="@+id/save" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="新增"/> Button android:id="@+id/find" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="查询"/> Button android:id="@+id/update" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="更新"/> Button android:id="@+id/delete" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="删除"/> LinearLayout> LinearLayout>
SQLiteOpenHelper
package org.fkjava.db; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase.CursorFactory; import android.database.sqlite.SQLiteOpenHelper; import android.util.Log; /** * 数据库操作助手类 * 步骤: * 1:继承SQLiteOpenHelper * 2: 定义构造器调用父类的构造器(因为父类没有提供无参数构造器,所以必须显示的写调用父类那个构造器) * 3:重写父类的抽象方法 * @authorhanfeili * */ publicclass DBHelper extends SQLiteOpenHelper{ privatestaticfinal String TAG = "DBHelper"; publicstaticfinalintVERSION = 1; publicstaticfinal String DB_NAME = "stu.db"; publicstaticfinal String TABLE_NAME = "stuinfo"; publicstaticfinal String ID = "id"; publicstaticfinal String NAME = "name"; publicstaticfinal String PHONE = "phone"; publicstaticfinal String ADDRESS = "address"; publicstaticfinal String BRITHDAY = "brithday"; /** * 创建DBHelper类实例 * @param context 上下文 * @param name 数据库名称 */ public DBHelper(Context context,String dbname){ this(context,dbname,null,VERSION); } /** * 创建DBHelper类实例 * @param context 上下文 * @param name 数据库名称 * @param factory 游标工厂(暂时不需要 给 null) * @param version 数据库版本号 */ public DBHelper(Context context, String name, CursorFactory factory,int version) { super(context, name, factory, version); } /** * 初始化方法 * 写 数据库 表 的创建代码 */ @Override publicvoid onCreate(SQLiteDatabase db) { StringBuilder sql = new StringBuilder("create table stuinfo("); sql.append("id integer primary key autoincrement,").append("name varchar(20),"); sql.append("phone varchar(12),").append("address varchar(50),"); sql.append("brithday varchar(12)").append(")"); Log.i(TAG, "--onCreate--------------"+sql.toString()); //执行sql语句(创建数据库表) db.execSQL(sql.toString()); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { db.execSQL("DROP TABLE IF EXISTS student"); onCreate(db); //db.execSQL("alter table student add address varchar(20) null"); } }
MainActivity测试类
package org.fkjava.sqlite; import org.fkjava.db.DBHelper; import android.app.Activity; import android.content.ContentValues; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; /** * API方式进行增删改查 * @authorhanfeili * */ publicclass MainActivity extends Activity implements OnClickListener { Button add, find, update, delete; EditText userId, userName, userPhone, userAddress, brithday; @Override publicvoid onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); userId = (EditText) findViewById(R.id.userId); userName = (EditText) findViewById(R.id.userName); userPhone = (EditText) findViewById(R.id.phone); userAddress = (EditText) findViewById(R.id.address); brithday = (EditText) findViewById(R.id.brithday); add = (Button) findViewById(R.id.add); find = (Button) findViewById(R.id.find); update = (Button) findViewById(R.id.update); delete = (Button) findViewById(R.id.delete); add.setOnClickListener(this); find.setOnClickListener(this); update.setOnClickListener(this); delete.setOnClickListener(this); } SQLiteDatabase db =null; ContentValues values = null; intcount; publicvoid onClick(View v) { //创建DBHelper(参数1:上下文,参数2:数据库名称[后缀db 可以没有]) DBHelper dbHelper = new DBHelper(this,DBHelper.DB_NAME); switch (v.getId()) { case R.id.add: //获得一个可写的数据库连接 db = dbHelper.getWritableDatabase(); values = new ContentValues(); //key 对应 数据库表 字段名 //value 就是需要插入key对应的字段中的数据 values.put(DBHelper.NAME, userName.getText().toString()); values.put(DBHelper.PHONE, userPhone.getText().toString()); values.put(DBHelper.ADDRESS, userAddress.getText().toString()); values.put(DBHelper.BRITHDAY, brithday.getText().toString()); /** * 参数1:需要插入数据的 表名 * 参数2: 为了防止当参数3没有数据的时候报SQL语法错误,所以可以写一个参数1表中存在的字段名。 * 参数3:需要插入的数据 * 执行成功将返回 一个long的行号 */ long rowId = db.insert(DBHelper.TABLE_NAME, DBHelper.NAME, values); Toast.makeText(this, (rowId>0?"新增成功"+rowId:"新增失败"), Toast.LENGTH_LONG).show(); userId.setText(rowId+""); break; case R.id.find: db = dbHelper.getReadableDatabase(); //select name from table where id = ? /** * 查询API * 参数1:需要查询的表 * 参数2:需要查询的字段 * 参数3:查询条件 * 参数4:条件值 * 参数5:组函数 * 参数6:having * 参数7:orderBy */ Cursor cursor = db.query(DBHelper.TABLE_NAME, new String[]{ DBHelper.ID, DBHelper.NAME, DBHelper.PHONE, DBHelper.ADDRESS, DBHelper.BRITHDAY}, "id = ?", new String[]{userId.getText().toString()}, null, null, null); //Cursor表示查询的结果集 //moveToNext()判断结果集还有没有下一条记录 while(cursor.moveToNext()){ //cursor.getColumnIndex(DBHelper.ID) 获得参数指定对应表的 列的下标 //cursor.getXxx()获得给定列下标对应的值 int id = cursor.getInt(cursor.getColumnIndex(DBHelper.ID)); String name = cursor.getString(cursor.getColumnIndex(DBHelper.NAME)); String phone = cursor.getString(cursor.getColumnIndex(DBHelper.PHONE)); String address = cursor.getString(cursor.getColumnIndex(DBHelper.ADDRESS)); String drithday = cursor.getString(cursor.getColumnIndex(DBHelper.BRITHDAY)); Toast.makeText(this, id+"-"+name+"-"+phone+"-"+address+"-"+drithday, Toast.LENGTH_LONG).show(); userName.setText(name); userPhone.setText(phone); userAddress.setText(address); brithday.setText(drithday); } cursor.close(); break; case R.id.update: db = dbHelper.getWritableDatabase(); values = new ContentValues(); values.put(DBHelper.NAME, userName.getText().toString()); values.put(DBHelper.PHONE, userPhone.getText().toString()); values.put(DBHelper.ADDRESS, userAddress.getText().toString()); values.put(DBHelper.BRITHDAY, brithday.getText().toString()); /** * 更新API * 参数1:需要更新数据的表名 * 参数2:需要更新的数据(key[列名] = value[数据]) * 参数3:更新条件 * 参数4:条件值 */ count = db.update(DBHelper.TABLE_NAME, values, "id = ?", new String[]{userId.getText().toString()}); Toast.makeText(this, (count>0?"更新成功"+count:"更新失败"), Toast.LENGTH_LONG).show(); break; case R.id.delete: db = dbHelper.getWritableDatabase(); /** * 删除API * 参数1:需要删除数据的表 * 参数2:更新条件 * 参数3:条件值 */ count = db.delete(DBHelper.TABLE_NAME, "id = ?", new String[]{userId.getText().toString()}); Toast.makeText(this, (count>0?"删除成功"+count:"删除失败"), Toast.LENGTH_LONG).show(); break; } } }
SQlite-代码方式增删改查
package org.fkjava.sqlite; import org.fkjava.db.DBHelper; import android.app.Activity; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.os.Bundle; import android.os.SystemClock; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; /** * 代码方式进行增删改查 * @authorhanfeili * */ public class MainActivity extends Activity implements OnClickListener { Button add, find, update, delete,test; EditText userId, userName, userPhone, userAddress, brithday; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); userId = (EditText) findViewById(R.id.userId); userName = (EditText) findViewById(R.id.userName); userPhone = (EditText) findViewById(R.id.phone); userAddress = (EditText) findViewById(R.id.address); brithday = (EditText) findViewById(R.id.brithday); add = (Button) findViewById(R.id.add); find = (Button) findViewById(R.id.find); update = (Button) findViewById(R.id.update); delete = (Button) findViewById(R.id.delete); test = (Button) findViewById(R.id.test); add.setOnClickListener(this); find.setOnClickListener(this); update.setOnClickListener(this); delete.setOnClickListener(this); test.setOnClickListener(this); } SQLiteDatabase db = null; public void onClick(View v) { DBHelper dbHelper = new DBHelper(this, DBHelper.DB_NAME); switch (v.getId()) { case R.id.add: db = dbHelper.getWritableDatabase(); /** * 参数1: 需要执行的SQL语句 参数2:给SQL语句的值(需要存储的值) */ db.execSQL("insert into " + DBHelper.TABLE_NAME + "(name,phone,address,brithday) values(?,?,?,?)", new Object[] { userName.getText().toString(), userPhone.getText().toString(), userAddress.getText().toString(), brithday.getText().toString() }); Toast.makeText(this, "新增成功", Toast.LENGTH_LONG).show(); break; case R.id.find: db = dbHelper.getReadableDatabase(); String uid = userId.getText().toString(); Cursor cursor = null; if (!"".equals(uid)) { /** * 参数1:查询语句 参数2:条件值 */ cursor = db.rawQuery("select * from stuinfo where id=?",new String[] { uid }); if(cursor.moveToFirst()){//移动指针到第一条记录,如果存在第一条记录将返回true int id = cursor.getInt(cursor.getColumnIndex(DBHelper.ID)); String name = cursor.getString(cursor.getColumnIndex(DBHelper.NAME)); String phone = cursor.getString(cursor.getColumnIndex(DBHelper.PHONE)); String address = cursor.getString(cursor.getColumnIndex(DBHelper.ADDRESS)); String drithday = cursor.getString(cursor.getColumnIndex(DBHelper.BRITHDAY)); userName.setText(name); userPhone.setText(phone); userAddress.setText(address); brithday.setText(drithday); Toast.makeText(this, "根据ID获得的记录是:"+id+"-"+name+"-"+phone+"-"+address+"-"+drithday, Toast.LENGTH_LONG).show(); } } else { cursor = db.rawQuery("select * from stuinfo ", null); while(cursor.moveToNext()){//移动指针到 下 一条记录,如果存在下一条记录将返回true int id = cursor.getInt(cursor.getColumnIndex(DBHelper.ID)); String name = cursor.getString(cursor.getColumnIndex(DBHelper.NAME)); String phone = cursor.getString(cursor.getColumnIndex(DBHelper.PHONE)); String address = cursor.getString(cursor.getColumnIndex(DBHelper.ADDRESS)); String drithday = cursor.getString(cursor.getColumnIndex(DBHelper.BRITHDAY)); Toast.makeText(this, cursor.getCount()+"记录集:"+id+"-"+name+"-"+phone+"-"+address+"-"+drithday, Toast.LENGTH_LONG).show(); } } //关闭游标 cursor.close(); break; case R.id.update: db = dbHelper.getWritableDatabase(); db.execSQL("update stuinfo set name=? where id=?", new String[]{userName.getText().toString(),userId.getText().toString()}); Toast.makeText(this, "更新成功", Toast.LENGTH_LONG).show(); break; case R.id.delete: db = dbHelper.getWritableDatabase(); db.execSQL("delete from stuinfo where id=?", new String[]{userId.getText().toString()}); Toast.makeText(this, "删除成功", Toast.LENGTH_LONG).show(); break; case R.id.test: db = dbHelper.getWritableDatabase(); //SystemClock 在android中获得系统当前时间的方法 long startTime = SystemClock.currentThreadTimeMillis(); for(int i =0;i db.execSQL("insert into stuinfo(name,phone,address,brithday) values(?,?,?,?)", new Object[]{"admin_"+i,"1342221856"+i,"gdgz","2012-07-21"}); } long endTime = SystemClock.currentThreadTimeMillis(); System.out.println("普通方式:"+(endTime-startTime)); System.out.println("-------------------------------"); startTime = SystemClock.currentThreadTimeMillis(); db.beginTransaction();//开启事务 for(int i =0;i db.execSQL("insert into stuinfo(name,phone,address,brithday) values(?,?,?,?)", new Object[]{"tom_"+i,"1342221856"+i,"gdgz","2012-07-21"}); } db.setTransactionSuccessful();//设置事务成功状态 db.endTransaction(); //提交事务(如果没有执行setTransactionSuccessful,那么事务将回滚) endTime = SystemClock.currentThreadTimeMillis(); System.out.println("事务批处理方式:"+(endTime-startTime)); break; } } }
事务
db = dbHelper.getWritableDatabase(); //SystemClock 在android中获得系统当前时间的方法 long startTime = SystemClock.currentThreadTimeMillis(); for(int i =0;i db.execSQL("insert into stuinfo(name,phone,address,brithday) values(?,?,?,?)", new Object[]{"admin_"+i,"1342221856"+i,"gdgz","2012-07-21"}); } long endTime = SystemClock.currentThreadTimeMillis(); System.out.println("普通方式:"+(endTime-startTime)); System.out.println("-------------------------------"); startTime = SystemClock.currentThreadTimeMillis(); db.beginTransaction();//开启事务 for(int i =0;i db.execSQL("insert into stuinfo(name,phone,address,brithday) values(?,?,?,?)", new Object[]{"tom_"+i,"1342221856"+i,"gdgz","2012-07-21"}); } db.setTransactionSuccessful();//设置事务成功状态 db.endTransaction(); //提交事务(如果没有执行setTransactionSuccessful,那么事务将回滚) endTime = SystemClock.currentThreadTimeMillis(); System.out.println("事务批处理方式:"+(endTime-startTime));
存储大数据类型
package org.fkjava.sqlite2; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import org.fkjava.db.DBHelper; import android.app.Activity; import android.content.ContentValues; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.graphics.Bitmap; import android.graphics.Bitmap.CompressFormat; import android.graphics.BitmapFactory; import android.os.Bundle; import android.view.View; import android.widget.ImageView; import android.widget.TextView; public class MainActivity extends Activity { private static final String TAG = "MainActivity"; TextView show = null; ImageView imageView = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); show = (TextView)findViewById(R.id.show); imageView = (ImageView)findViewById(R.id.imageView1); } public void myOnClick(View v) throws IOException { DBHelper dbHelper = new DBHelper(this); SQLiteDatabase db = dbHelper.getWritableDatabase(); //获得assets目录中资源 InputStream in = this.getAssets().open("cls.jpg"); //将流转换从Bitmap数据 Bitmap img = BitmapFactory.decodeStream(in); ByteArrayOutputStream out = new ByteArrayOutputStream(); //将bitmap对应 的图片数据压缩的ByteArrayOutputStream流中 img.compress(CompressFormat.JPEG, 100, out); ContentValues values = new ContentValues(); values.put("t_name", "tttttt"); //获得ByteArrayOutputStream中保存的图片字节数据 values.put("t_images", out.toByteArray()); long rowId = db.insert("stu_info","t_name", values); show.setText("保存成功返回的rowId:"+rowId); db.close(); } public void myOnClick2(View v) { DBHelper dbHelper = new DBHelper(this); SQLiteDatabase db = dbHelper.getWritableDatabase(); Cursor cursor = db.query("stu_info", new String[]{"t_name","t_images"}, "id=?",new String[]{"901"}, null, null, null); if(cursor.moveToFirst()){ String name = cursor.getString(cursor.getColumnIndex("t_name")); //获得blob字段的数据使用getBlob(),返回一个byte[]数据 byte[] buffer = cursor.getBlob(cursor.getColumnIndex("t_images")); //将byte[]数据还原成Bitmap对象 Bitmap img = BitmapFactory.decodeByteArray(buffer, 0, buffer.length); //设置到imageview上显示 imageView.setImageBitmap(img); show.setText(name); } cursor.close(); db.close(); } }
命令行操作android中的SQLite数据库
需要在系统path中配置 SDK的 tools 和 platform-tools  SQLite数据库操作步骤:  如果没有配置环境变量操作如下: 
opendir failed, Permission denied

Cursor游标常用方法
android.database.Cursor 常用方法: boolean moveToPosition(position)将指针移动到某记录 getColumnIndex(“ColumnName”) 按列名获取对应的下标 getXxx 获取Xxx对应类型数据 int getCount() 获取记录总数 boolean requery() 重新查询 boolean isAfterLast() 指针是否在末尾 boolean isBeforeFirst() 指针是否在开始位置 boolean isFirst() 是否是第一条记录 boolean isLast() 是否是最后一条记录 boolean moveToFirst() 移动指针到第一行 boolean moveToLast() 移动指针到最后一行 boolean moveToNext() 移动指针到下一行
JavaJDBC操作SQLite数据库
import java.sql.*; //导入 sqlitejdbc-v056.jar包 //下载地址:http://www.zentus.com/sqlitejdbc/index.html import org.sqlite.JDBC; /** * 测试连接SQLite数据库实例代码 * * @author hanfei.li * @since Jul 1, 2010 */ public class SQLiteDemo { public static void main(String[] args) { try { //sqlite数据库文件夹存储位置 String fileName = "c:/sqlitedb.db"; Class.forName("org.sqlite.JDBC"); Connection conn = DriverManager.getConnection("jdbc:sqlite:"+ fileName); Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery("SELECT * FROM student"); while (rs.next()) { String id = rs.getString("id"); String name = rs.getString("name"); String sex = rs.getString("sex"); System.out.println("编号:" + id + " 名称:" + name + "性别:"+ sex); } conn.close(); } catch (Exception e) { System.out.println(e.getMessage()); System.out.println(e.toString()); } } }
11-ContentProvider和ContentResolver
使用ContentProvider只需要知道协议,同时这种方式是同步的,使用方便,类似操作数据库。 数据内容的供应者,是一个数据源,屏蔽了具体底层数据源的细节,在ContentProvider内部可以用Android支持的任何手段进行数据的存储和操作。当应用之间需要共享数据时,就可以通过ContentProvider为需要共享的数据定义一个URI。然后当别的应用程序要对数据进行增删改查时,只需要从当前上下文对象获得ContentResolver(内容解析器)传入相应的URI就可以了完成共享数据的操作。 ContentProvider 主要负责 1、组织应用程序的数据; 2、向其他应用程序提供数据; ContentResolver 主要负责 1、获取ContentProvider提供的数据; 2、修改/添加/删除/更新数据等;
ContentProvider实现和调用步骤
实现 数据暴露的ContentProvider 类 步骤: 1 :写一个类继承 ContentProvider 抽象类 2: 重写 需要暴露给第三方应用调用的方法  onCreate() 初始化方法,在应用程序安装的时候调用一次 如果需要提供新增方法给第三方应用需要 重写 insert()方法 如果需要提供查询方法给第三方应用需要 重写 query()方法 。。。 3:在AndroidManifest.xml注册 需要暴露数据的ContentProvider providerandroid:name="org.fkjava.db.UserContentProvider" android:authorities="org.fkjava.usercontentprovider"/> content://org.fkjava.usercontentprovider/stu 4:第三方应用调用 通过 this.getContentResolver().insert(uri ,,)调用暴露的新增方法 通过 this.getContentResolver().query(uri ,,)调用暴露的查询方法 。。。
Uri代码
通过Uri判断具体是什么操作,是否允许请求的操作 static { //UriMatcher 相当是一个uri容器,当有第三方请求过来的时候将请求的带的uri与UriMatcher中的所有uri进行匹配,匹配成功的返回第三部分值,如果没有一个匹配的将返回 -1 (NO_MATCH) uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); // http://www.fkjava.org/user.html // content://org.fkjava.usercontentprovider/user uriMatcher.addURI(authorities, "user", USER); // content://org.fkjava.usercontentprovider/user/8 // #表示 匹配id 部分 * 表示匹配任何数据 uriMatcher.addURI(authorities, "user/#", USER_ID); } //uri匹配实例 @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { db = dbHelper.getReadableDatabase(); // 当调用某个操作的时候,如果第三方应用传递的uri与uriMatcher中的某uri匹配的时候将返回 //uriMatcher.addURI(authorities, "user/#", USER_ID)方法的第3个参数部分,如果没有与任何一个uri匹配将返回 -1 (UriMatcher.NO_MATCH) if(uriMatcher.match(uri) == USER){ cursor = db.query(...); }elseif(uriMatcher.match(uri) == USER_ID){ //从uri上解析id数据 long id = ContentUris.parseId(uri); String where = " id = "+id; cursor = db.query(...); } returncursor; }
代码
DBHelper类代码
package org.fkjava.db; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase.CursorFactory; import android.database.sqlite.SQLiteOpenHelper; public class DBHelper extends SQLiteOpenHelper{ public static final String TABLE_NAME = "user"; public static final String ID = "id"; public static final String NAME = "name"; public static final String PHONE = "phone"; public static final String ADDRESS = "address"; public static final String BRITHDAY = "brithday"; public DBHelper(Context context) { super(context, "userDB.db", null, 1); } @Override public void onCreate(SQLiteDatabase db) { StringBuilder sql = new StringBuilder("create table user("); sql.append("id integer primary key autoincrement,").append("name varchar(20),"); sql.append("phone varchar(12),").append("address varchar(50),"); sql.append("brithday varchar(12)").append(")"); db.execSQL(sql.toString()); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } }
ContentProvider类代码
package org.fkjava.db; import android.content.ContentProvider; import android.content.ContentResolver; import android.content.ContentUris; import android.content.ContentValues; import android.content.UriMatcher; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.net.Uri; import android.util.Log; /** * 为了提供Uesr表数据给第三方应用程序使用 * * @author hanfeili * */ public class UserContentProvider extends ContentProvider { private static final String TAG = "UserContentProvider"; // 协议 private final static String authorities = "org.fkjava.usercontentprovider"; private final static int USER = 1; private final static int USER_ID = 2; static UriMatcher uriMatcher; static { uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); // http://www.fkjava.org/user.html // content://org.fkjava.usercontentprovider/user uriMatcher.addURI(authorities, "user", USER); // content://org.fkjava.usercontentprovider/user/8 // #表示 匹配id 部分 * 表示匹配任何数据 uriMatcher.addURI(authorities, "user/#", USER_ID); } DBHelper dbHelper =null; SQLiteDatabase db =null; Cursor cursor = null; long rowID = 0; @Override public boolean onCreate() { Log.i(TAG, "-------onCreate----------"); dbHelper = new DBHelper(this.getContext()); return false; } @Override public Uri insert(Uri uri, ContentValues values) { Log.i(TAG, "-------insert----------"+uri.toString()); db = dbHelper.getWritableDatabase(); //content://org.fkjava.usercontentproviderg/user Log.i(TAG, "----uriMatcher.match------ "+uriMatcher.match(uri)); if(uriMatcher.match(uri) == USER){ rowID = db.insert(DBHelper.TABLE_NAME, DBHelper.NAME, values); } //content://org.fkjava.usercontentproviderg/user/8 return ContentUris.withAppendedId(uri, rowID); } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { Log.i(TAG, "-------query----------"+uri); db = dbHelper.getReadableDatabase(); if(uriMatcher.match(uri) == USER){ cursor = db.query(DBHelper.TABLE_NAME, projection, selection, selectionArgs, null, null, sortOrder); }else if(uriMatcher.match(uri) == USER_ID){ //从uri上解析id数据 long id = ContentUris.parseId(uri); String where = " id = "+id; if(selection != null && !"".equals(selection)){ where +=" and "+ selection; } cursor = db.query(DBHelper.TABLE_NAME, projection, where, selectionArgs, null, null, sortOrder); } return cursor; } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { Log.i(TAG, "-------update----------"+uri); db = dbHelper.getWritableDatabase(); if(uriMatcher.match(uri) == USER_ID){ return db.update(DBHelper.TABLE_NAME, values, " id = ?",new String[]{ContentUris.parseId(uri)+""} ); } return 0; } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { Log.i(TAG, "-------delete----------"+uri); db = dbHelper.getWritableDatabase(); if(uriMatcher.match(uri) == USER_ID){ return db.delete(DBHelper.TABLE_NAME, " id = ?", new String[]{ContentUris.parseId(uri)+""}); } return 0; } // 目前可以不用管了,告诉系统操作数据是批量还是单条 @Override public String getType(Uri uri) { Log.i(TAG, "-------getType----------"); int match = uriMatcher.match(uri) ; switch (match){ case USER: return "vnd.android.cursor.dir/user"; case USER_ID: return "vnd.android.cursor.item/user"; } return null; } }
第三方调用端代码
package org.fkjava.cp; import org.fkjava.db.DBHelper; import android.app.Activity; import android.content.ContentValues; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; public class MainActivity extends Activity implements OnClickListener{ private static final String TAG = "MainActivity"; EditText stuName,phone,address,brithday,userId; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TextView show = (TextView)findViewById(R.id.show); stuName = (EditText)findViewById(R.id.userName); phone = (EditText)findViewById(R.id.phone); address = (EditText)findViewById(R.id.address); brithday = (EditText)findViewById(R.id.brithday); userId = (EditText)findViewById(R.id.userId); Button add = (Button)findViewById(R.id.add); Button find = (Button)findViewById(R.id.find); Button update = (Button)findViewById(R.id.update); Button delete = (Button)findViewById(R.id.delete); add.setOnClickListener(this); find.setOnClickListener(this); update.setOnClickListener(this); delete.setOnClickListener(this); } ContentValues values=null; Uri uri = null; Cursor cursor= null; @Override public void onClick(View v) { switch (v.getId()) { case R.id.add: uri = Uri.parse("content://org.fkjava.usercontentprovider/user"); values = new ContentValues(); values.put(DBHelper.NAME, stuName.getText().toString()); values.put(DBHelper.PHONE, phone.getText().toString()); values.put(DBHelper.ADDRESS, address.getText().toString()); values.put(DBHelper.BRITHDAY, brithday.getText().toString()); Uri returnUri = this.getContentResolver().insert(uri, values); Log.i(TAG, "insert---"+returnUri.toString()); break; case R.id.find: String uid = userId.getText().toString(); boolean flag = true; if(uid !=null && !"".equals(uid)){ uri = Uri.parse("content://org.fkjava.usercontentprovider/user/"+uid); cursor = this.getContentResolver().query(uri, null, " name=?", new String[]{stuName.getText().toString()}, null); }else{ uri = Uri.parse("content://org.fkjava.usercontentprovider/user"); cursor = this.getContentResolver().query(uri, null, null, null, " id desc "); flag = false; } while(cursor.moveToNext()){ int ids = cursor.getInt(cursor.getColumnIndex(DBHelper.ID)); String names = cursor.getString(cursor.getColumnIndex(DBHelper.NAME)); String phones = cursor.getString(cursor.getColumnIndex(DBHelper.PHONE)); String addresss = cursor.getString(cursor.getColumnIndex(DBHelper.ADDRESS)); String brithdays = cursor.getString(cursor.getColumnIndex(DBHelper.BRITHDAY)); Toast.makeText(this, ids+"-"+names+"-"+phones+"-"+addresss+"-"+brithdays, Toast.LENGTH_SHORT).show(); if(flag){ userId.setText(ids+""); stuName.setText(names); phone.setText(phones); address.setText(addresss); brithday.setText(brithdays); } } break; case R.id.update: Uri uri =Uri.parse("content://org.fkjava.usercontentprovider/user/"+userId.getText().toString()); values = new ContentValues(); values.put(DBHelper.NAME, stuName.getText().toString()); values.put(DBHelper.PHONE, phone.getText().toString()); values.put(DBHelper.ADDRESS, address.getText().toString()); values.put(DBHelper.BRITHDAY, brithday.getText().toString()); int count = this.getContentResolver().update(uri, values, null, null); Toast.makeText(this, "更新影响["+count+"]行", Toast.LENGTH_SHORT).show(); break; case R.id.delete: Uri uri2 =Uri.parse("content://org.fkjava.usercontentprovider/user/"+userId.getText().toString()); int count2 = this.getContentResolver().delete(uri2, null, null); Toast.makeText(this, "删除影响["+count2+"]行", Toast.LENGTH_SHORT).show(); userId.setText(""); stuName.setText(""); phone.setText(""); address.setText(""); brithday.setText(""); break; } } }
数据变化监听
通知
//数据改变监听 通知 uri = Uri.parse("content://org.fkjava.usercontentprovider/user"); this.getContext().getContentResolver().notifyChange(uri, null);
监听
//注册感兴趣的uri ,当感兴趣的uri变化的时候将会执行项目的onChange方法 uri = Uri.parse("content://org.fkjava.usercontentprovider/user"); this.getContentResolver().registerContentObserver(uri, true, new ContentObserver(new Handler()) { //可以实现当数据变化的时候希望进行的操作 publicvoid onChange(boolean selfChange, Uri uri) { Cursor cursor = MainActivity.this.getContentResolver().query(uri, null,null, null, " id desc "); while(cursor.moveToNext()){ int ids = cursor.getInt(cursor.getColumnIndex("id")); String names = cursor.getString(cursor.getColumnIndex("name")); String phones = cursor.getString(cursor.getColumnIndex("phone")); String addresss = cursor.getString(cursor.getColumnIndex("address")); String brithdays = cursor.getString(cursor.getColumnIndex("brithday")); Log.i("---onChange监听的uri对应的数据有变化----",ids+"-"+names+"-"+phones+"-"+addresss+"-"+brithdays); } } });
13-JSON和XML解析
无论在PC还是移动端都有可能需要涉及数据的跨平台传输. 一般会选择XML 或者 JSON 推荐多使用JSON
XML
以前在java部分已经学习了SAX和DOM方式 今天学习一种android推荐的新的方式Pull方式 Dom是一次将文件内容全部载入内存,方便在内存中修改xml数据,但是占系统资源比较多。 SAX是基于事件的方式,读一行解析一行,每一次读一行都会产生一个事件。 PUll方式类型SAX也是基于事件的。  www.xmlpull.org
解析
RSS /** * 解析xml * /* facejava facejava]]> 20090909 http://www.facejava.org * * @return */ public List getChannel()throws Exception{ ArrayList channelList = null; Channel channel =null; //获得 assets目录中的 资源 InputStream in = this.getResources().getAssets().open("channel.xml"); //创建一个pull解析器 XmlPullParser pull = Xml.newPullParser(); //传递需要解析的 xml 数据 (以流的形式进行) ,并指定编码 pull.setInput(in, "utf-8"); //开始解析 (因为pull是基于事件的所以 这里会返回一个 节点对应的int类型值 来表示解析到什么位置) int key = pull.getEventType(); int i = 0; //判断解析是否到文档结束 while(key != XmlPullParser.END_DOCUMENT){ Log.i("key----", "key--"+(i++)+"-"+key); switch (key) {//循环判断当前解析到的 节点 位置 case XmlPullParser.START_DOCUMENT: //是不是文档开始节点 channelList = new ArrayList(); break; case XmlPullParser.START_TAG://是不是普通节点开始 if(pull.getName().equals("item")){//获取当前解析到的节点名称 channel = new Channel(); channel.setId(channelList.size()+1); //获取当前节点中的第一个属性 (从 0 开始) channel.setName(pull.getAttributeValue(0)); }elseif(pull.getName().equals("title")){ //获得当前节点的 文本内容 channel.setTitle(pull.nextText()); }elseif(pull.getName().equals("description")){ channel.setDescription(pull.nextText()); }elseif(pull.getName().equals("pubDate")){ channel.setPubDate(pull.nextText()); }elseif(pull.getName().equals("link")){ channel.setLink(pull.nextText()); } break; case XmlPullParser.END_TAG://是不是节点结束 if(pull.getName().equals("item")){ channelList.add(channel); } break; } key = pull.next();//继续解析 } return channelList; }
Channel
package org.fkjava.pull; /** * facejava facejava]]> 20090909 http://www.facejava.org * @authorhanfeili * */ publicclass Channel { privateintid; private String name; private String title; private String description; private String link; private String pubDate; public String getPubDate() { returnpubDate; } publicvoid setPubDate(String pubDate) { this.pubDate = pubDate; } @Override public String toString() { return"Channel [id=" + id + ", name=" + name + ", title=" + title + ", description=" + description + ", link=" + link + "]"; } publicint getId() { returnid; } publicvoid setId(int id) { this.id = id; } public String getName() { returnname; } publicvoid setName(String name) { this.name = name; } public String getTitle() { returntitle; } publicvoid setTitle(String title) { this.title = title; } public String getDescription() { returndescription; } publicvoid setDescription(String description) { this.description = description; } public String getLink() { returnlink; } publicvoid setLink(String link) { this.link = link; } }
channel.xml
存储在:  xmlversion="1.0"encoding="UTF-8"?> channel> itemname="www.facejava.org"> title>facejavatitle> description>description-facejava]]>description> pubDate>20090909pubDate> link>http://www.facejava.orglink> item> itemname="jietu"> title>jietutitle> description>description-jietu]]>description> pubDate>20110606pubDate> link>jietulink> item> itemname="google"> title>gooletitle> description>description-goole]]>description> pubDate>2011088pubDate> link>googlelink> item> itemname="baidu"> title>baidutitle> description>description-baidu]]>description> pubDate>20110898pubDate> link>baidulink> item> itemname="baidu2"> title>baidu2title> description>description-baidu]]>description> pubDate>20110898pubDate> link>baidulink> item> channel>
生成
//FileOutputStream out = new FileOutputStream(file); //openFileOutput 获得对输出的一个fileOutpStream对象(输出文件到 本应用对应的 files文件夹中) FileOutputStream out = PullDemoActivity.this.openFileOutput("new_channel.xml", MODE_PRIVATE); OutputStreamWriter writer = new OutputStreamWriter(out); //String xmlstr = writeXML.writeXML("", channelList, new StringWriter()); String xmlstr =writeXML("", channelList, writer); writer.close(); publicstatic String writeXML(String namespace, List channelList, Writer writer) { XmlSerializer serializer = Xml.newSerializer(); try { // 设置输出方式和输出目的地(在writer中指定) serializer.setOutput(writer); // 设置开始文档 serializer.startDocument("utf-8", true); /* * 参数1:命名空间 参数2:文档开始根节点 */ serializer.startTag(namespace, "channel"); serializer.attribute(namespace, "good", "good"); for (Channel channel : channelList) { // 设置节点 serializer.startTag(namespace, "item"); // 设置带属性的节点内容 serializer.attribute(namespace, "id", new Integer(channel.getId()).toString()); serializer.startTag(namespace, "title"); serializer.attribute(namespace, "name", channel.getName()); // 设置节点中的文本内容 serializer.text(channel.getTitle()); serializer.endTag(namespace, "title"); serializer.startTag(namespace, "description"); serializer.text(channel.getDescription()); serializer.endTag(namespace, "description"); serializer.startTag(namespace, "pubDate"); serializer.text(channel.getPubDate()); serializer.endTag(namespace, "pubDate"); serializer.startTag(namespace, "link"); serializer.text(channel.getLink()); serializer.endTag(namespace, "link"); serializer.endTag(namespace, "item"); } serializer.endTag(namespace, "channel"); // 结束xml文档 serializer.endDocument(); return writer.toString(); } catch (Exception e) { Log.d(TAG, "create xml exception ", e); } returnnull; }
JSON
JSON对象结构 (Map结构)  JSON数组结构  JSON的值可以是如下类型数据 
代码1
package org.facejava.jsons; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import android.app.Activity; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.TextView; /** * Android中操作JSON数据 * @author hanfeili * */ public class MainActivity extends Activity { protected static final String TAG = null; TextView tv; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); tv = (TextView)findViewById(R.id.tv); findViewById(R.id.json_btn).setOnClickListener(click); } //对象JSON格式 键/值 对 String json_str = "{\"name\":\"facejava\",\"website\":\"www.facejava\",\"phone\":1342}"; String json_user = "[{\"id\":1,\"name\":\"tom\",\"address\":\"广东广州\",\"phone\":\"13422218560\"}," + "{\"id\":2,\"name\":\"tiger\",\"address\":\"湖南\",\"phone\":\"134\"}]"; String json_user2 = "{\"id\":1,\"name\":\"tom\",\"address\":\"广东\",\"phone\":\"13422218560\"}"; View.OnClickListener click = new View.OnClickListener() { @Override public void onClick(View v) { /*try { //parserJsonObject(); //parserJsonArray(); } catch (JSONException e) { e.printStackTrace(); }*/ /*//使用google 的gson进行Json数据操作,可以非常方便的在java对象和json之间进行转换 * GsonTest gsontest = new GsonTest(); ArrayList userList = gsontest.parser(json_user); //将ArrayList中的数据打印出来 Log.i(TAG, "userList----"+Arrays.toString(userList.toArray())); User user = gsontest.jsonToObject(json_user2); Log.i(TAG, "User---"+user); System.out.println("--------java对象转换json格式字符串--------"); String jsonStr = gsontest.objectToJson(user); Log.i(TAG, "jsonStr---"+jsonStr);*/ //使用android内置的json类操作json数据生成 WriterJson wj = new WriterJson(); wj.writerJsons(); } /** * json数组解析 * @throws JSONException */ //数组JSON格式 String json_array = "[{\"name\":\"tom\",\"age\":23,\"address\":\"gz\"} , {\"name\":\"tiger\",\"age\":30,\"address\":\"hn\"}]"; private void parserJsonArray() throws JSONException { JSONArray jsonArray = new JSONArray(json_array); //获得JSON数组值的个数 int len = jsonArray.length(); for(int i=0; i JSONObject jo = jsonArray.getJSONObject(i); Log.i(TAG, "name-------"+jo.getString("name")); Log.i(TAG, "age--------"+jo.getInt("age")); Log.i(TAG, "address----"+jo.getString("address")); } } /** * 操作 JSON 对象 * @throws JSONException */ private void parserJsonObject() throws JSONException { //String json_str = "{\"name\":\"facejava\",\"website\":\"www.facejava\",\"phone\":1342}"; String json_str = "{'name':'facejava','website':'www.facejava','phone':1342,stu:{'name':'tom','age':18}}"; JSONObject jsonObj = new JSONObject(json_str); //通过键去获得JSON格式中的对应的值 Log.i(TAG, "name-----"+jsonObj.get("name")); //可以使用上面的get()和下面的getXxx()方法去获得键对应的值 Log.i(TAG, "website--"+jsonObj.getString("website")); Log.i(TAG, "phone----"+jsonObj.getInt("phone")); JSONObject stu_Json = jsonObj.getJSONObject("stu"); Log.i(TAG, "stu-name----"+stu_Json.getString("name")); Log.i(TAG, "stu-age----"+stu_Json.getInt("age")); } }; }
android内置Json类 产生Json
package org.facejava.jsons; import org.json.JSONArray; import org.json.JSONObject; import android.util.Log; /** * android内置Json类 产生Json * * @author hanfei.li * @since 2011-8-18 下午02:14:46 */ public class WriterJson { private static final String TAG = "WriterJson"; /** * 产生Json对象(json中包含数组) */ public void writerJsons() { JSONObject jo = new JSONObject(); try { jo.put("id", 1); jo.put("name", "tom"); jo.put("age", 26); JSONArray ja = new JSONArray(); ja.put(1,"广东广州"); ja.put(0,"湖南"); jo.put("addrss", ja); Log.i(TAG, jo.toString()); } catch (Exception e) { e.printStackTrace(); } } }
Gson
GSON 包下载地址 http://code.google.com/p/google-gson /*- History ********************************************** * ID DATE PERSON REASON * 1 2011-8-18 hanfei.li Created ********************************************** */ package org.facejava.jsons; import java.io.StringReader; import java.util.ArrayList; import com.google.gson.Gson; import com.google.gson.stream.JsonReader; /** * 使用GSON 方式对json格式数据进行解析 Gson还可以非常方便的操作Map,List,数组...可以参考上课PPT的备注 * * @author hanfei.li * @since 2011-8-18 上午11:51:41 */ public class GsonTest { public ArrayList parser(String jsons) { User user = null; ArrayListuserList = new ArrayList(); // StringReader 是将给他的字符串参数以 流 的形式返回 // StringWriter JsonReader jr = new JsonReader(new StringReader(jsons)); try { jr.beginArray(); while (jr.hasNext()) { //json对象开始 jr.beginObject(); user= new User(); while (jr.hasNext()) { String tagName = jr.nextName(); if (tagName.equals("name")) { user.setName(jr.nextString()); } else if (tagName.equals("id")) { user.setId(jr.nextInt()); }else if(tagName.equals("address")){ user.setAddress(jr.nextString()); }else if(tagName.equals("phone")){ user.setPhone(jr.nextString()); } } userList.add(user); jr.endObject(); } jr.endArray(); } catch (Exception e) { e.printStackTrace(); } return userList; } /** * 将一个json格式的字符串对应转换到一个对象中 * @param jsons * String json_user2 = "{\"id\":1,\"name\":\"tom\",\"address\":\"广东\",\"phone\":\"13422218560\"}"; * @return */ public User jsonToObject(String jsons){ Gson gson = new Gson(); //通过formJson方法可以将一个一定格式的json数据转换成一个对象实例 User u = gson.fromJson(jsons, User.class); return u; } /** * 将对象转换为json格式的字符串 * @return */ public String objectToJson(User user){ Gson gson = new Gson(); //将一个对象转换为相应格式的json数据 String json_str = gson.toJson(user); return json_str; } }
User
/** * @(#)User.java * * Copyright XXX.All rights reserved. * This software is the XXX system. * * @Version: XXX * @JDK: jdk 1.6.0.XXX * @Module: JsonDemo */ /*- History ********************************************** * ID DATE PERSON REASON * 1 2011-8-18 hanfei.li Created ********************************************** */ package org.facejava.jsons; /** * JSON数据存放的对象 * * @author hanfei.li * @since 2011-8-18 上午11:52:49 */ public class User { private int id; private String name; private String address; private String phone; public String toString() { return "User@id:" + this.id + " name:" + this.name + " address:" + this.address + " phone:" + this.phone; } public User() { } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } }
14-Service服务
通过startService()启动的服务需要通过stopService()或selfService()停止 会经过:onCreate()->onStartCommand()->runing-->onDestroy() 调用者和服务之间没有联系 通过bindService()启动的服务需要通过unbindService()停止 会经过:onCreate()->onBind()->runing-->onUnbind()-->onDestroy() 调用者和服务之间有联系 Service是通过其他组件启动的,虽然在后台运行,但是仍然是的主线程中 Service是android为开发者提供的一个开辟子线程,进行耗时操作的机会。 IntentService  使用 startService() 一般适用于 本应用内部调用,并且不需要获取服务端的数据 因为使用startService()启动的服务和调用组件之间没有关系 使用bindService() 一个适用于 不同的进程之间进行调用,并需要获取服务端的数据。 因为使用bindService()启动的服务和调用组件之间可以建立联系。 使用IntentService 可以不用管理线程的创建会关闭 可以简化线程操作
startService
MainActivity
package org.fkjava.service; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; /** * @author hanfeili * */ public class MainActivity extends Activity implements OnClickListener { private static final String TAG = "MainActivity"; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TextView show = (TextView) findViewById(R.id.textView1); Button start = (Button) findViewById(R.id.start); Button stop = (Button) findViewById(R.id.stop); start.setOnClickListener(this); stop.setOnClickListener(this); } @Override public void onClick(View v) { Thread currentThread = Thread.currentThread(); Log.i(TAG, "------Activity当前的的UI线程--["+currentThread.getId()+"]---["+currentThread.getName()+"]--------"); Intent intent = new Intent(this,MyService.class); switch (v.getId()) { case R.id.start: //启动一个intent中指定的服务 //通过startService启动的服务不会随调用端的结束而结束 startService(intent); break; case R.id.stop: //停止服务 stopService(intent); break; } } }
MyService
package org.fkjava.service; import java.io.IOException; import android.app.Service; import android.content.Intent; import android.media.MediaPlayer; import android.os.IBinder; import android.provider.MediaStore.Audio.Media; import android.util.Log; /** * 创建服务类步骤 * 1:继承Service类 * 2:重写方法 * 3: 服务的注册 特别注意: 服务是运行在UI线程中,所以在服务中进行耗时操作同样会影响UI线程 服务通常是给我们提供一个平台,让我们有机会创建一个新的线程去完成耗时任务 * @author hanfeili * */ public class MyService extends Service{ private static final String TAG = "MyService"; MediaPlayer player =null; @Override public void onCreate() { super.onCreate(); Log.i(TAG, "-------onCreate--------"); //初始化需要播放的资源 player = MediaPlayer.create(this, R.raw.test); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i(TAG, "-------onStartCommand--------"); Thread currentThread = Thread.currentThread(); Log.i(TAG, "------Service当前的线程--["+currentThread.getId()+"]---["+currentThread.getName()+"]--------"); //初始化资源,准备播放 /*try { player.prepare(); } catch (IOException e) { e.printStackTrace(); }*/ //开始播放 player.start(); return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { Log.i(TAG, "-------onDestroy--------"); //停止播放 player.stop(); //释放资源 player.release(); super.onDestroy(); } @Override public IBinder onBind(Intent intent) { Log.i(TAG, "-------onBind--------"); return null; } }
bindService
MainActivity
package org.fkjava.service; import org.fkjava.service.MyService.MyBinder; import android.app.Activity; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; public class MainActivity extends Activity implements OnClickListener { private static final String TAG = "MainActivity"; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TextView show = (TextView) findViewById(R.id.textView1); Button start = (Button) findViewById(R.id.start); Button stop = (Button) findViewById(R.id.stop); start.setOnClickListener(this); stop.setOnClickListener(this); } MyService myService =null; ServiceConnection conn = new ServiceConnection() { //当调用端和服务端绑定以后将返回调用onServiceConnected方法,来返回服务端的引用 //获得服务端的引用以后就可以通过引用调用服务端的数据 @Override public void onServiceConnected(ComponentName name, IBinder service) { //service是IBinder接口类型,需要转换成目标子类 MyBinder myBinder = (MyBinder)service; //通过服务端的内部类的引用调用他的方法获得外部类(服务类)的引用 myService = myBinder.getServiceInstance(); //通过获得的外部类引用调用数据 myService.startMusic(); } @Override public void onServiceDisconnected(ComponentName name) { } }; @Override public void onClick(View v) { Thread currentThread = Thread.currentThread(); Log.i(TAG, "------Activity当前的的UI线程--["+currentThread.getId()+"]---["+currentThread.getName()+"]--------"); Intent intent = new Intent(this,MyService.class); switch (v.getId()) { case R.id.start: //启动一个intent中指定的服务 //通过bindService启动的服务会随调用端的结束而结束 /** * 参数1:intent * 参数2:返回回调实例 * 参数3:当服务不存在的时候自动创建服务 */ bindService(intent,conn, Context.BIND_AUTO_CREATE); break; case R.id.stop: if(conn != null){ myService.stopMusic(); //停止服务 unbindService(conn); } break; } } @Override protected void onDestroy() { Log.i(TAG, "------onDestroy--"); if(conn != null){ //停止服务 unbindService(conn); } super.onDestroy(); } }
MyService
package org.fkjava.service; import android.app.Service; import android.content.Intent; import android.media.MediaPlayer; import android.os.Binder; import android.os.IBinder; import android.util.Log; /** * 创建服务类步骤 * 1:继承Service类 * 2:重写方法 * 3: 服务的注册 特别注意: 服务是运行在UI线程中,所以在服务中进行耗时操作同样会影响UI线程 服务通常是给我们提供一个平台,让我们有机会创建一个新的线程去完成耗时任务 * @author hanfeili * */ public class MyService extends Service{ private static final String TAG = "MyService"; MediaPlayer player =null; @Override public void onCreate() { super.onCreate(); Log.i(TAG, "-------onCreate--------"); Thread currentThread = Thread.currentThread(); Log.i(TAG, "------Service当前的的UI线程--["+currentThread.getId()+"]---["+currentThread.getName()+"]--------"); //初始化需要播放的资源 player = MediaPlayer.create(this, R.raw.test); } public void startMusic(){ player.start(); } public void stopMusic(){ player.stop(); } @Override public IBinder onBind(Intent intent) { Log.i(TAG, "-------onBind--------"); //返回内部类实例,给调用端的ServiceConnection实例 return new MyBinder(); } //创建一个内部类继承Binder(IBinder的子类) class MyBinder extends Binder{ //提供一个成员方法,返回外部类的引用,方便给其他的调用端使用 public MyService getServiceInstance(){ return MyService.this; } } @Override public void onDestroy() { Log.i(TAG, "-------onDestroy--------"); this.stopMusic(); super.onDestroy(); } }
AIDL
AIDL (Android Interface Definition Language)是一种AIDL 语言,用于生成可以在Android设备上两个进程之间进行进程间通信的代码。 如果在一个进程中要调用另一个进程中对象的操作,就可以使用AIDL生成可序列化的参数。 AIDL IPC机制是面向接口的,类似COM或Corba一样,J2EE RMI,但是更加轻量级。 它是使用代理类在客户端和服务端传递数据。 注意:AIDL只支持方法,不能定义静态成员,并且方法也不能有类似public等的修饰符;
AIDL-服务端
第一步: 定义一个RemoteService.aidl文件,该文件里是符合aidl语言规范的接口定义,文件中定义了供外部应用调用的方法的接口。 保存该文件的时候,在gen文件夹下会自动生成对应的RemoteService.java接口文件。 第二步:自定义Service类,并注册到AndroidManifest.xml文件中 客户端进程可以通过action访问到服务端进程。 在实现自己的service时,为了外部应用可以通过bindService和我们的service进行交互,我们要实现service中的onBind()方法,并且返回一个继承了Binder的内部类; 在这里,eclipse自动为我们生成的RemoteService.java中有一个实现了Binder的内部类RemoteService.Stub。 在这里不能再直接去实现Binder类,而是去实现,AIDL提供给我们的Stub类。 实现Stub类的同时,AIDL还要求同时实现我们在接口中定义的各种服务方法的具体实现。
目录结构

RemoteInterface.aidl
package org.fkjava.interfaces; import org.fkjava.pojo.User; interface RemoteInterface { String getName(String name); User getUser(in User u); }
复合类型对象
User.java
package org.fkjava.pojo; import android.os.Parcel; import android.os.Parcelable; /** * AIDL中如果要传递一个自定义对象,需要实现Parcelable接口,并自定义序列化策略 * @author hanfeili * */ public class User implements Parcelable{ private int id; private String name; private int age; private String phone; public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { //相当于反序列化 public User createFromParcel(Parcel source) { return new User(source.readInt(),source.readString(),source.readInt(),source.readString()); } public User[] newArray(int size) { return new User[size]; } }; public int describeContents() { return 0; } //相当于序列化输出数据,希望进行序列化的属性输出指定 public void writeToParcel(Parcel dest, int flags) { dest.writeInt(this.id); dest.writeString(this.name); dest.writeInt(this.age); dest.writeString(this.phone); } public User() { } public User(int id, String name, int age, String phone) { this.id = id; this.name = name; this.age = age; this.phone = phone; } @Override public String toString() { return "User [id=" + id + ", name=" + name + ", age=" + age + ", phone=" + phone + "]"; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } }
User.aidl
package org.fkjava.pojo; parcelable User;
RemoteService
package org.fkjava.services; importorg.fkjava.interfaces.RemoteInterface; import org.fkjava.pojo.User; import android.app.Service; import android.content.Intent; importandroid.os.Binder; import android.os.IBinder; import android.os.RemoteException; import android.util.Log; publicclassRemoteService extends Service { publicvoid test(){}; @Override public IBinder onBind(Intent intent) { returnnew MyBinder(); } class MyBinder extendsRemoteInterface.Stub{ privatestaticfinal String TAG = "MyBinder"; public String getName(String name) throws RemoteException { Log.i(TAG, "------------getName()---------"+name); return"hello:"+name; } public User getUser(User u) throws RemoteException { Log.i(TAG, "--getUser()--"+u); u.setName("tiger"); u.setAge(28); return u; } } }
AIDL-客户端
目录结构
 RemoteInterface.aidl 还有User.java和User.aidl到和服务器的一模一样。
MainActivity
package org.fkjava.servicec; import org.fkjava.interfaces.RemoteInterface; import org.fkjava.pojo.User; import android.app.Activity; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.TextView; publicclass MainActivity extends Activity implements OnClickListener { protectedstaticfinal String TAG = "MainActivity"; TextView show = null; @Override publicvoid onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findViewById(R.id.start).setOnClickListener(this); findViewById(R.id.stop).setOnClickListener(this); show = (TextView) findViewById(R.id.textView1); } publicvoid onClick(View v) { switch (v.getId()) { case R.id.start: Intent intent = new Intent("org.fkjava.rs"); bindService(intent, conn, Context.BIND_AUTO_CREATE); break; case R.id.stop: if(conn !=null){ unbindService(conn); } break; } } RemoteInterface ri =null; ServiceConnection conn = new ServiceConnection(){ publicvoid onServiceConnected(ComponentName name, IBinder service) { ri = RemoteInterface.Stub.asInterface(service); try{ /*String returnName = ri.getName("tom"); Log.i(TAG, "-----服务器返回数据--------------"+returnName);*/ User u = ri.getUser(new User(8,"hanfeili",18,"12345678")); Log.i(TAG, "-----服务器返回自定义User对象数据--------------"+u); }catch(Exception e){ e.printStackTrace(); } } publicvoid onServiceDisconnected(ComponentName name) {} }; }
IntentService
IntentService是Service类的子类,用来处理异步请求。 可以通过startService(Intent)方法传递请求给IntentService,IntentService通过worker thread按顺序处理每个Intent对象,执行完所有的工作之后会自动停止Service。 说明:worker thread处理所有通过传递过来的请求,创建一个worker queue一次只传递一个intent到onHandleIntent中,从而不必担心多线程带来的问题。 处理完毕之后自动调用stopSelf()方法; 默认实现了onBind()方法,返回值为null; 默认实现了startCommand()方法,这个方法会放到worker queue中,然后在onHandleIntent()中执行 使用IntentService需要2个步骤: 1、写构造函数(无参构造器) 2、重写onHandleIntent() 使用IntentService优点: 1:处理异步请求的时候可以减少代码量。 2:不必担心多线程带来的问题。
MainActivity
package org.fkjava.service; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; public class MainActivity extends Activity implements OnClickListener { private static final String TAG = "MainActivity"; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TextView show = (TextView) findViewById(R.id.textView1); Button start = (Button) findViewById(R.id.start); Button stop = (Button) findViewById(R.id.stop); start.setOnClickListener(this); stop.setOnClickListener(this); } @Override public void onClick(View v) { Thread currentThread = Thread.currentThread(); Log.i(TAG, "------Activity当前的的UI线程--["+currentThread.getId()+"]---["+currentThread.getName()+"]--------"); Intent intent = new Intent(this,MyService.class); switch (v.getId()) { case R.id.start: //启动一个intent中指定的服务 //通过startService启动的服务不会随调用端的结束而结束 startService(intent); break; case R.id.stop: //停止服务 stopService(intent); break; } } @Override protected void onDestroy() { Log.i(TAG, "------onDestroy--"); super.onDestroy(); } }
MyService
package org.fkjava.service; import android.app.IntentService; import android.content.Intent; import android.os.IBinder; import android.os.SystemClock; import android.util.Log; /** * 通过继承IntentService 的方式来实现服务类 * 好处是 在onHandleIntent方法中会自动的创建一个子线程完成工作队列中的任务,当所有任务完成以后将自动结束服务 * * 但是需要注意:只有onHandleIntent方法才是在一个子线程中工作,其他的都是在UI线程中工作的 * @author hanfeili * */ public class MyService extends IntentService{ private static final String TAG = "MyService"; public MyService() { super("myService"); } @Override public void onCreate() { Log.i(TAG, "---------onCreate----------"); Thread currentThread = Thread.currentThread(); Log.i(TAG, "------Service当前的的UI线程--["+currentThread.getId()+"]---["+currentThread.getName()+"]--------"); super.onCreate(); } /** * 自动创建一个子线程完成工作队列中的任务 */ @Override protected void onHandleIntent(Intent intent) { Log.i(TAG, "---------onHandleIntent----start------"); Thread currentThread = Thread.currentThread(); Log.i(TAG, "------Service当前的的UI线程--["+currentThread.getId()+"]---["+currentThread.getName()+"]--------"); //Thread.sleep(1000); //睡眠指定时间 SystemClock.sleep(2000); Log.i(TAG, "---------onHandleIntent-----end----"); } @Override public void onDestroy() { Log.i(TAG, "---------onDestroy----------"); super.onDestroy(); } }
15-Broadcast和BroadcastReceiver
Broadcast - 用于发送广播 Broadcast是一种广泛运用于应用程序之间异步传输信息的机制。 BroadcastReceiver - 用于接收广播 BroadcastReceiver是对发送出来的Broadcast进行过滤接受并响应的组件。 Broadcast Receiver 没有提供可视化的界面来显示广播信息。 可以使用Notification和Notification Manager来实现可视化的信息的界面,显示广播信息的内容,图标及震动信息。 BroadcastReceiver 用于异步接收广播Intent。 主要有两大类,用于接收广播的: 正常广播 是完全异步的。运行在一个未定义的顺序,通常是在同一时间。这样会更有效,但意味着receiver不能包含所要使用的结果或中止的API。 有序广播 每次被发送到一个receiver。所谓有序,就是每个receiver执行后可以传播到下一个receiver,也可以完全中止传播——不传播给其他receiver。 而receiver运行的顺序可以通过匹配intent-filter里面的android:priority来控制,当priority优先级相同的时候,Receiver以任意的顺序运行。 要注意的是,即使是正常广播 ,系统在某些情况下可能会恢复到一次传播给一个receiver。 特别是receiver可能需要创建一个进程,为了避免系统超载,只能一次运行一个receiver。
正常广播
MainActivity
package org.fkjava.broadcastreceivera; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; public class MainActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } public void send(View v){ Intent intent = new Intent("org.fkjava.a"); //android在3版本以后新增了一个安全控制,防止随意启动一些没有运行的程序,而添加的控制标记 //FLAG_INCLUDE_STOPPED_PACKAGES 将广播发送给所有的程序,不管启动与否 intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); //FLAG_EXCLUDE_STOPPED_PACKAGES 将广播只发送给启动了的程序 //intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES); //发送正常广播 sendBroadcast(intent); } }
BroadcastReceiverA
package org.fkjava.broadcastreceiver; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.util.Log; /** * 广播处理类实现步骤: * 1:写一个类继承BroadcastReceiver * 2:重新onReceive()实现广播处理代码 * 3:注册广播,并指定感兴趣的广播事件 4:发送正常广播使用sendBroadcast(intent); * @author hanfeili * */ public class BroadcastReceiverA extends BroadcastReceiver{ private static final String TAG = "A"; //每一个感兴趣的广播接收以后,都将创建实例 public BroadcastReceiverA(){ Log.i(TAG, "------BroadcastReceiver-A----------"); } //处理感兴趣的广播事件 //当onReceive()方法执行完毕,就表示广播处理类生命周期结束 //所以不能在onReceive方法中不能写太耗时的处理代码 @Override public void onReceive(Context context, Intent intent) { Log.i(TAG, "------onReceive----------"+intent.getAction()); } }
有序广播
MainActivity
package org.fkjava.a; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; public class MainActivity extends Activity { EditText input = null; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); input = (EditText)findViewById(R.id.editText1); Button send = (Button)findViewById(R.id.button1); send.setOnClickListener(new OnClickListener() { public void onClick(View v) { Intent intent = new Intent("org.fkjava.orderbr"); //在android 3版本以后发送广播,实现了更加安全的控制 //默认情况是没有启动的程序不能接收广播,因为在广播发送中包含了如下的flag排除没有启动的程序接收广播 //intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);‘ //如果我们希望所有程序都能够接收广播,需要手动配置如下的一个flags intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); //通过广播携带数据(就是参数传递) intent.putExtra("name", input.getText().toString()); intent.putExtra("password", "1234"); //发送正常广播 //MainActivity.this.sendBroadcast(intent); //发送有序广播 MainActivity.this.sendOrderedBroadcast(intent, null); } }); } }
BReceiverA
publicclass BReceiverA extends BroadcastReceiver { privatestaticfinal String TAG = "BReceiverA"; public BReceiverA(){ Log.i(TAG, "---------BReceiverA()--------"); } @Override publicvoid onReceive(Context context, Intent intent) { Log.i(TAG, "-onReceive()--:"+intent.getAction()); String name = intent.getStringExtra("name"); String password = intent.getStringExtra("password"); Log.i(TAG, "-A接收到的参数:"+name+"---"+password); //创建一个Bundle,方便数据绑定进行传递 Bundle bundle = new Bundle(); bundle.putString("names", name); //设置需要继续传递的参数 //参数1:传递标识码 //参数2:传递标识字符串 //参数3:传递的数据 this.setResult(123, "A", bundle); } }
BReceiverB
publicclassBReceiverBextends BroadcastReceiver { privatestaticfinal String TAG = "BReceiverB"; public BReceiverB(){ Log.i(TAG, "---------BReceiverB()--------"); } @Override publicvoid onReceive(Context context, Intent intent) { Log.i(TAG, "-onReceive()--:"+intent.getAction()); //接收前面设置进广播的数据 int code = this.getResultCode(); String data = this.getResultData(); Bundle bundle = this.getResultExtras(true); String name = bundle.getString("names"); Log.i(TAG, "-B接收到的参数:"+code+"---"+data+"--"+name); if(!"admin".equals(name)){ //终止广播继续向下传递 this.abortBroadcast(); } } }
广播注册
常驻广播注册
程序能够随时处理感兴趣的广播 receiverandroid:name=".BReceiverA"> intent-filterandroid:priority="10"> actionandroid:name="org.fkjava.broadcastreceiverA"/> intent-filter> receiver>
非常驻广播注册
package org.fkjava.a; import android.app.Activity; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; public class MainActivity extends Activity { private static final String TAG = "动态注册MainActivity"; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button send = (Button)findViewById(R.id.button1); send.setOnClickListener(new OnClickListener() { public void onClick(View v) { Intent intent = new Intent("org.fkjava.dynReceiver"); //在android 3版本以后发送广播,实现了更加安全的控制 //默认情况是没有启动的程序不能接收广播,因为在广播发送中包含了如下的flag排除没有启动的程序接收广播 //intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);‘ //如果我们希望所有程序都能够接收广播,需要手动配置如下的一个flags intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); //发送正常广播 MainActivity.this.sendBroadcast(intent); } }); } DynBReceiver receiver =null; @Override protected void onResume() { Log.i(TAG, "-----onResume()---广播处理类注册--------"); receiver = new DynBReceiver(); //动态配置IntentFilter IntentFilter intentFilter = new IntentFilter(); //intentFilter.addAction("org.fkjava.dynReceiver"); //测试动态注册,在退出以后还是否可以接收广播处理 intentFilter.addAction("android.provider.Telephony.SMS_RECEIVED"); //动态注册广播处理类 this.registerReceiver(receiver, intentFilter); super.onResume(); } @Override protected void onDestroy() { Log.i(TAG, "-----onDestroy()---广播处理类注销--------"); this.unregisterReceiver(receiver); super.onDestroy(); } }
短信监听实例
SMSListener
package org.fkjava.smslistener; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.telephony.SmsMessage; import android.util.Log; /** * 短信监听 * @author hanfeili * */ public class SMSListener extends BroadcastReceiver { private static final String TAG = "SMSListener"; @Override public void onReceive(Context context, Intent intent) { Log.i(TAG, "action:"+intent.getAction()); //获取系统发送广播的传递的参数 (短信相关内容) Bundle bundle = intent.getExtras(); //取短信数据 Object[] pdus = (Object[])bundle.get("pdus"); SmsMessage[] smg = new SmsMessage[pdus.length]; for(int i=0;i smg[i] =SmsMessage.createFromPdu((byte[])pdus[i]); Log.i(TAG, "smg"+i+"--"+smg[i].toString()); } String smsBody = ""; for(SmsMessage m : smg){ smsBody = m.getDisplayMessageBody(); Log.i(TAG, "短信内容 "+m.getDisplayMessageBody()); Log.i(TAG, "发送人 "+m.getDisplayOriginatingAddress()); Log.i(TAG, "短信内容 "+m.getMessageBody()); Log.i(TAG, "发送人 "+m.getOriginatingAddress()); } if(smsBody.indexOf("love") != -1){ Intent intents = new Intent(context,ShowActivity.class); //延迟发送Intent PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intents, 0); Notification notification = new Notification(); //设置图标 notification.icon = R.drawable.ic_launcher; //设置振动,声音,灯关 //notification.defaults = Notification.DEFAULT_ALL; notification.defaults = Notification.DEFAULT_SOUND; notification.tickerText = "警告"; notification.setLatestEventInfo(context, "警告!", "认真学习!", pendingIntent); //notification.contentIntent = pendingIntent; NotificationManager notificationManager =(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); /** * 参数1:唯一的全局标示 (方便后续的管理) * 参数2:notification 信息短信 */ notificationManager.notify(168, notification); abortBroadcast(); } } }
ShowActivity
package org.fkjava.smslistener; import android.app.Activity; import android.app.NotificationManager; import android.content.Context; import android.os.Bundle; /** * 短信点击自定义显示界面 * @author hanfeili * */ public class ShowActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.show); //获得通知服务 NotificationManager notificationManager =(NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE); //将一个指定的通知清除 notificationManager.cancel(168); } }
配置文件
application android:icon="@drawable/ic_launcher" android:label="@string/app_name"> activityandroid:name=".ShowActivity">activity> receiverandroid:name=".SMSListener"> intent-filterandroid:priority="100"> actionandroid:name="android.provider.Telephony.SMS_RECEIVED"/> intent-filter> receiver> application> uses-permissionandroid:name="android.permission.RECEIVE_SMS"/>
16-WebView
访问web应用的页面的时候使用的是PC浏览器 移动端访问web应用的页面使用 WebView 组件 WebKit webView 开发: 一般不变的静态页面放在当前应用的assest文件夹中,进行访问 file:///android_asset/test.html 一般经常变化或者动态页面就直接访问服务器端 网络操作记得配置网络权限
代码
package org.fkjava.wv; import android.app.Activity; import android.app.AlertDialog; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; import android.os.Bundle; import android.os.Handler; import android.util.Log; import android.view.KeyEvent; import android.webkit.JsResult; import android.webkit.WebChromeClient; import android.webkit.WebSettings; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.Toast; /** * WebView使用实例 * @author hanfeili * */ public class MainActivity extends Activity { WebView wv = null; //测试给js传递参数 int count = 0; // String user = "tom"; //json格式 String user = "{'id':10,'name':'lis'}"; Handler handler = new Handler(); @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); wv = (WebView) findViewById(R.id.webview); //获得WebView的设置对象 WebSettings webSetting = wv.getSettings(); // 设置WebView 支持javascript引擎 (支持javascript操作) webSetting.setJavaScriptEnabled(true); // 服务网络web服务 (一般经常改变的页面,动态页面,使用网络web) //wv.loadUrl("http://192.168.10.222:8080/myServer/index.html"); // 访问本程序中的 资源 页面(一般不经常改变的页面,静态页面,使用如下方式) //file:///android_asset/ 表示操作本工程的assets目录中的资源 wv.loadUrl("file:///android_asset/index.html"); //wv.loadUrl("http://www.baidu.com"); // 在本webview中实现继续浏览,不使用系统的浏览器 wv.setWebViewClient(new WebViewClient() { /* *参数1:表示当前点击了连接的webview对象 *参数2:点击的连接 */ public boolean shouldOverrideUrlLoading(WebView view, String url) { // 在自己的webview中打开新连接 view.loadUrl(url); return true; } }); wv.setWebChromeClient(new WebChromeClient() { @Override /** * 捕获页面的alert对话框 * 参数1:产生事件的webview * 参数2:当前页面的url * 参数3:alert对话框想显示的信息 * 参数4:操作对话框是否 通过 */ public boolean onJsAlert(WebView view, String url, String message, final JsResult result) { AlertDialog.Builder dialog = new AlertDialog.Builder( MainActivity.this); dialog.setTitle("提示"); dialog.setIcon(R.drawable.ic_launcher); dialog.setMessage(message); dialog.setPositiveButton("确定", new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { result.confirm(); } }); dialog.create(); dialog.show(); return true; } }); JSTest jstest = new JSTest(); // 绑定java对象和页面javascript的操作 /** * 参数1:java对象 * 参数2:给页面javascript操作 参数1 java对象的 句柄 页面是操作使用 * window.obj.show(); 对象方法 * */ wv.addJavascriptInterface(jstest, "obj"); //如果有多个对象需要暴露给页面操作可以再写一个类暴露 wv.addJavascriptInterface(new Object() { public void show4(){ handler.post(new Runnable() { @Override public void run() { wv.loadUrl("javascript:sayHello4()"); } }); } }, "obj2"); } private class JSTest { // 传递int数据到页面javascript public void show() { handler.post(new Runnable(){ public void run(){ // 删除 wv.loadUrl("javascript:sayHello(" + (count++) + ")"); } }); } // 传递json数据到页面javascript public void show2() { Log.i("----", "-user--" + user); wv.loadUrl("javascript:sayHello2(" + user + ")"); } // 页面javascript传递参数到java对象中 public void show3(String name) { Toast.makeText(MainActivity.this, name, Toast.LENGTH_LONG).show(); } } /** * 重写 返回键的操作 避免 点击了返回键直接退出应用程序 */ int flag = 0; @Override public boolean onKeyDown(int keyCode, KeyEvent event) { // 判断 当前点击的按钮 是不是返回键,并且还要判断 当前的操作是不是可以返回上一步 if (keyCode == KeyEvent.KEYCODE_BACK && wv.canGoBack()) { flag = 0; wv.goBack();// 返回上一个页面 }else{ //点击2次退出程序 flag++; if(flag == 1){ Toast.makeText(this, "再点击一次将退出应用程序!", Toast.LENGTH_LONG).show(); }else{ //退出程序 this.finish(); } } return true; } }
HTML页面代码
HTML>HEAD>TITLE>我们自己的服务器TITLE> metahttp-equiv=content-typecontent="text/html; charset=utf-8"/> script> function sayHello(v){ if(v){ alert("大家好!"+v); document.getElementById("msg").innerHTML="hi_"+v; }else{ alert("同学们好~"); } } function sayHello2(v){ document.getElementById("msg").innerHTML="用户ID"+v.id+"-用户名-"+v.name; } //获取输入框中的数据,发送给java对象 function sendMsgtoJava(){ //获取数据 var name = document.getElementById("name").value; //发送给java对象的方法 window.obj.show3("您好:"+name); } function sayHello4(){ document.getElementById("msg").innerHTML="handler_操作"; } script> HEAD> BODY> P> H3>访问本应用程序中的html页面H3> divid="msg">div> ul> 用户名:inputtype="text"name="name"id="name"value="tom">br> 密 码:inputtype="password"name="password">br> inputtype="button"value="测试1"onclick="sayHello()">br> ahref="javascript:sayHello()">页面直接调用sayHello函数a>br> inputtype="button"value="测试show()"onclick="window.obj.show();">br> inputtype="button"value="测试show2()"onclick="window.obj.show2();">br> inputtype="button"value="测试show3()"onclick="sendMsgtoJava()">br> inputtype="button"value="测试show4()"onclick="window.obj2.show4();">br> ul> BODY>HTML>
布局
android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > android:id="@+id/webview" android:layout_width="match_parent" android:layout_height="match_parent" />
17-动画
渐变动画
渐渐的变化的动画 渐渐变化 位置 渐渐变化 透明度 渐渐变化 旋转 渐渐变化 缩放
代码方式
Activity类代码
package org.fkjava.animation; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.view.animation.AlphaAnimation; import android.view.animation.Animation; import android.view.animation.AnimationSet; import android.view.animation.RotateAnimation; import android.view.animation.ScaleAnimation; import android.view.animation.TranslateAnimation; import android.widget.Button; import android.widget.ImageView; /** * 动画 代码 方式 * @author hanfeili * */ public class MainDemoActivity extends Activity implements View.OnClickListener { ImageView iv = null; Button alpha, scale, rotate, trauslate; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); iv = (ImageView) findViewById(R.id.imageView1); alpha = (Button) findViewById(R.id.alpha); rotate = (Button) findViewById(R.id.rotate); scale = (Button) findViewById(R.id.scale); trauslate = (Button) findViewById(R.id.trauslate); alpha.setOnClickListener(this); rotate.setOnClickListener(this); scale.setOnClickListener(this); trauslate.setOnClickListener(this); } @Override public void onClick(View v) { Animation anim =null; AnimationSet animSet =null; switch (v.getId()) { case R.id.alpha:// 透明度 //创建透明度动画 //0.0表示完全透明 //1.0表示完全不透明 //取值范围在0.0 - 1.0之间数值 anim = new AlphaAnimation(1.0f,0.0f); //设置动画执行持续时间 (秒) anim.setDuration(5000); //android的动画基本可以运用在所有的View子类上 //alpha.startAnimation(anim); //使用单个动画 iv.startAnimation(anim); alpha.startAnimation(anim); break; case R.id.rotate:// 旋转 //创建旋转动画 //50以自己为中心进行旋转 //参数1:从什么当角旋转 //参数2:旋转到什么当角停止 //当角度为正数——表示顺时针旋转 当角度为负数——表示逆时针旋转 // 参数 3,4 : x,y 坐标 50以自己为中心进行旋转 anim = new RotateAnimation(0,360,50,50); anim.setDuration(5000); //使用单个动画 iv.startAnimation(anim); alpha.startAnimation(anim); break; case R.id.scale:// 伸缩 /** * 0.0表示收缩到没有 1.0表示正常无伸缩 值小于1.0表示收缩 值大于1.0表示放大 */ anim = new ScaleAnimation(1.0f,0.0f,1.0f,0.0f,200,200); anim.setDuration(5000); //使用单个动画 iv.startAnimation(anim); break; case R.id.trauslate:// 移动 anim = new TranslateAnimation(0, 100, 0, 250); anim.setDuration(5000); //使用单个动画 iv.startAnimation(anim); break; case R.id.btn:// 综合动画效果 //创建一个动画结果集 animSet = new AnimationSet(true); anim = new AlphaAnimation(0.0f,1.0f); //添加透明度动画 animSet.addAnimation(anim); anim = new TranslateAnimation(10, 100, 20, 250); //添加移动动画 animSet.addAnimation(anim); anim = new RotateAnimation(0,360,30,30); //添加旋转动画 animSet.addAnimation(anim); animSet.setDuration(8000); //使用动画集 iv.startAnimation(animSet); break; } } }
布局
android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > android:id="@+id/alpha" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="透明度动画" /> android:id="@+id/trauslate" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="移动动画" /> android:id="@+id/rotate" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="旋转动画" /> android:id="@+id/scale" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="伸缩动画" /> android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="综合动画效果" /> xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="horizontal" > android:id="@+id/imageView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:src="@drawable/b" />
XML方式
Activity类代码
package org.fkjava.animation; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.view.animation.AlphaAnimation; import android.view.animation.Animation; import android.view.animation.AnimationSet; import android.view.animation.AnimationUtils; import android.view.animation.RotateAnimation; import android.view.animation.ScaleAnimation; import android.view.animation.TranslateAnimation; import android.widget.Button; import android.widget.ImageView; /** * 动画 xml 方式 * @author hanfeili * */ public class OtherActivity extends Activity{ ImageView iv = null; Button btn; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); iv = (ImageView) findViewById(R.id.imageView1); btn = (Button) findViewById(R.id.btn2); findViewById(R.id.alpha).setVisibility(View.GONE); findViewById(R.id.rotate).setVisibility(View.GONE); findViewById(R.id.scale).setVisibility(View.GONE); findViewById(R.id.trauslate).setVisibility(View.GONE); findViewById(R.id.btn).setVisibility(View.GONE); } public void onCliek2(View v) { //加载 xml 中定义的动画 Animation anim = AnimationUtils.loadAnimation(this, R.anim.tween_anim); //应用到组件上 iv.startAnimation(anim); } }
动画配置文件(res\anim)
动画效果配置文件存储位置:res\anim\tween_anim.xml android:duration="5000" android:fromAlpha="0.0" android:toAlpha="1.0" /> android:duration="5000" android:fillAfter="false" android:fromXScale="0.0" android:fromYScale="0.0" android:interpolator="@android:anim/accelerate_decelerate_interpolator" android:pivotX="50%" android:pivotY="50%" android:repeatCount="10" android:startOffset="700" android:toXScale="1.4" android:toYScale="1.4" /> android:duration="5000" android:fromXDelta="30" android:fromYDelta="30" android:toXDelta="150" android:toYDelta="300" /> android:interpolator="@android:anim/accelerate_decelerate_interpolator" android:duration="5000" android:fromDegrees="0" android:pivotY="50%" android:pivotX="50%" android:repeatCount="10" android:toDegrees="-350"/>
帧式动画
一张一张 播放 图片效果
动画监听
package org.fkjava.anim; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.view.animation.AlphaAnimation; import android.view.animation.Animation; import android.view.animation.Animation.AnimationListener; import android.widget.Button; public class AActivity extends Activity implements View.OnClickListener,AnimationListener{ private static final String TAG = "AActivity"; Button btn = null; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); btn = (Button) findViewById(R.id.button1); btn.setOnClickListener(this); } @Override public void onClick(View v) { Animation anim = new AlphaAnimation(1.0f, 0.0f); anim.setDuration(5000); //设置动画监听处理器 anim.setAnimationListener(this); btn.setAnimation(anim); } /** * 触屏 事件 */ @Override public boolean onTouchEvent(MotionEvent event) { if(event.getAction() == MotionEvent.ACTION_MOVE){ Intent intent = new Intent(this,BActivity.class); this.startActivity(intent); //2.0之后 才可以使用 实现 Activity之间的动画跳转 //overridePendingTransition 一定是在startActivity 方法之下调用 this.overridePendingTransition(R.anim.push_up_in,R.anim.push_up_out); return true; } return super.onTouchEvent(event); } @Override public void onAnimationStart(Animation animation) { Log.i(TAG, "------动画开始---------"); } @Override public void onAnimationEnd(Animation animation) { Log.i(TAG, "------动画结束---------"); } @Override public void onAnimationRepeat(Animation animation) { Log.i(TAG, "------动画重复---------"); } }
动画转场效果
Intent intent = new Intent(this,BActivity.class); this.startActivity(intent); //2.0之后 才可以使用 实现 Activity之间的动画跳转 //overridePendingTransition 一定是在startActivity 方法之下调用 //this.overridePendingTransition(R.anim.zoom_in,R.anim.zoom_out); this.overridePendingTransition(R.anim.left_in,R.anim.left_out);
转场动画配置文件
   
in
android:duration="10000" android:fromXDelta="-50%p" android:toXDelta="0" /> android:duration="10000" android:fromAlpha="0.0" android:toAlpha="1.0" /> android:duration="10000" android:fromDegrees="0" android:pivotX="50%p" android:pivotY="50%p" android:toDegrees="360" /> android:duration="10000" android:fromXScale="0.0" android:fromYScale="0.0" android:toXScale="1.0" android:toYScale="1.0" android:pivotX="50%" android:pivotY="0%" />
out
android:duration="10000" android:fromXDelta="50%p" android:toXDelta="0" /> android:duration="10000" android:fromAlpha="0.0" android:toAlpha="1.0" /> android:duration="10000" android:fromDegrees="0" android:pivotX="50%p" android:pivotY="50%p" android:toDegrees="360" /> android:duration="10000" android:fromXScale="1.0" android:fromYScale="1.0" android:toXScale="0.0" android:toYScale="0.0" android:pivotX="50%" android:pivotY="0%" />
18-多媒体操作
音乐
视频
照相机
综合实例
调用系统的镜头,实现拍照 和 录视频 调用系统的mac实现 录音 (电话监听)
19-游戏框架代码实现思路
开发中常见问题
遇到的错误多了,经验才丰富,解决问题速度才快,所以遇到问题我们应该开心的面对,积极的解决!
1-ActivityNotFoundException
1:当没有在AndroidManifest.xml文件中配置对应的Activity或者配置写错了的时候,会出现ActivityNotFoundException 异常 android.content.ActivityNotFoundException: Unable to find explicit activity class {org.fkjava.activity/org.fkjava.activity.a.OtherActivity}; have you declared this activity in your AndroidManifest.xml?
2-android.content.res.Resources$NotFoundException
Caused by: android.content.res.Resources$NotFoundException: 一个对应的资源没有找到: 这个问题有2中方式解决: 1,提供对应的资源 2,通常在进行例如View.setText(),传递了一个int会报这个错误 因为 setText()有 多个 重载 重载1: setText(CharSequence text) // 直接给一个字符串显示 重载2: setText(int resId) //给一个对应的资源id进行显示
3-AUTOINCREMENT is only allowed on an INTEGER PRIMARY KEY
SQLite3支持 NULL、INTEGER、REAL(浮点数字)、TEXT(字符串文本)和BLOB(二进制对象)数据类型,虽然它支持的类型只有五种,但实际上sqlite3也接受varchar(n)、char(n)、decimal(p,s) 等数据类型,但是在运算或保存时会转成对应的五种数据类型。SQLite3最大的特点是你可以保存任何类型的数据到任何字段中。例如:可以在Integer字段中存放字符串,或在布尔型字段中存放浮点数,或在字符型字段中存放日期型值。 但有一种情况例外:定义为INTEGER PRIMARY KEY的字段只能存储64位整数。另外,SQLite3在解析CREATE TABLE 语句时,会忽略 CREATE TABLE 语句中跟在字段名后面的数据类型信息,如下面语句会忽略 name字段的类型信息:create table stuinfo(_id integer primary key autoincrement, name varchar(20))
4-SQLiteException: near "null": syntax error (code 1)
12-14 06:15:20.384: E/SQLiteLog(609): (1) near "null": syntax error 12-14 06:15:20.424: E/SQLiteDatabase(609): Error inserting 12-14 06:15:20.424: E/SQLiteDatabase(609): android.database.sqlite.SQLiteException: near "null": syntax error (code 1): , while compiling: SQL语句语法错误 不能对一个 null 字段 进行操作 INSERT INTO stuinfo(null) VALUES (NULL) 应该修改为下面的形式 Insert into stuinfo('name')values(null);
5-android.os.NetworkOnMainThreadException
如果你的设备是android4.0系统,进行网络操作必须放在一个子线程中完成。否则包错。android.os.NetworkOnMainThreadException
6-Only the original thread that created a view hierarchy can touch its views
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views. 不能在子线程中操作通过主线程(UIThread)创建的View
7-java.net.ConnectException: failed to connect to localhost/127.0.0.1
12-16 07:30:04.650: W/System.err(17949): java.net.ConnectException: failed to connect to localhost/127.0.0.1 (port 8080): connect failed: ECONNREFUSED (Connection refused) 2:如果我们进行网络操作测试的时候,不能直接写127.0.0.1或localhost ,需要写具体的ip地址
8-Invalid file name: must contain only [a-z0-9_.]
在res 目录中的文件命名必须遵守 [a-z0-9_.]
9-ActivityManager: Warning: Activity not started, its current task has been brought to the front
因为模拟器中已经存在当前这个项目的apk程序了 在没有进行任何修改的前提下,重新部署apk。 解决办法: 在程序的任何对方进行任何的修改,总之让工程重新编译一下就可以,重新部署了。
10-java.lang.SecurityException: Permission Denial
执行某个需要对应权限的任务,但是没有在AndroidMesfist.xml中配置相应的权限,而引发这个异常 解决方案: 配置对应的权限就可以了 操作SDcard需要配置相应的权限 02-03 03:56:10.745: W/System.err(11494): java.io.FileNotFoundException: /sdcard/myfile.txt: open failed: EACCES (Permission denied) uses-permissionandroid:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
11-java.lang.NoClassDefFoundError
02-03 02:37:55.159: E/AndroidRuntime(19060): java.lang.NoClassDefFoundError: com.google.gson.stream.JsonReader 在android工程的lib中导入了需要的jar 但是原来的SDK版本可以获得工程的lib中的jar数据 在升级以后就不能再获得工程中的lib中的jar包了  因为android工程在安装以后会有一个默认的lib包存在 data/data/  解决办法: 把工程中的lib修改为libs与安装中lib文件夹区分 
12-java.net.SocketException: Permission denied
进行 网络数据 访问 一定要有网络范围权限 uses-permissionandroid:name="android.permission.INTERNET"/>
Android requires compiler compliance level 5.0 or 6.0. Found '1.7' instead. Please use Android Tools > Fix Project Properties.
目前android 开发使用的JDK还只支持1.6的 ,如果你使用是1.7的需要修改  
java.lang.Throwable: Warning: A WebView method was called on thread 'WebViewCoreThread'. All WebView...
webview_proxy(1438): java.lang.Throwable: Warning: A WebView method was called on thread 'WebViewCoreThread'. All WebView methods must be called on the UI thread. Future versions of WebView may not support use on other threads. 是因为在所以webView调用javascript的时候进行了一些耗时的操作 需要将耗时的操作放在一个线程中完成 wv.addJavascriptInterface(new Object() { publicvoidshow4(){ handler.post(new Runnable() { @Override publicvoid run() { wv.loadUrl("javascript:sayHello4()"); } }); } }, "obj2");
Unknown error: Unable to build: the file dx.jar was not loaded from the SDK folder!
ADT 和 SDK 不兼容
requestFeature() must be called before adding content
//设置本Activity带一个进度条效果(必须在setContentView()之前设置,否则报错) getWindow().requestFeature(Window.FEATURE_PROGRESS); setContentView(R.layout.activity_main);