一、反编译
二、
三、布局
四、加背景、布局
五、布局
六、弹出对话框
七、LayoutInFlater、适配器
八、自动完成文本框、时间日期拾取器
九、拖动条、 星际评分条、进度条、视图
十、消息提示框与对话框、Toast、notification、Activity跳转配置
十一、多个Activity之间使用
十二、Fragment 碎片
十三、
十四、
十五、Intent
十六、使用字符串资源、颜色资源、尺寸资源、布局文件、数组资源、使用菜单资源、安卓国际化、设置透明度
十七、
十八、gradle、预定义的Content Provider、查询数据、增加记录、增加新值、批量更新记录、删除记录、自定义Content Provider
十九、线程
二十、service学习:Started(启动)、Bound(绑定);
二十一、绑定式启动服务
二十二、通过Http访问网络
二十三、 ArrayAdapter 、SimpleAdapter
二十四、
一、反编译
1 、安装了反编译工具 jad net.sf.jadclipse_3.3.0.jar 或者在help install software http://feeling.sourceforge.net/update/2 、生成excel 读取Excel里面的数据搞定 这里使用的是jxl.jar
二、
1、小米2s在安模拟器里面DDMS里面没显示 拨号模式下按 *#*#717717#*#*
2、1、在Eclipse中,选择Window > Preference;
2、从左侧的菜单中,选择Android项;
3、设置SDK Location,点Browse选择SDK的安装根目录;
3、UI的四种布局
线性布局、表格布局、帧布局、相对布局
三、
1 线性布局
android:orientation 排列方式 可选 vertical、horizontal水平
android:gravity 设置布局管理器内组件的对齐方式 top bottom left right right|bottom
android:layout_width android:layout_height 属性是ViewGroup.LayoutParams所支持的XML属性
设置组件的基本宽度 fill_parent、match_parent、wrap_content(该组件的宽度恰好能包裹它的内容)
android:id属性用于为组件指定一个id属性
android:background 为组建设置背景 android:background="#FFFFFFFF"
<Button android:text="按钮1" android:id="id+@/button1"></button>
四、
安卓里面加背景是 android:background="@drawable/ic_name";
表格布局 TableLayout继承了LinearLayout 支持的XML属性 productbrand/toList
android:collapseColums 设置需要被隐藏的列的列序号
android:shrinkColums 设置允许被收缩的列的列序号
android:stretchColums 设置允许被拉伸的列的列序号
帧布局 FrameLayout
android:foreground 设置该帧布局容器的前景图像
android:foregroundGravity 定义绘制前景图像的gavity属性,即前景图像显示的位置
五、
android:scaleType="centerCrop" CENTER_CROP 按统一比例缩放图片(保持图片的尺寸比例)便于图片的两维(宽度和高度)等于或者大于相应的视图的维度
android:layout_above="" android:layout_below="" android:layout_toRightOf="" android:layout_toLeftOf="" // 与哪边对齐 android:layout_alignTop="" android:layout_alginLeft=""
<TextView /><EditView android:inputType="textPassword"/> EditText login=(EditText)findViewById(R.id.login);String loginText=login.getText().toString()
Toast.makeText(MainActivity.this, "用户名: " + name + ", 密码: " + password, Toast.LENGTH_SHORT).show();//在屏幕上显示下然后就消失了 一定要记得有show()方法 不然没反应
Alt+上下左右 可以移动代码
安卓里面 edit.getText().toString();这些一定要写在监听事件的执行函数里面 不然拿不到数据 下次注意
按钮 分两种<Button/> <imgButton> android:src="@drawable/login" android:onClick="" android:background="#000"
<RadioButton/> <RadioGroup <RadioButton/><RadioButton/>/>
sex.getChildCount();可以得到所有数目 然后if(sex.getChildAt(i).isChecked()){sex.getChildAt(i).getText()};
六、
CheckBox cb1=(CheckBox)findViewById(R.id.music);
cb1.setOnCheckedChangeListener(listener);
//记得前面要加CompoundButton. 不然默认成其它的RadioGroup
privarte CompoundButton.OnCheckedChangeListener listener = new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
// TODO Auto-generated method stub
CheckBox box = (CheckBox) buttonView;
Toast.makeText(getApplicationContext(),
"获取的值:" + isChecked + "xxxxx" + box.getText(),
Toast.LENGTH_LONG).show();
}
};
图像视图
<Imageview android:maxWidth="180px" android:maxHeight="180px" android:adjustViewBounds="true" android:scaleType="fieEnd">
七、
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder.setTitle("登陆成功");
// builder.setMessage("用户名:"+name+"密码:"+password);
// 通过LayoutInflater来加载一个xml的布局文件作为一个View对象
View view = LayoutInflater.from(MainActivity.this).inflate(R.layout.activity_main2, null);
// 设置我们自己定义的布局文件作为弹出框的Content
builder.setView(view);
builder.setPositiveButton("确定", new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface arg0, int arg1) {
Toast.makeText(MainActivity.this, "用户名: " + name + ", 密码: " + password, Toas.LENGTH_SHORT).show();
}
});
<Spinner></Spinner>列表选择框 创建有2种方式 第一种通过XML配置 第二种通过适配器对象创建
1、列表选择框 在xml文件里面一定要写成大写 不能写成<spinner></spinner> 这样就会报错
<Spinner android:entries="@arrays/ctype"></Spinner> <? xml version="1.0"><resources><string-array name="ctype"><item>身份证</item><item>学生证</item></string-array></resources></xml>
spinner.getSelectedItem(); //得到选择的值
2、通过创建适配器的模式
得到资源文件
Resources res=getResources();
String[] ss=res.getStringArray(R.array.ctype);
//第一种 创建 通过ArrayAdapter来创建 这里是通过java文件中使用字符串数组创造
//记得这个地方要学MainActivity.this 而不是this 记得加Android.
ArrayAdapter<String> adapter=new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_spinner_item, ctype);
//设置下拉样式
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner2.setAdapter(adapter);
//第二种创建 通过数组资源文件创建适配器
// ArrayAdapter<CharSequence> adapter1=ArrayAdapter.createFromResource(MainActivity.this, R.array.ctype, android.R.layout.simple_dropdown_item_1line);
// adapter1.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
// spinner3.setAdapter(adapter1);
<ListView></ListView>
是不可以listView.getSelectedItem()拿到值的
final ListView lv=(ListView) findViewById(R.id.listView1);
//1 过资源文件创建适配器对象
// ArrayAdapter<CharSequence> adapter=ArrayAdapter.createFromResource(MainActivity.this, R.array.listView, android.R.layout.simple_list_item_1);
// lv.setAdapter(adapter);
lv.setOnItemClickListener(new OnItemClickListener(){
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
// TODO Auto-generated method stub
String result=arg0.getItemAtPosition(arg2).toString();
Toast.makeText(MainActivity.this, "changeValue"+result,Toast.LENGTH_SHORT).show();
// Toast.makeText(MainActivity.this, "value"+value,Toast.LENGTH_SHORT).show() ;
}});
//通过数组来创建适配器对象
Resources rs=getResources();
String[] arrays=rs.getStringArray(R.array.listView);
ArrayAdapter<String> adapter1=new ArrayAdapter<String>(MainActivity.this,android.R.layout.simple_list_item_single_choice,arrays);
lv.setAdapter(adapter1);
时间日期拾取器
时间拾取器<TimePicker/> 日期拾取器<DatePicker>
计时器 <Chronometer></Chronometer>
八、
自动完成文本框
<AutoCompleteTextView></AutoCompleteTextView>
ArrayAdapter adapter =new ArrayAdapter<String>(MainActivity.this,android.R.layout.simple_dropdown_item_1line,countries);
at.setAdapter(adapter);
String text=at.getText().toString();
进度条
<ProgressBar></ProgressBar>
<ProgressBar
android:id="@+id/pb1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="100"
style="@android:style/Widget.ProgressBar.Horizontal"></ProgressBar>
<ProgressBar
android:id="@+id/pb2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="?android:attr/progressBarStyleLarge"></ProgressBar>
九、
拖动条
<SeekBar></SeekBar> seebar.setOnSeekBarChangeingLister(listener);
星际评分条
<RatingBar></RatingBar>
选项卡
<TabHost></TabHost>
tabHost.addTab(tabHost
.newTabSpec("tab3")
.setIndicator("TAB3",
getResources().getDrawable(R.drawable.ic_launcher))
.setContent(R.id.textview3));
}
图像切换器
<ImageSwitcher> </ImageSwitcher>
网格视图
<GridView></GridView>
画廊视图
<Gallery></Gallery>
幻灯片图片浏览
十、
使用Toast
使用notification
Activity里面的跳转配置
//在这个地方要记得加上包 不然读不出来 显示错误 .DetailActivity 错了
<activity
android:icon="@drawable/ic_launcher"
android:name="com.mingrisoft.DetailActivity"
android:label="详细"></activity>
十一、
在MainActivity中使用
Intent intent=new Intent(MainActivity.this,其它类.class);
Bundle bundle=new Bundle();
bundle.setCharSequence("name",name);
也可以封装一个实体对象
bundle.setSerializable("Student",student);
intent.putExtra(bundle);
startActivity(intent);
如果调用另外一个Activity并返回结果 startActivityForResult(intent,CODE);
还需要从写 public void onActivityResult(int requestCode,int resultcode,intent data){
if(requestCode==CODE&&resultcode==CODE){
}
}
在新的Activity里面
Intent intent=getIntent();
Bundle bundle=intent.getExtras();
Student student=(Student)bundle.getSerializable("student");
String name=bundle.getString("name");
如果调用另外一个Activity并返回结果
设置返回的结果码,并返回调用该Activity的Activity
setResult(0X717,intent);
finish();
这样就可以显示图片了
imageView.setImageResource(imageId[position]);
十二、
android:id="@+id/id_ly_bottombar"
android:layout_width="fill_parent"
android:layout_height="55dp"
android:layout_alignParentBottom="true"
layout="@layout/bottombar" />
Fragment 碎片
这个地方是写成“@id/id_ly_bottonmbar”
而不是“@+id/dd” 要注意
<FrameLayout
android:id="@+id/id_content"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_above="@id/id_ly_bottombar"
android:layout_below="@id/id_fragment_title" />
requestWindowFeature 的学习
十四、
FragmentManager fm=getFragementManager();
FragmentTransaction ft=fm.beginTransaction();
Fragement weixin=new ContentFragment();
ft.replace(R.id.id_content,weixin);
ft.commit();
十五、
Intent
动作(action)
数据(Data)
种类(Category)
额外(Extras)
标记(Flags)
Intent 分为显示和隐示
显示的Intent 通过组件名称来指定目标组件 用于应用程序的内部消息
隐示的Intent 不指定组件名称 用于激活其它应用程序中的组件
android:textColor="@android:color/black"
android:textSize="25px"
显示调用 1.Intent intent = new Intent(); intent.setClass(A.this,B.class); //intent.setClassName("com.view","com.view.B");前者是A的包名,后者是B的代包类名
startActivity(Intent);
隐式调用:private static String MY_ACTION = "com.view.my_action";
Intent intent = new Intent(); intent.setAction(MY_ACTION);
或者// Intent intent = new Intent(MY_ACTION);
startActivity(Intent);
隐式的话需要在AndroidManifestl.xml里面配置
<activity android:name="包名.类名">
<intent-filter>
<action android:name="com.view.my_action"/>
<intent-filter/>
</activity>
十六、
<Resources>
<string name="hello">hello</string>
</Resources>
getResources().getString(R.string,introduce);
android:text="@string/introduce"
颜色资源
getResources().getColor(R.color.tittle);
android:textColor="@color/title"
<Resources>
<color name="tittle">#66ff0000</color>
</Resources>
尺寸资源
<dimen name="title">24px</dimen>
textview.setTextSize(getResources().getDimension(R.dimen.title));
android:textSize="@dimen/title"
布局文件
image.xml
<include layout="@layout/image"></include>
数组资源
<resources>
<string-array name="listItem">
<item>hello</item>
<item>yingwei</item>
<item>word</item>
</string>
</resources>
getResources.getStringArray(R.array.listItem);
<style name="tittl">
<item name="android:textSize">48px</item>
</style>
<TextView
sytle="@style/title"></TextView>
customers.xml文件
<customers>
<customer name="wgh" tel="2222222" email="mingrisoft@mingirosdd"></customer>
<customer name="wg1h" tel="2222222" email="mingrisoft@mingirosdd"></customer>
<customer name="wgh3" tel="2222222" email="mingrisoft@mingirosdd"></customer>
</customers>
解析
StringBuiler sb=new StringBuilder();
XmlResourcesParser xrp=getResources().getXml(R.xml.custoners);
while(xrp.getEventType()!=XmlResourceRarser.END_DOCUMENT){
if(xrp.getEventType()==XmlResourceRarser.START_TAG){//判断是否为标记开始
String name=xrp.getName();//判断标记名
if(tagName.equals("customer")){//如果标记名字是customer
sb.append("姓名"+xrp.getAttributeValue(0)+"");
sb.append("联系电话"+xrp.getAttributeValue(1)+"");
}
}
xrp.next();//下一个标记
}
String value=sb.toString();
使用菜单资源
registerForContextMenu(tv);//为文本框注册上下文菜单
从写 onCreateContextMenu();
安卓国际化
分别创建名称为(values-zh-rCN)(value-zh-rTW)(value-en-rUS)
设置透明度
<style name="">
<item name="android:alpha">0.95</item>
</style>
十七、
看安卓项目代码
十八、
Content Provider学习
每个Content Provider提供公共的URI(使用uri类包装)来唯一表示其数据集,
content://com.mingrisoft.employeeprovider/dba/001
content://标准的前缀
com.mingrisoft.employeeprovider URI的authority部分,用于标识该Content Provider
/dba/ Content Provider的路劲部分
/001 被请求的特定记录的ID值
预定义的Content Provider
安卓提供了很多预定义的Content Provider(声音、视频、图像、联系人)
Browser:读取活修改书签,浏览历史或网络搜索
CallLag:查询或者更新通话历史
Contacts:获取、修改、或者保存联系人信息
LiveFolders:由Content Provider 提供内容的特定文件夹
MediaStore:访问声音、视频和图片
Setting:查看蓝牙设置
SyncStateContract:用于使用数据组账号关联数据的ContentProvider约束
UserDictionary:在可预测文本输入时,提供用户定义单词给输入法使用
查询数据
ContentResovler.query()或Activity.managedQuery()方法
增加记录
ContentResolver.insert();
增加新值
ContentValue.put();
批量更新记录
ContentResolver.update();
删除记录
ContentResolver.delete();
查询手机里面联系人的名字和id
private String[] columns={Contacts._ID,Contacts._DISPLAY_NAME};
private String gerQueryData(){
StringBuilder sb=new StringBuilder();
ContentResolver resolver=getContentResolver();
Cursor cursor=resolver.query(Contacts.CONTENT_URI,columns,null,null,null);//查询记录
int idIndex=cursor.getColumnIndex(columns[0]);//获取id索引
int displayIndex=cursor.getColumnIndex(columns[1]);//获取name索引
for(cursor.moveToFirst();!cursor.isAfterLast();cursor.moveToNext()){
int id=cursor.getInt(idIndex);
String displayName=cursor.getString(displayNameIndex);
sb.append(id+":"+displayName+"\n");
}
cursor.close();//关闭Cursor
return sb.toString();
}
要记得在AndroidMainfest文件中增加读取联系人记录的权限,代码如下
<uses-permission android:name="android.permisson.READ_CONTACTS">
自定义Content Provider
十九、
创建线程方法2钟
1、Thread threa=new Thread(new Runable(){
@Override
public void run(){
}
});
2.
public class MainActivity implements Runable(){
@Override
public void onCreate(Bundle savedInstanceState){
}
@Override
public void run(){
}
}
中断线程
thread.interrupt();
threda=null;
Handler消息传递机制 来实现在新创建的线程中操作UI界面
一个Handler对应一个Looper对象,一个Loopre对象对应一个MessageQueue
Looper 对象用来为一个线程开启一个消息循环
1、主线程中创建线程
Handler handler=new Handler();
2 非主线程创建
Looper.prepare(); //初始化Looper对象
Handler handler1=new Handler(){
public void handleMessage(Message msg){
Log.i("Looper",String.valueOf(msg.what));
}
};
Message m=handler1.obtainMessage(); //获取一个消息
m.what=0x11; //设置Message的what属性值
handler1.sendMessage(m); //发送消息
Looper.loop(); //启动Looper
Message类的简介
二十、
2种服务
1、Started(启动)
2、Bound(绑定);
重要方法
onStartCommand();
onBind();
onCreate();
onDestroy();
组建调用startService()方法启动服务(onStartCommand()方法被调用)
组件调用bindService()方法启动服务(onStartCommand()方法不被调用)
需要在配置文件里面声明全部的Service,在Application中添加<Sercice>
<Service android:enabled="true" //是否能被系统实例化
android:exported="true" //其他应用程序是否能调用服务
android:icon="drawable resource" //服务的图标
android:label="" //服务名称
android:name="" //里面写包名 必须指定
android:permission="" //实体必须包含的权限名称
android:process="" > //服务运行的进程名称
</Service>
1、创建启动式服务
1、Service :
2、IntendService :
IntentService:这是Service类的子类,它每次使用一个工作线程来处理全部启动请求,在不必要同时处理多个请求时候,这是最佳选择
仅需要实现onHandleIntent()方法 该方法接受每次接受启动请求的Intent以便完成后台任务
1、通过继承Service类
2、通过继承IntentService类
这里面有个onHandleIntent(Intent intent ){}需要从写
二十一、
2、绑定式启动服务
1、继承Binder类 这个地方一定要注意 在AndroidMainfest.xml文件里面的<application></application>里面加上<service andorid:name=""/>
相关代码
如果服务仅用于本地应用程序并且不必垮进程工作,开发人员可以实现自己的Binder类作为客户端提供访问服务端公共方法。
package com.example.think.binder;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import java.util.Random;
/**
* Created by Think on 2015/8/30.
*/
public class LocalService extends Service{
private final IBinder binder=new LocalBinder();
private final Random generator=new Random();
class LocalBinder extends Binder{
public LocalService getService(){
return LocalService.this;
}
}
@Override
public IBinder onBind(Intent intent) {
return binder;
}
public int getNum(){
return 520;
}
}
package com.example.think.binder;
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.widget.Button;
import android.widget.Toast;
/**
* Created by Think on 2015/8/30.
*/
public class MainActivity extends Activity {
private LocalService localService;
private boolean boo=false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final Button button=(Button)findViewById(R.id.showTime);
final Button button1=(Button)findViewById(R.id.button2);
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
System.out.println("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
Toast.makeText(MainActivity.this, "success", Toast.LENGTH_SHORT).show();
}
});
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
System.out.print("boo"+boo);
if(boo){
if(localService==null){
System.out.println("localService is null");
}else{
System.out.println("localService is not null");
int num=localService.getNum();
System.out.println("num"+num);
Toast.makeText(MainActivity.this, "num" + num, Toast.LENGTH_SHORT).show();
}
}
}
});
}
@Override
protected void onStop() {
super.onStop();
if(boo){
unbindService(connection);
boo=false;
}
}
@Override
protected void onStart() {
super.onStart();
Intent intent=new Intent(this,LocalService.class);
bindService(intent,connection, Context.BIND_AUTO_CREATE);
}
private ServiceConnection connection=new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
LocalService.LocalBinder binder=(LocalService.LocalBinder)service;
localService=binder.getService();
boo=true;
System.out.println("has go to ServiceConnetion");
}
@Override
public void onServiceDisconnected(ComponentName name) {
boo=false;
}
};
}
2 使用Messenger类需要服务与远程进程通信,可以通过Messenger来为服务提供接口,该技术允许不使用ALDL执行进程间通信(IPC)
Handler 是属于 android.os.Handler这个包里面的 要注意
package com.example.think.binder;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.support.annotation.Nullable;
import android.widget.Toast;
import java.util.logging.Handler;
/**
* Created by Think on 2015/8/30.
*/
public class MessengerService extends Service{
static final int HELLO_WORD=1;
class IncomingHandler extends android.os.Handler{
@Override
public void handleMessage(Message msg) {
switch(msg.what){
case HELLO_WORD:
Toast.makeText(getApplicationContext(),"HELLO WORD",Toast.LENGTH_SHORT).show();
break;
default:
super.handleMessage(msg);
}
}
}
final Messenger messenger=new Messenger(new IncomingHandler());
@Nullable
@Override
public IBinder onBind(Intent intent) {
Toast.makeText(getApplicationContext(),"Binding",Toast.LENGTH_SHORT).show();
return messenger.getBinder();
}
}
package com.example.think.binder;
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.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
/**
* Created by Think on 2015/8/30.
*/
public class MainActivity extends Activity {
// private LocalService localService;
// private boolean boo=false;
private Messenger messenger=null;
private boolean bound=false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final Button button=(Button)findViewById(R.id.showTime);
final Button button1=(Button)findViewById(R.id.button2);
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(!bound)return;
Message message=Message.obtain(null,MessengerService.HELLO_WORD,0,0);
try {
messenger.send(message);
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
// button.setOnClickListener(new View.OnClickListener() {
// @Override
// public void onClick(View v) {
// System.out.print("boo"+boo);
// if(boo){
// if(localService==null){
// System.out.println("localService is null");
// }else{
// System.out.println("localService is not null");
// int num=localService.getNum();
// System.out.println("num" + num);
// Toast.makeText(MainActivity.this, "num" + num, Toast.LENGTH_SHORT).show();
// }
// }
// }
// });
}
@Override
protected void onStop() {
super.onStop();
// if(boo){
// unbindService(connection);
// boo=false;
// }
if(bound){
unbindService(connection1);
bound=false;
}
}
@Override
protected void onStart() {
super.onStart();
// Intent intent=new Intent(this,LocalService.class);
// if(boo) bindService(intent,connection, Context.BIND_AUTO_CREATE);
bindService(new Intent(this,MessengerService.class),connection1,Context.BIND_AUTO_CREATE);
}
// private ServiceConnection connection=new ServiceConnection() {
// @Override
// public void onServiceConnected(ComponentName name, IBinder service) {
// LocalService.LocalBinder binder=(LocalService.LocalBinder)service;
// localService=binder.getService();
// boo=true;
// System.out.println("has go to ServiceConnetion");
// }
// @Override
// public void onServiceDisconnected(ComponentName name) {
// boo=false;
// }
// };
private ServiceConnection connection1=new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
messenger=new Messenger(service);
bound=true;
}
@Override
public void onServiceDisconnected(ComponentName name) {
messenger=null;
bound=false;
}
};
}
onStartCommand; 已经取代了onStart();
二十二、
通过Http访问网络
1 使用HttpURLConnetion访问网络
private String result="";
URl url=new URL("http://192.168.1.66:8801/index.jsp?content="+base64(content.getText(),toString().trim()));
HttpURLConnetion con=url.openConnection();创建一个HTTP连接
InputStreamReader in=new InputStreamReader(url.getInputStream());
String inputLine=null;
while((inputLine=in.readLine()!=null){
result+=inputLine;
}
in.close();
con.disconnect();
public String base64(String content){
content=Base64.encodeToString(content.getBytes("utf-8"),Base64.DEFAULT);
content=URLEncoder.encode(content);
return content;
}
String content=request.getParam("content");
//替换content中的加好,这是犹豫在进行URL编码时,讲“+”号转换成了%2B
content =content.replaceAll("%2B","+");
BASE64Decoder decoder=new BASE64Decoder();
content=new String(decoder.decodeBuffer("content","utf-8"));
get方式只适合发送大小在1024个字节内的数据
数据大的时候要用post
con.setRequestMethod("post");
2 使用HttpClient访问网络 apache组织提供的 主要有HttpGet和HttpPost和HttpResponse类
String url="http://192.1.66.808/blog/1.jsp?param=get";
HttpClient httpclient=new DefaultHttpClient();
HttpGet httpRequest=new HttpGet("url");
HttpResponse httpResponse;
httpResponse =httpclient.execute(httpRequest);
if(Httpresponse.getStatusLine().getStatusCode()==HttpStatus.SC_OK){
String result=EntityUtils.toString(HttpResponse.getEntity()); //EntityUtils的学习
}else{
result="请求失败";
}
//haracterSet为字符编码 可以是iso-8859-1,utf-8等编码名称
// charsequence为字符序列接口,即由字符构成的序列需要具备的功能
// String类型是Charsequence接口的实现,自然,所有使用charsequence字符序列接口类型的程序,都可以使用其不同的实现,常见的是String 类型,所以调用时大部分情况下输入的都是字符串
发送psot请求
HttpPost httpRequest=new HttpPost(url);
List<NameValuePair> params=new List<NameValuePair>();
params.add(new BasicNameValuePair("param","get");
params.add(new BasicNameValuePair("nickName",nickName.getText(),toString());
ameValuePair(简单名称值对节点类型)
HttpRequest.setEnity(new UrlEncodedFormEntity(params,"utf-8"));
SD卡上面写文件需要在在AndroidMainfesl.xml里面加入下面的东西
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
finish();关闭当前的activity
使用Web显示页面
安卓内置浏览器 使用了开源的WebKit引擎
WebView webView=(WebView)findViewById(R.id.vebView);
webView.loadUrl("http://192.168.66.8081/bbs/");
webview.getSettings().setSupportZoom(true); //放大缩小功能
webView.getSettings().setBuiltlnZoomcontrols(true);
加载html的方法 不会乱码
loadDataWithBaseURL(String baseURL,String data,String mimeType,String encoding ,String history);
让vebView支持javascript
webview.getSettings().setJavaScriptEnabled(true); //设置javaScript可用
webview.setWebChromeClient(new WebChromeClient()); //处理javaScript对话框
//处理各种通知和请求事件,如果不使用该句代码,讲使用内置浏览器访问页面
webView.setWebViewClient(new WebViewClient());
二十三、
一、 ArrayAdapter 支持泛型操作,最为简单,只能展示一行字。
public class ArrayAdapterActivity extends ListActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//列表项的数据 String[] strs = {"1","2","3","4","5"};
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,android.R.layout.simple_expandable_list_item_1,strs);
setListAdapter(adapter);
} }
总结 这种是继承了ListActivity,所以才有setLsitAdapter(adapter)这个方法,有了setListAdapter(adapter)就不要setContentView(R.^^^^);
public class MainActivity extends Activity {
private ListView listView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
listView=new ListView(this);
ArrayAdapter<String> adapter=new ArrayAdapter<String>(this,android.R.layout.simple_expandable_list_item_1,getData());
listView.setAdapter(adapter);
setContentView(listView);
}
public List<String> getData(){
ArrayList<String> data=new ArrayList<String>();
data.add("chenyu");
data.add("hehe");
data.add("nidongde");
data.add("dangdang");
return data;
}
总结 这个地方使用的是继承Activity 而不是ListActivity 不然会报错,还有就是setContentView(listView),放的是listView,而不是其它的东西。
二、 SimpleAdapter 扩展性最好,可以定义各种各样的布局出来,可以放上ImageView(图片),还可以放上Button(按钮),CheckBox(复选框)等等。
wrap_content:表示大小刚好足够显示当前控件里的内容
fill_parent将强制性让它布满整个屏幕或填满父控件的空白
layout_gravity 表示组件自身在父组件中的位置
gravity 表示组件的子组件在组件中的位置
还没有完,到时候再补上
Volley使用
Volley的网络请求父类为Request<T>,可以提供给开发者进行继承,同时也预置了几种开发中常用的请求类型,下边介绍两个:StringRequest和JsonObjectRequest。
为了更加贴近实际使用,下边将使用Volley与Cloudant进行通讯做示例。Cloudant是一家提供云服务业务的公司,其向开发者提供免费的云存储、云数据库服务。关于其注册等流程本文不做叙述,很简单的。直接从登录开始:
1. 申请网络请求队列
Volley的一个很大的特色,就是所有的网络请求无需开发者自己执行,而是在请求构造完成后扔到Volley的请求队列中,队列依次进行请求,这样就省去了很多麻烦,开发者也不用担心网络请求是否会冲突,是否会在主线程,这些烦心事Volley的网络队列都帮我们解决了。
一般来说,一个应用程序如果网络请求没有特别频繁则完全可以只有一个请求队列(对应Application),如果非常多或其他情况,则可以是一个Activity对应一个网络请求队列,具体情况具体分析。下边的代码展示了如何申请一个Volley网络请求队列:
RequestQueue mQueue;
mQueue = Volley.newRequestQueue(getApplicationContext());
2. 使用Volley登录Cloudant
假设已经成功注册,登录名foo,密码bar。
通过查阅Cloudant的登录认证文档:https://docs.cloudant.com/api/authn.html。可以发现Cloudant登录认证相关接口有三个:
这里我们使用POST方法进行cookie登录认证。结合上边假设的用户名和密码可知:
要访问的url为 foo.cloudant.com/_session
头信息为 Content-Type: application/x-www-form-urlencoded
参数为 name = foo, password = bar
若访问成功,我们就可以在网络回应中获取cookie,以备之后其他操作使用。显然,这个请求跟json毫无关系,应该使用StringRequest,StringRequest有两种构造方法:
public StringRequest(int method, String url, Listener<String> listener, ErrorListener errorListener)
public StringRequest(String url, Listener<String> listener, ErrorListener errorListener)
第二个方法只有GET请求才可以使用,第一个方法的method参数可以用来自定义请求类型,这里我们需要的是POST,所以应该使用第一个构造方法:
StringRequest request = new StringRequest(
Request.Method.POST,
"http://foo.cloudant.com/_session",
new Response.Listener<String>() {
@Override
public void onResponse(String s) { //收到成功应答后会触发这里
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError volleyError) { //出现连接错误会触发这里
}
}
);
上边的代码中,我们成功构造了一个StringRequest,其中已经包含了我们需要的POST和正确的URL,同时还添加了网络回应监听器。但是,还缺少文档要求我们的头信息和参数。StringRequest在构造中并不提供这些信息的定义,这也是与其他常用网络工具不同的地方,刚接触的同学可能会很不适用,通过复写StringRequest的两个方法就可以将这些信息放进去了。下边来完善这个请求:
StringRequest request = new StringRequest(
Request.Method.POST,
"http://foo.cloudant.com/_session",
new Response.Listener<String>() {
@Override
public void onResponse(String s) {
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError volleyError) {
}
}
) {
@Override
public Map<String, String> getHeaders() throws AuthFailureError { //设置头信息
Map<String, String> map = new HashMap<String, String>();
map.put("Content-Type", "application/x-www-form-urldecoded");
return map;
}
@Override
protected Map<String, String> getParams() throws AuthFailureError { //设置参数
Map<String, String> map = new HashMap<String, String>();
map.put("name", "foo");
map.put("password", "bar");
return map;
}
};
相比第一次我们的构造过程,这一次多了两个复写的方法来设置头信息和参数,很容易吧。这个时候请求基本完成了,但是却缺少另一个很重要的东西,我们的登录认证为的是拿回属于自己的cookie,如果不能获取cookie的话,多么正确的请求格式都是白费力气啊,想要拿到cookie一样也是通过复写另一个方法进行获取:
@Override
protected Response<String> parseNetworkResponse(NetworkResponse response) {
for (String s : response.headers.keySet()) {
if (s.contains("Set-Cookie")) {
mCookie = response.headers.get(s);
break;
}
}
return super.parseNetworkResponse(response);
}
在网络请求成功后,服务端返回应答信息,而我们所需的Cookie信息就在这些应答信息中,通过对应答信息的遍历查找,很方便就可以找到我们所需的信息了。到这里,我们的登录认证请求就构造完成了,最后需要做的就是将这个StringRequest扔到我们的请求队列中去:
mQueue.add(request);
网络通畅的情况下,很快就能够获取Cookie信息了。
3. 查看测试文档
在注册Cloudant成功后,Cloudant会在我们的帐号中创建一个默认数据库——crud,其中保存着一行测试数据welcome。
让我们用Volley来访问这条数据。查阅Cloudant API文档Documents相关可以发现:
通过简单的GET请求搭配正确的URL即可得到文件(数据)内容,当然,这一切的前提是我们已经掌握了正确的Cookie数据。那么,我们需要:
1. 请求头数据中包含正确的Cookie信息
2. 访问正确的URL
3. 请求类型:GET
假设通过上一步登陆认证后我们将Cookie信息保存在了mCookie字符串变量中。而我们需要访问的URL通过查阅文档也可以得出路径为 数据库名 + 文档名,即foo.cloudant.com/crud/welcome。万事俱备,使用StringRequest:
StringRequest request = new StringRequest(
"http://foo.cloudant.com/crud/welcome",
new Response.Listener<String>() {
@Override
public void onResponse(String s) {
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError volleyError) {
}
}
) {
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> map = new HashMap<String, String>();
map.put("Cookie", mCookie);
return map;
}
};
mQueue.add(request);
在onResponse中我们会收到welcome这条数据的json形式字符串:
简单的网络请求StringRequest完全处理得来,使用也比较简单,就介绍到这里。下边介绍JsonObjectRequest应用方法。
4. 使用JsonObjectRequest创建新数据
首先看一下JsonObjectRequest的构造方法:
public JsonObjectRequest(int method, String url, JSONObject jsonRequest, Listener<JSONObject> listener, ErrorListener errorListener)
public JsonObjectRequest(String url, JSONObject jsonRequest, Listener<JSONObject> listener, ErrorListener errorListener)
第一种方法参数以此为:请求方法,访问的URL,Json数据对象,请求成功监听器,请求失败监听器。
第二种构造方法中,若jsonRequest为空,则方法自动为GET,不为空则自动切换为POST,其他参数含义相同。
Cloudant的文档(https://docs.cloudant.com/api/documents.html)要求创建文档可以使用POST或PUT方法进行,所携带的数据均为json格式。这样以来,StringRequest就显得力不从心了,我们需要使用到Volley的另一个自带请求类型:JsonObjectRequest。下边以POST方式创建数据为例,通过查看Cloudant文档,可知:
1. 访问的URL path为数据库目录
2. Content-Type被要求为application/json
3. 携带的数据要求为json数据
既然方法要求为POST,我们又是创建数据,肯定数据内容不会为空,所以我们选择第二种构造方法。首先,创建一个Json对象:
JSONObject jsonObject = new JSONObject();
jsonObject.put("_id", "testinfo");
jsonObject.put("person", "foo");
jsonObject.put("phone", "bar");
在Cloudant数据存储系统中,id可以由开发者指定。接下来进行JsonObjectRequest的构造和请求:
JsonObjectRequest request = new JsonObjectRequest(
"http://foo.cloudant.com/crud",
jsonObject,
new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject jsonObject) {
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError volleyError) {
}
}
) {
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> map = new HashMap<String, String>();
map.put("Cookie", mCookie);
return map;
}
};
mQueue.add(request);
jsonObject数据不为空,所以请求方式自动切换为POST,url为所要创建数据所在的数据库所在路径,然后就是请求结果的监听器,最后别忘了将Cookie带上,否则会出现认证错误的。最后,将构造完成的请求丢进队列中,由Volley进行调度处理。这个时候不妨再回头看一看之前分析的请求所需要哪些元素,不难发现,Volley的json请求中,并没有对Content-Type进行特殊设定。JsonObjectRequest是继承于JsonRequest的,而JsonRequest已经帮我们完成了这个动作:
@Override
public String getBodyContentType() {
return PROTOCOL_CONTENT_TYPE;
}
PS:设置Content-Type也可以通过复写getBodyContentType这个函数,而不用总是麻烦的使用getHeader中的map进行设定,两种设定方式效果一致。而且也不用担心编码格式,因为默认就是utf-8的:
/** Charset for request. */
private static final String PROTOCOL_CHARSET = "utf-8";
/** Content type for request. */
private static final String PROTOCOL_CONTENT_TYPE =
String.format("application/json; charset=%s", PROTOCOL_CHARSET);