安卓主要由四层构成:
Applications 应用程序层
ApplicationFramework 程序框架层
Libraries 核心类库
LinuxKernel Linux内核
各目录作用:
add-ons android拓展库
docs android相关文档
extras android附加支持文件(驱动)
platforms androidSDK相关文件
platform-tools 存放工具平台
samples SDK自带的默认示例工程
sources api源代码
system-images 系统中用到的图片
temp 系统中临时文件
tools 各类工具
(android调试桥)ADB工具常用命令:
adb start-server 开启adb服务
adb device 列出可用的模拟器
adb logcat 查看日志
abd kill-server 关闭服务
adb shell 挂载到linux的空间
adb install <应用程序> 安装应用程序
adb -s <模拟器名称> install <应用程序> 安装到指定的模拟器
adb uninstall <程序包名> 卸载指定的应用程序
ApplicationName 应用名称
ProjectName 项目名
PackageName 包名
minimumRequiredSDK 最兼容的版本
TargetSDK 最匹配的版本
compilewith 那个版本SDK进行编译
Theme UI主题
src 所有java代码的地方
geb 自动生成R.java文件
Android4.1.1 用的SDK文件
assets 用于存放一些随陈旭打包的文件
bin 生成apk文件测试包
libs jar包
res 图片,布局,字符串
androidmanifese.xml 重新编译最高最低版本
proguardproject.txt 混淆代码工具
project.properties 安卓运行环境
MainActivity.java 文件
public class MainActivity extands Activity{
protected void oncreate(Bundle s){
super.onCreate(s); //记住布局
setContentView(R.layout.UI); //打开布局
}
}
布局的类型
一、相对布局(RelativeLayout)
android:layout_alignParentLeft 是否跟父布局左对齐
android:layout_alignParentTop 是否跟父布局顶部对齐
android:layout_alignParentRight 是否跟父布局右对齐
android:layout_alignParentBouttom 是否跟父布局底部对齐
android:layout_toRightOf 在指定控件右边
android:layout_toLeftOf 在指定控件左边
android:layout_above 在指定控件上边
android:layout_below 在指定控件下边
android:layout_alignBaseline 与指定控件水平对齐
android:layout_alignLeft 与指定控件左对齐
android:layout_alignRight 与指定控件右对齐
android:layout_alignTop 与指定控件顶部对齐
android:layout_alignBottom 与指定控件底部对齐
二、线性布局(LinearLayout)
android:orientation="vertical"; 垂直布局
android:orientation="horizontal"; 水平布局
三、表格布局(TableLayout)
TableRow 行数对象
android:stretchColumns="n" 为第多少列拉伸
android:layout_column="n" 列数属性
四、网格布局(GridLayout)
android:layout_gravity 对齐方向
android:columnCount="n" 网格列数
android:layout_column="n" 该控件在第几列
android:layout_rowSpan="n" 该控件占几行
android:layout_columnSpan 该控件占几列
五、帧布局(FrameLayout)
android:layout_width="dp" 占据的宽度
android:layout_height="dp" 占据的长度
六、绝对布局(AbsoluteLayout)
android:layout_x="dp" 所在横坐标的位置
android:layout_y="dp" 所在纵坐标的位置
各类控件属性
TextView 文本控件
EditText 编辑框
Button 普通按钮
RadioButton 单选按钮
android:drawableTop="@android:drawable/ic_med"设置文字上方的图片
ProgressBar 进度条(不可更改)
SeekBar 进度条(可通过滑动更改)
style="?android:attr/progressBarStylrHorizontal"设置进度条为条形(还有环形进度条)
OnSeekBarChangeListener //监听滑块位置
setMax() //设置进度条最大值
setProgress() //设置当前进度
getProgress() //获取当前进度
ListView 列表框
android:cacheColorHint //设置拖动的背景色
android:divider //设置分界线
android:dividerHeight //设置分割线高度
android:listSelector //设置选中时颜色
android:scrollbars //设置滚动条
android:fadeScrollbars //是否自动隐藏显示
样式调用:style="@style/TextStyle"
环境测试
一、Junit
<application><uses-library android:name="android.test.runner"/></application>
<instrumentation android:name="android.test.InstrumentationTestRunner" android:targetPackage="需要测试的包名称" />
assertEquals(期望值,真实值);
开始测试:Run As→Android Junit Test
二、LogCat
五种级别:Verbose黑色、Debug蓝色、Info绿色、Warming橙色、Error红色
Log.v||d||i||w||e显示全部信息||显示调试信息||一般信息||警告信息||错误信息显示
三、Toast
Toast.makeText(javaname.this,"信息",0||1).show();0表示短,1表示长
事件:
onKeyDown(int,event)对应键按下事件
onKeyUp(int,event)对应键松开事件
onTouchEvent(event)对应点击屏幕事件
Activity生命周期:
onCreate(Bundle s) 创建时执行
onStart() 可见时执行
onRestart() 回到前台,再见到时执行
onReause() 获取焦点时执行
onPause() 失去焦点时执行
onStop() 用户不可见进入后台时执行
onDestroy() 销毁时执行
不希望横竖屏幕时Activity被重建
android:configChanges="orientation|keyboardHidden|screenSize"
一直处于竖屏
android:screenOrientation="portrait"
一直处于横屏
android:screenOrientation="landscape"
点击事件的四种方法:
onClick指定方法名称
创建内部类实现OnClickListener接口
{...
b.setOnClickListener(new m());
}
private class m implements OnClickListener{
public void onClick(View v){
switch(v.getId()){
case R.id.b:
点击事件
break;
}
}
}
主类中实现OnClickListener
主类 implements OnClickListener
{...
b.setOnClickListener(this);
}
public void onClick(View v){
switch(v.getId()){
case R.id.b:
点击事件
break;
}
}
匿名内部类:
{...
b.setOnClickListener(
new OnClickListener(){
public void onClick(View v){
点击事件
}
}
);
}
Activity的启动模式:
<activity>中,设置android:launchMode="standard||singleTop||singleTask||singleInstance"
分别表示:默认启动方式,完全新建||重复利用||重用删上||重用仅存
Intent的调用:
显示调用(主要用于打开本应用Activity):
Intent i.setClassName("包名","包名+class名称");//异包调用
startActivity(i);//开启Activity
Intent i=new Intent(this,b.class); //同包调用
i.putExtra("key","value"); //传递字符串值
startActivity(Intent i); //打开这个Intent
Intent ii=getIntent();
String data=ii.getStringExtra("key");//调用的包中取出数据
如果传递多个数据,利用putExtras(Bundle);传递数据,Bundle.putString||Int("key","value")
多个数据接收,Intent ii=getIntent();
Bundle data=ii.getStringExtras();
String n=data.getString("key")
隐式调用(主要用于打开其他应用组件,自己的也可以):
清单文件中<intent-filter>
<action android:name="包名+class名称">
<category android:name="android.intent.category.DEFAULT" />
//默认的category会自动将这个category添加到Intent中
</intent-filter>
Intent i=new Intent();
i.setAction("name");
startActivity(i);//开启Activity
Intent回传数据
Intent i=new Intent(this,b.class);
startActivityForResult(Intent i,int n); //Intent,请求码
protected void onActivitResult(int requestCode,int resultCode,Intent data){
super.onActivityRequest(requestCode,resultCode,data);
String data=data.getStringExtra("key");
}
另一个java中
Intent i=new Intent();
i.putExtra("key","value"); //传输的密码和内容
setResult(int n,Intent i); //结果码,intent
finish(); //销毁当前Activity
数据存储的五种方式:
文件储存:以IO流的形式储存在本地文件中,分为内部储存,和外部储存。
内部储存:放在data/data/packagename/files/目录下,应用卸载时与之同炬
主要的方法:
openFileOutput(String name,int mode); //储存文件名,模式
MODE_PRIVATE只能被该文件读写
MODE_APPEND该文件内容可以追加
MODE_WORLD_READABLE可被其他文件读取
MODE_WORLD_WRITEABLE可被其他应用写入
openFileInput(String name); //打开的文件名称
外部储存:放在mnt/sdcard/目录下,属于永久储存
主要的方法:
Environment.getExternalStorageDirectory() //获取SD卡根目录
String Environment.getExternalStorageState() //检测外围设备是否可用
String n=Environment.getExternalStorageState()
n.equals(Enviroment.MEDIA_MOUNTED||BAD_REMOVAL||CHECKING)//以挂载||没挂载||正在检查
外部储存需要的权限:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />//写
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />//读
序列化:
XmlSerialize X=Xml.newSerializer(); //创建XmlSerializer对象
X.setOutput(fileOutputStream,"utf-8"); //设置文件编码方式
X.startDocument("utf-8",true); //写入XML文件标识
X.startTag(null,"persons"); //开始节点
X.attrribute(null,"key","value") //标签内写入
X.text("value"); //写入内容
X.endTag(null,"persons"); //结束节点
X.endDocument(); //结束
XML文件解析:DOM解析、SAX解析、PULL解析。适合较小的xml文件,消耗内存||解析超大的xml文件,不必等到加载结束显示,不存在占用内存,无法进行增删改查。||pull最常用android和javaee中
PULL解析
XmlPullParser.START_DOCUMENT //文档的开始
XmlPullParser.END_DOCUMENT //XML文档的结束
XMLPullParser.START_TAG //开始节点
XMLPullParser.END_TAG //结束节点
XmlPullParser pull=Xml.newPullParser(); //得到XmlPullParser对象
pull.setInput("文件名称","utf-8"); //文件的输入编码
int n=pull.getEventType(); //得到类型
while(n!=XmlPullParser.END_DOCUMENT){ //直到结束
switch(n){
case XMLPullParser.START_TAG:
if("name".equals(pull.getName())){
this.name=pull.nextText();
}
if("id".equals(pull.getName())){
this.id=pull.getAttributeValue(0);
}
···(XMLPullParser.END_TAG)
n=pull.next(); //获取类型给予n
}
}
SharedPreferences:以key/value键值对应形式保存,文件位置:data/data/packagename/shared_prefs
可储存数据类型:float、int、long、boolean、String、StringSet
SharedPreferences sp=context.getSharedPreferences(String name,int mode);//文件名、模式
MODE_PRIVATE只能被该文件读写
MODE_APPEND该文件内容可以追加
MODE_WORLD_READABLE可被其他文件读取
MODE_WORLD_WRITEABLE可被其他应用写入
常用方法(读取):
sp.contains(String key) //判断是否包含特定key的数据
sp.getAll() //获取全部key/value键值对应
sp.getBoolean(String key,boolean defValue) //获取key对应的Boolean值
(getInt||Float||Long||String||StringSet) //同理获取
sp.edit() //获取编辑器,返回Editor对象
常用方法(修改):
Editor np=sp.edit(); //得到编辑对象
np.putString("key","value"); //存入指定key的String||int||Float||Boolen||long值
np.putStringSet("key",Set<String> value) //存入指定key的set值
np.remove(key) //删除指定的key所对应的数据
np.clear() //清除所有数据
np.commit() //编辑结束后提交
SQLite:数据库数据位置位于data/data/packagename/database
SQLiteOpenHelper类 //用于创建数据库和数据库版本更新
常用方法:
SQLiteOpenHelper(Context context,String name,CursorFactory factory,int version)
分别代表:context、数据库名称、查询的结果集、数据库版本
onCreate(SQLiteDatabese db){ //创建数据库调用该方法
SQLiteDatabese类--常用方法:
db.insert(String table,String nullColumnHack,ContentValues values)
分别代表:表名、列名、values参数集合。用于添加一条记录
db.query(String table,String[] columns,String selection,String[] selectionArgs,String groupBy,String having,String orderBy)
分别代表:表名、列名数据、查询条件、查询参数值、分组、聚合函数、排序。用于查询
db.rawQuery(String sql,String[] selectionArgs)
分别代表:查询sql语句、查询条件
db.update(String table,ContentValues values,String whereClause,String[] whereArgs)
分别代表:代表想要更新数据的表名、代表想要更新的数据、满足该whereClause子句的记录将会被更新、用于为whereArgs子句传递参数。用于修改特定数据
db.delete(String table,String whereClause,String[] whereArgs)
分别代表:table:代表想删除数据的表名。
whereClause:满足该whereClause子句的记录将会被删除。
whereArgs:用于为whereArgs子句传入参数。
例:
删除person_inf表中所有人名以孙开头的记录
int result=db.delete("person_inf","person_name like ?",new String[]{"孙_"});
db.execSQL(String sql,Object[] bindArgs)
执行一条带占位符的SQL语句
db.close() //关闭数据库
}
onUpgrade(SQLiteDatabese db,int oldVersion,int newVersion)
分别代表:数据库名称,旧版本,新版本 更新版本时调用
getReadable||WritableDatabase() //创建或打开一个只读||读写的数据库
Cursor接口(返回值,相当于ResultSet)
常用方法:
moveToNext() //移动光标到下一行
getInt(int columnIndex) //获取列
getColumnIndex(String columnName) //返回列索引值,不存在则返回-1
getString(int columnIndex) //获取指定列的字符串
moveToFirst() //移动光标到第一行
moveToLast() //移动光标到最后一行
moveToPrevious() //移动光标到上一行
moveToPosition(int position) //移动光标到指定位置
getCount() //返回Cursor中的行数
getPosition() //返回当前Cursor的位置
getColumnName(int columnIndex) //根据列的索引值获取列的名称
getColumnNames() //获取Cursor所有列的名称数组
sqlite3工具查看数据库:
adb shell //挂载到linux的空间
cd data/data/packagename/database //进入文件夹
sqlite3 databasename //操作的数据库
select*from tablename //打开表
ListView适配器(Adapter)
BaseAdapter抽象方法
常用方法:getCount()//得到Item的总数
getItem(int position)//根据position得到Item对象
getItemId(int position)//根据position得到Item的ID
getView(int,View,ViewGroup)//视图位置
SimpleAdapter只能适配Checkable、TextView、ImageView三种类型,继承BaseAdapter
拥有BaseAdapter的全部方法,使用时直接在其构造方法中传入参数即可
SimpleAdapter(Context,data,int,String[],int[])
Context用于布局转换为View对象
data类似Map类的数据集合
int资源布局的id
String[]Map集合里面的key
int[]item布局对应的控件id
ArrayAdapter继承BaseAdapter,适用于TextView
拥有BaseAdapter的全部方法,使用时直接在其构造方法中传入参数即可
ArrayAdapter(Context,int,int,T[])
Context用于布局转换为View对象
int资源布局的id(0,1)
int对应控件的id(R.id.a)
T[]需要适配的数组
ContentProvider:内容提供者,主要用于保存和检索数据
ContentProvider抽象类//用于创建内容提供其他应用访问
使用前清单文件注册:
<provider
android:name="cn.itcast.db.PersonDBProvider"//继承于ContentProvider类的全路径名称
android:authorities="cn.itcast.db.personprovider">//访问路径
可选参数配置:android:permission="mobile.permission.PROVIDER"
//其他应用访问时必须 加上权限<user-permission android:name="mobile.permission.PROVIDER" />
android:readPermission属性//使用后其他程序调用query()方法访问数据时需要权限
android:writePermission属性//使用后其他程序调用增删改查更改数据时需要权限
</provider>
ContentProvider主要方法:onCreate()//创建时调用
delete(uri,selection,String[])//根据uri删除指定条件下的数据
insert(uri,values)//根据传入的uri插入数据
query(uri,string[],string,string[],string)//根据传入的uri查询指定条件下数据
update(uri,values,selection,string[])//根据uri更新指定条件下数据
getType(uri)//返回uri代表数据的MIME类型
uri是由:scheme、authorites、path组成。scheme部分是"content://"前缀||authorites代表"cn.itcast.db.personprovider||path代表资源person根据需要的不同,动态改变"
uri对应的方法:Uri.parse(String str)//将字符串变成路径
UriMatcher用于匹配Uri的辅助类,主要的方法
UriMatcher(int code)//创建UriMatcher时调用,int通常指UriMatcher.NO_MATCH,不满足返回-1
addURI(String authority,String path,int code)//前两者分别代表Uri的半部分,后者代表返回码
match(uri)//匹配uri与addURI方法传入参数的code值,给予前面两个,返回code值
ContentResolver:访问内容提供者
Uri uri=Uri.parse("...");
ContentResolver r=context.getContentResolver();
Cursor c=r.query(uri,string[],string,string[],string);
String data=c.getString(int columnIndex)
c.close();
ContentObserver:内容观察者
ContentObserver(Handler h)//构造方法,h可为任意Handler对象
onChange(boolean selfChange)//当uri代表的数据发生修改时会调用该方法
使用该方法之前必须调用ContentResolver的notifyChange()方法,在ContentProvider中insert()update()delete()方法中
getContentResolver().notifyChange(Uri uri,ContentObserver cob);//分别uri、和观察者,不指定观察者可写null
BroadcastReceiver广播接收者
打电话时广播:
<receiver android:name="cn.itcast.MyBroadcastReceiver">//监听类路径
<intent-filter android:priority="20">//优先级,值越大,接收优先级越高(-1000~1000)之间
<action android:name="android.intent.action.NEW_OUTGOING.CALL">//受到监视的广播,此处是打电话广播
</intent-filter>
</receiver>
权限:<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
短信接收广播:
<receiver android:name="cn.itcast.MyBroadcastReceiver">//监听类路径
<intent-filter android:priority="20">//优先级,值越大,接收优先级越高(-1000~1000)之间
<action android:name="android.provider.Telephony.SMS_RECEIVED">//受到监视的广播,此处是短信接收广播
</intent-filter>
</receiver>
权限:<uses-permission android:name="android.permission.RECEIVE_SMS" />
开机广播:
<receiver android:name="cn.itcast.MyBroadcastReceiver">//监听类路径
<intent-filter android:priority="20">//优先级,值越大,接收优先级越高(-1000~1000)之间
<action android:name="android.intent.action.BOOT_COMPLETED">//受到监视的广播,此处是短信接收广播
</intent-filter>
</receiver>
权限:<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
继承BroadcastReceiver类,重写onReceive方法。
onReceive(Context c,Intent i)//当监听到广播事件时,调用该方法
注册常驻广播:当应用程序关闭后,接收到其他的应用发出的广播,该程序就会自动重新启动
<receiver android:name="cn.itcast.MyBroadcastReceiver">//上述类路径
<intent-filter android:priority="20">//优先级,值越大,接收优先级越高(-1000~1000)之间
<action android:name="android.provider.Telephony.SMS_RECEIVED">//受到监视的广播,此处是短信接收广播
</intent-filter>
</receiver>
注册非常驻广播:当应用程序关闭后,就不再起作用
MyBroadcastReceiver r=new MyBroadcastReceiver();//上述类
String a="android.provider.Telephony.SMS_RECEIVED";//受到监视的广播,此处是短信接收广播
IntentFilter intentFilter=new IntentFilter(action);//设置要过滤的广播
registerReceiver(r,intentFilter);//注册广播
注册非常驻广播需要解除广播,例如在onCreate()中注册广播,需要在onDestory()中解除广播
unrgisterReceiver(r);
自定义广播:
Intent i=new Intent();
i.setAction("www.itcast.cn");//定义广播的事件类型
sendBroadcast(i);//发送广播
接收广播可接收数据
<receiver android:name="cn.itcast.MyBroadcastReceiver">//广播接收者,可添加多个
<intent-filter>
<action android:name="www.itcast.cn">
</intent-filter>
</receiver>
onReceive(c,i){
String n=i.getAction;
}
广播类型:无序广播和有序广播,前者效率高,但无法被拦截,后者根据优先级接收广播,同优先级先安装应用优先结束
有序广播拦截广播调用方法abortBroadcast()即可使广播不再传播
sendOrderedBroadcast(i,null);//发送有序广播。intent,指定接收者,可强制接收广播,哪怕高级拦截了广播,一样可以接受到广播,可指定多个,(i,null,activ,01,02...);
利用广播开机自启:第一步,监听开机事件,自android3.0后,必须安装打开过的android软件才可以开机自启。
第二步,在监听方法中执行Intent i=new Intent(context,主函数.class);
i.setFlags(intent.FLAG_ACTIVITY_NEW_TASK);//指定Activity运行在任务栈中
context.startActivity(i);//启动该应用
一. intent.setFlags()方法中的参数值含义:
1.FLAG_ACTIVITY_CLEAR_TOP:跳转到的activity若已在栈中存在,则将其上的activity都销掉。
2.FLAG_ACTIVITY_NEW_TASK:跳转到的activity根据情况,可能压在一个新建的栈中。
3.FLAG_ACTIVITY_NO_HISTORY:跳转到的activity不压在栈中。
4.FLAG_ACTIVITY_SINGLE_TOP:目标activity已在栈顶则跳转过去,不在栈顶则在栈顶新建activity。
二.intent.setFlags()方法中参数的用例:
很多人使用startActivity时候,会碰到如下的异常:
Caused by: Android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
都知道,Context中有一个startActivity方法,Activity继承自Context,重载了startActivity方法。如果使用Activity的startActivity方法,不会有任何限制,而如果使用Context的startActivity方法的话,就需要开启一个新的task,遇到上面那个异常的,都是因为使用了Context的startActivity方法。解决办法是:Java代码中加一个flag,即intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)。这样就可以在新的task里面启动这个Activity了。
服务:能长期在后台运行且不提供任何界面
清单文件注册:(位于"</application>"之前)
<service android:name="cn.itcast.servicetest.myservice" />
启动方式:(服务不能主动启动,只能被调用)两种Context.startService()、Context.bindService()
Context.startService():使用起来相对方便,但不能进行数据交互
其他组件调用startService()方法→onCreate()→onStartCommand()→stopSelf()或者stopService()→onDestroy();
创建 第一次启动 运行中 自己调用关闭 其他组件调用关闭 销毁
例:Intent i=new Intent(this,myservice.class);
Context.startService(i); //开启服务
Context.stopService(i); //关闭服务
创建服务:public class myservice extends Service{ //继承Service抽象类
public IBinder onBind(Intent arg0){ //重写唯一的抽象方法
return null;
}
}
Context.bindService():可实现数据交互
其他组件调用bindService()方法→onCreate()→onBind()→unBindService()→onDestroy();
创建 第一次启动 运行中 客户通过此方法关闭(可对应多个客户,当全部客户都断开连接,此服务销毁) 销毁
例:Intent i=new Intent(this,myservice.class);
创建服务:public class myservice extends Service{ //继承Service抽象类
public IBinder onBind(Intent arg0){ //重写唯一的抽象方法,绑定服务
return new MyBinder();
}
class MyBinder extends Binder{
public void callMethodInService(){
...
}
}
public void onCreate(){super.onCreate();} //创建服务
public void boolean onUnbind(intent i){return super.onUnbind(i);}//解绑服务
}
链接服务:public class MyConn implements ServiceConnection{ //接入接口
public void onServiceConnected(ComponentName name,IBinder service){//当服务成功绑定时调用的方法
MyBinder myBinder=(MyBinder) service;//通过service传递参数
}
public void onServiceDisconnected(ComponentName name){ //当服务失去连接时调用的方法
}
}
MyConn myconn=new MyConn();
Context.bindService(intent,myconn,BIND_AUTO_CREATE); //intent,链接对象,flag表示没有就重新创建
Context.unbindService(myconn); //解绑服务
远程服务通讯:通过AIDL实现不同应用之间的绑定服务
第一步:创建AIDL文件
package 包名
interface 文件名{需要跨软件调用的方法...}
第二步:创建Service服务器端
public class myservice extends Service{
public IBinder onBind(Intent arg0){ //重写唯一的抽象方法,绑定服务
return null;
}
...其他方法任意
}
第三步:清单文件中配置
<service android:name=".myservice"> //配置服务器的java文件
<intent-filter>
<action android:name="com.yu.IMyService"/> //调用时用的action
</intent-filter>
</service>
第四步:客户端调用
复制alid文件至对应的包中,conn=new MyConn();
bindService(new Intent("com.yu.IMyService"), conn, BIND_AUTO_CREATE); //绑定服务
unbindService(conn); //解绑服务
private IService iService; //alid文件
iService.方法名() //调用其它应用方法
private class MyConn implements ServiceConnection{
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub
iService=IService.Stub.asInterface(service); //链接成功调用
}
@Override
public void onServiceDisconnected(ComponentName name) { //当服务失去连接时调用的方法
// TODO Auto-generated method stub
}
}
网络编程:UI线程不能访问网络,子线程不能根系UI界面。
Handler机制包括四个关键对象Message、Handler、MessageQueue、Looper
Message:可用于线程之间传递消息,不同的线程之间交换数据.
what、obj分别可携带整形数据和Object对象
Handler:用于发送消息【sendMessage()】和处理消息,最后会传递到Handler对象的handlerMessage()方法中
MessageQueue:消息队列,主要用来存放通过Handle发送的消息,每个线程中只会有一个MessageQueue对象
Looper:每个线程中MessageQueue的管家,调用Looper的loop()方法后将会无限循环,每当发现MessageQueue对象存在消息,就将他取出,并传递到Handler对象的handlerMessage()中,每个线程中只会有一个Looper对象,主线程中自带loop()方法,自动循环,子线程需要调用Looper.loop方法来开启消息循环。
Handler→发送消息→MessageQueue→利用Message携带消息发送至MessageQueue中→Looper→取出队列的消息处理→发送至Handler的handlerMessage()方法中
AsyncTask抽象类,异步处理机制,可从子线程切换到主线程。
class Down extends AsyncTask<Void,Integer,Boolean> //Params传入的参数,给予后台任务使用,Porgress进度显示进度单位,Result返回结果类型
主要方法:onPreExcute()后台任务执行之前调用
doInBackgroud(Params...)子线程中运行,可调用publishProgress(Porgress...)来更新UI
onProgressUpdate(Params...)如果在上述方法中调用了publishProgress(Porgress...)更新UI,本方法就会被调用
onPostExcute(Result)当doInBackgroud方法完毕时,并通过return返回参数,将传递到本方法当中,提示任务完成情况
asyncTask.execute("http://www.google.com");//可以通过此处传参数给AsyncTask,execute方法只能在UI线程里使用
HttpURLConnection访问网络
HttpURLConnection的基本用法:
<user-permission android:name="android.permission.INTERNET" /> //清单位置权限,任何方式访问网络都是这个权限
URL u=new URL("http://anlemusic.cn"); //设置URL
HttpURLConnection c=(HttpURLConnection)url.openConnection(); //根据URL发送HTTP请求
c.setRequestMethod("GET"); //设置请求方式
c.setConnectTimeout(5000); //设置超时时间
c.setRequestProperty("User-Agent","..."); //设置请求头User-Agent浏览器版本
c.getResponseCode(); //返回服务器返回码
InputStream i=c.getInputStream(); //获取服务器返回的输入流
读取流信息,获取服务器返回数据
c.disconnect(); //关闭http链接
HttpClient访问网络
主要方法:
DefaultHttpClient() //用于创建HttpClient对象
HttpGet(URL) //创建GET方式请求创建该类实例
HttpPost() //使用POST方式请求创建该实例
setParams(params) //HttpGet、HttpPost都具有此方法,用于设置请求参数
setEntity() //HttpPost可用设置请求参数
HttpClient.execute() //访问网络,获取HttpResponse对象
NameValuePair //关联参数的KEY
BasicNameValuePair //以Key,Value的形式存放参数的类
UrlEncodedFormEntity //将提交给服务器参数进行编码的类
HttpResponse //封装了服务器返回信息的类
HttpEntity //封装了服务返回数据的类
HttpClient http=new DefaultHttpClient(); //创建HttpClient对象
HttpPost httpPost=new HttpPost("网址"); //设置请求方式
List<NameValuePair> params=new ArrayList<NameValuePair>(); //创建一个NameValuePair的集合
params.add(new BasicNameValuePair("username","admin")); //添加参数
UrlEncodedFormEntity entity=new UrlEncodedFormEntity(params,"utf-8"); //给参数设置编码
httpPost.setEntity(entity); //设置参数
HttpResponse response=http.execute(httpPost); //获取HttpResponse对象
int code=response.getStatusLine().getStatusCode(); //获取状态码
if(code==200){ //访问成功
HttpEntity Entity=response.getEntity(); //获取httpEntity的实例
String re=EntityUtils.toString(Entity,utf-8); //设置编码格式
}
AsyncHttpClient访问网络 完美解决了UI线程不能访问网络
使用之前需要导入对应的夹包,本文件夹就有...此方式主要是对HttpClient再次包装.
AsyncHttpClient //用来访问网络的类
RequestParams //用于添加参数的类
AsyncHttpResponseHandle //访问网络后回调的接口
AsyncHttpClient client=new AsyncHttpClient(); //创建AsyncHttpClient实例
String path="访问的URL"; //设置拼接的URL
client.get(path,new AsyncHttpResponseHandle(){ //get的方式请求网络
public void onSuccess(String content){ //访问网络成功
super.onSuccess(content);
Toast.makeText(this,"请求成功"+content,0).show();
}
public void onFailure(Throwable error,String content){ //访问网络失败
super.onFailure(error,content);
Toast.makeText(this,"请求失败"+content,0).show();
}
});
AsyncHttpClient client=new AsyncHttpClient(); //创建AsyncHttpClient实例
String url="访问的URL"; //设置访问地址
RequestParams params=new RequestParams(); //用于添加参数的类
client.post(url,params,new AsyncHttpResponseHandle(){ //post的方式请求网络
public void onSuccess(int statusCode,Header[] headers,byte[] responseBody){ //访问网络成功
super.onSuccess(statusCode,headers,responseBody);
Toast.makeText(this,"请求成功"+new String(responseBody),0).show();
}
public void onFailure(Throwable error,String content){ //访问网络失败
super.onFailure(error,content);
Toast.makeText(this,"请求失败"+content,0).show();
}
});
SmartImageView控件,使用之前需要导入对应的夹包,本文件夹就有...此方法主要解决加载图片慢的问题.
<com.loopj.android.image.SmartImageView
android:layout_weight="1000"
android:id="@+id/id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
java文件中:SmartImageView siv=(SmartImageView)findViewById(R.id.id);
siv.setImageUrl("指定地址的图片",R.drawable.ic_error,R.drawable.ing);//网络图片没找到时显示的图片,正在加载的图片
多线程下载:首先获得服务器资源文件大小,然后再在本地创建一个大小与服务器一样的文件,接着在客户端开启若干个线程去下载服务器资源,每个线程下载自己对应的模块.
long l=conn.getContentLength(); //获取文件大小
RandomAccessFile r=new RandomAccessFile("文件名","类型"); //随机文件名+类型
r.setLength(l); //设置本地文件大小
threadCount=3; //设置线程数量
long blocksize=l/threadCount; //设置每个线程下载区块的大小
for(int id=1;id<=threadCount;id++){
long starPos=(id-1)*blocksize; //从starPos字节开始下载
long endPos=id*blocksize-1; //知道endPos字节结束
if(id==threadCount){
endPos=l;
new Down(starPos,endPos,id,path).start(); //开始下载
}
}
class Down extends Thread{
private long starPos;...
Down(long starPos,long endPos,long id,String path){
super();
this.starPos = starPos;....
}
public void run(){
conn.setRequestProperty("Range","bytes="+starPos+"-"+endPos); //请求部分数据
InputStream is=conn.getInputStream();
RandomAccessFile r=new RandomAccessFile("文件名","类型");
r.seek(startPos);
int len=0;
byte[] b=new byte[1024];
while((len=is.read(buffer))!=-1){
r.write(buffer,0,len);
}
is.close();
r.close();
}
}
传感器andrid.hardware.Sensor:
<uses-permission android:name="android.permission.VIBRATE" /> //震动
<uses-permission android:name="android.hardware.sensor.accelerometer" /> //加速度传感器
传感器信息的方法:
getName() //传感器名称
getVersion() //传感器版本
getvendor() //传感器制造商的名称
getType() //传感器类型
getPower() //传感器功率
传感器类型常量 内部整数值 中文名称
Sensor.TYPE_ACCELEROMETER 1 加速度传感器
Sensor.TYPE_MAGNETIC_FIELD 2 磁力传感器
Sensor.TYPE_ORIENTATION 3 方向传感器
Sensor.TYPE_GYROSCOPE 4 陀螺仪传感器
Sensor.TYPE_LIGHT 5 环境光照传感器
Sensor.TYPE_PRESSURE 6 压力传感器
Sensor.TYPE_TEMPERATURE 7 温度传感器
Sensor.TYPE_PROXIMITY 8 距离传感器
Sensor.TYPE_GRAVITY 9 重力传感器
Sensor.TYPE_LINEAR_ACCELERATION 10 线性加速度传感器
Sensor.TYPE_ROTATION_VECTOR 11 旋转矢量
Sensor.TYPE_RELATIVE_HUMIDITY 12 湿度传感器
Sensor.TYPE_AMBIENT_TEMPERATURE 13 温度传感器(4.0之前用Sensor.TYPE_TEMPERATURE)
获取所有传感器:
SensorManager sm=(SensorManager)getSystemService(Context.SENSOR_SERVICE); //获取传感器管理器
List<Sensor> allSensors=sm.getSensorList(Sensor.TYPE_ALL); //从传感器管理器中获取全部传感器列表
allSensors.size();//显示一共有多少个传感器
for(Sensor s:allSensors){
s.getName();//列出传感器名称
}
获取指定传感器:
SensorManager sm=(SensorManager)getSystemService(Context.SENSOR_SERVICE);
Sensor sensor=sm.getDefaultSensor(Sensor.TYPE_GRAVITY);//使用getDefaultSensor(int type)方法获取
if(sensor!=null){
//重力传感器存在
sensor.getName();
//获取传感器的供应商
sensor.getvendor();
}else{
//重力传感器不存在
}
传感器注册监听事件:
sm.registerListener(SensorEventListener listerner,Sensor sensor,int rate);
listerner:监听接口拥有两个方法,分别是:onSensorChanged(SensorEvent event)和onAccuracyChanged(Sensor sensor,int rate);前者在传感器发生变化时调用,后者在精确度不准确时调用。
Sensor sensor:表示传感器对象
int rate:表示传感器数据采样率:10ms、20ms、60ms、200ms,分别对应0,1,2,3,也可以用SensorManager.SENSOR_DELAY_FASTEST||GAME||UI||NORMAL
注销传感器:
protected void onDestroy(){
super.onDestroy();
sm.unregisterListener(listener);
listener=null;
}
Fragment:与Activity类似,一个Activity可以包含多个Fragment
Fragment生命周期:
添加Fragment→onAttach()→onCreate()→onCreateView()→onActivityCreated()→onStart()→onResume()→Fragment已激活→点击返回→onPause()→onStop()→onDestroyView()→onDestroy()→onDetach()→Fragment被销毁
onAttach():当Fragment和Activity建立关联时调用
onCreateView():为Fragment创建视图时调用
onActivityCreate():确保与Fragment相关联的Activity已经创建完成时调用
onDestroyView():Fragment视图被移除时调用
onDetach():Fragment与Activity解除关联的时候调用
public class NewFragment extends Fragment{
public View onCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState){
View v=inflater.inflate(R.layout.fragment,container,false);
return v;
}
}
<fragment
android:name="包.类"
android:id="@+id/id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
NewFragment f=new NewFragment(); //实例化Fragment对象
FragmentManager fm=getFragmentManager(); //获取FragmentManager实例
FragmentTransaction begin=fm.beginTransaction(); //获取FragmentTransaction实例
begin.add(R.id.id); //添加一个Fragment
begin.commit(); //提交
Fragment与Activity通讯
在布局中定义SettingListFragment对象
<SettingListFragment
android:id="@+id/id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
//activity调用fragment
SettingListFragment f=(SettingListFragment)getFragmentManager().findFragmentById(R.id.id);
在Fragment中获取Activity实例
MainActivity activity=(MainActivity)getActivity();//调用getActivity方法得到Context对象
Fragment与Fragment对象之间互相交流就是依靠Activity实例对象调用
附一:MUSIC
MediaPlayer常用方法:
setAudioStreamType() //指定音频文件类型
setDataSource() //设置要播放的音频文件位置
prepare() //播放之前准备工作
start() //开始播放
pause() //暂停播放
reset() //将其对象重置到刚刚创建的状态
seekTo() //从指定的位置开始播放音频 重新播放可m.seekTo(0);m.start();
stop() //停止播放音频
release() //释放资源
isPlaying() //判断当前是否在播放
getDuration() //获取音乐文件时长
getCurrentPosition() //获取当前播放音频位置
音乐播放流程:
m=new MediaPlayer(); //创建MediaPlayer播放器
m.setAudioStreamType(AudioManager.STREAM_MUSIC); //指定参数类型AudioManager.STREAM_MUSIC||RING||ALARM||NOTIFICTION音乐、响铃、闹钟、提示音
m.setDataSource(path); //指定路径
m.prepare(); //准备播放
mediaplayer.setOnPreparedListener(new OnPreparedListener(){ //检测扫描预处理
public void onPrepared(MediaPlayer mp) {
// TODO Auto-generated method stub
mediaplayer.start(); //开始播放
}
});
音乐源:
m.create(this,R.raw.xxx); //app内部
m.setDataSource("mnt/sdcard/1.mp3") //SD卡中文件
m.setDataSource("http://www.anlemusic.cn/2.mp3") //网络音频
网络音乐播放不同:m.prepareAsync(); //准备工作
m.setOnPreparedListener(new OnPreparedListener){ //检测扫描预处理
public void onPrepared(MediaPlayer player){
m.start(); //开始播放
}
}
SoundPool播放音频
SoundPool sound=new SoundPool(int maxStreams,int streamType.int srcQuality);//同时播放流的最大数量,流的类型AudioManager.STREAM_MUSIC,采样率转换质量,当前无效果可用0
Map<Integer,Integer> soundMap=new HashMap<Integer,Integer>(); //音乐Map
soundMap.put(0,sound.load(this,R.raw.dingdong,1)); //load()方法添加音乐文件
soundMap.put(0,sound.load(this,R.raw.ding,1));
sound.setOnLoadCompleteListener(new OnLoadCompleteListener(){
public void onLoadComplete(SoundPool sound,int sampleId,int status){
play(soundMap.get(0),(float)1,(float)1,0,0,(float)1.2); //id,左音量,右音量,优先级,loop循环次数,速率最低0.5·最高2·正常1.0
play(soundMap.get(1),(float)1,(float)1,0,0,(float)1.2);
}
});
附二:Video
VideoView视频播放
SurfaceView视频播放
setVideoPath() //设置要播放的视频文件位置
start() //开始或继续播放视频
pause() //暂停播放视频
resume() //视频重头开始播放
seekTo() //从指定位置开始播放视频
isPlaying() //判断当前是否正在播放视频
getDuration() //获取载入的视频文件的时长
stopPlayback() //停止播放视频
VideoView v=(VideoView)findViewById(R.id.video); //找到控件
v.setVideoPath("mnt/sdcard/apple.avi"); //加载视频
//v.setVideoURI("http://www.xxx.avi"); //网络视频加载
v.start(); //播放视频
视频控制器:
MediaController controller=new MediaController(context);
v.setMediaController(controller); //为VideoView绑定控制器
MediaPlayer和SurfaceView结合播放视频,前者用于播放声音,后者利用两个线程互相配合,完成动画
<SurfaceView
android:id="@+id/sv"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
SurfaceView view=(SurfaceView)findViewById(R.id.sv);
SurfaceHolder holder=view.getHolder();
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
holder.addCallback(new Callback(){
public void surfaceDestroyed(SurfaceHolder holder){
//销毁SurfaceHolder触碰事件
}
public void surfaceCareated(SurfaceHolder holder){
//创建SurfaceHolder触碰事件
}
public void surfaceChanged(SurfaceHolder holder,int format,int width,int height){
//大小发生变化时
}
});
MediaPlayer mediaplayer=new MediaPlayer();
mediaplayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaplayer.setDataSource("path");
mediaplayer.prepareAsync();
mediaplayer.start();
CountDownTimer cdt=new CountDownTimer((3000,1000){
public void onTick(long millisUntilFinished){
每隔1000ms执行一次
}
public void onFinish(){
3000ms之后执行
}
});
RelativeLayout rl=(RelativeLayout)findViewById(R.id.rl);
rl.setVisibility(View.INVISIBLE); //隐藏该控件
rl.setVisibility(View.VISIBLE); //显示该控件
附三:IMAGE
Bitmap类的常用方法:用于图像处理.
createBitmap(int width,int height,Config config) //创建位图,分别为宽度,高度,图片的配置信息
createBitmap(int colors[],int offset,int stride,int width,int height,Config config)
//使用颜色数组,创建一个指定宽高的位图,颜色数组个数为width*height,图片的配置信息
createBitmap(Bitmap src) //使用源位图创建一个新的Bitmap对象
createBitmap(Bitmap source,int x,int y,int width,int height) //从源位图的指定坐标开始挖去width宽的,height高的Bitmap对象
createBitmap(Bitmap source,int x,int y,int width,int height,Matrix m,boolean filter)
//从源位图的指定坐标开始挖取width宽的,height高的Bitmap对象,并按照Matrix规则进行变换
isRecycled() //判断Bitmap对象是否被收回
recycle() //回收Bitmap对象
Config c=Config.ARGB_4444; //config表示每像素多少字节,也就是画质,ARGB_4444两个字节、ARGB_8888四个字节
Bitmap b=Bitmap.createBitmap(200, 200, c);
BitmapFactory类常用方法:从不同数据源中解析,创建Bitmap对象
decodeFile(String pathName) //从指定文件中解析,创建Bitmap对象
decodeStream(InputStream is) //从输入流中解析,创建Bitmap对象
decodeResource(Resources res,int id) //根据给定的资源id,从指定资源中解析,创建Bitmap对象
Bitmap bitmap=BitmapFactory.decodeResource(getResources(),R.drawable.ic_launcher);
Paint类
Paint() //创建一个Paint对象
Paint(int flags) //创建Paint对象,指定属性
setARGB(int a,int r,int g,int b) //设置颜色,透明度,RGB,范围都是(0~255)
setColor(int color) //设置颜色
setAlpha(int a) //设置透明度
setAntiAlias(boolean aa) //设置是否使用抗锯齿功能,使用会使绘图速度变慢
setDither(boolean dither) //指定图像是否抖动处理,图像会更平滑,饱满,清晰
setShadowLayer(float radius,float dx,float dy,int color) //设置阴影,阴影角度,阴影在x轴y轴的距离,color阴影颜色
setTextAlign(Align align) //设置绘制文本时的文字对齐方式Align.CENTER、LEFT、RIGHT
setTextSize(float textSize) //设置绘制文本时字体大小
setFakeBoldText(boolean fakeBoldText) //设置文字是否为粗体
setXfermode(Xfermode xfermode) //设置图形重叠时处理方式,合并或者交集,并集,制作橡皮擦擦除效果
Paint p=new Paint();
p.setColor(Color.RED);
p.setShadowLayer(2,3,3,Color.GRAY)
Canvas类
使用之前需要继承View类,并且重写onDraw(Canvas canvas)方法
drawRect(Rect r,Paint pain) //使用画笔画出指定的矩形
drawOval(RectF oval,Paint pain) //使用画笔画出指定的椭圆
drawCircle(float cx,float cy,float radius,Paint paint) //使用画笔画出指定的半径的园
drawLine(float startX,float startY,float stopX,float stopY,Paint paint)//画直线
drawRoundRect(RectF rect,float rx,float ry,Paint paint) //画圆角矩形
class pictures extends View{
public pictures(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
Paint p=new Paint();
p.setColor(TRIM_MEMORY_BACKGROUND);
p.setShadowLayer(2, 3, 3, Color.BLUE);
Rect r=new Rect(40,40,200,100);
canvas.drawRect(r, p);
}
}
<com.example.xy.pictures
android:id="@+id/id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
Matrix类主要方法:用于添加特效
Matrix() //创建一个唯一的Matrix类
setRotate(float degress) //将Matrix对象围绕(0,0)旋转degress度
setRotate(float degress,float x,float y) //将Matrix对象围绕(x,y)旋转degress度
setScale(float sx,float sy) //对Matrix对象进行缩放,XY轴分别缩放比例
setScale(float sx,float sy,float x,float y) //对Matrix对象进行缩放,XY轴分别缩放比例,以(x,y)为轴心
setSkew(float sx,float sy) //让Matrix对象倾斜,X轴,Y轴,分别倾斜kx,ky
setSkew(float sx,float sy,float x,float y) //让Matrix对象倾斜,X轴,Y轴,分别倾斜kx,ky,以(x,y)为轴心
setTranslate(float dx,float dy) //让Matrix对象平移,(dx,dy)为Matrix为平移后的坐标
matrix m=new Matrix();
canvas.drawBitmap(bitmap,m,paint);
动画:外部文档有记载