Java的IO操作真是复杂,要经过以下几个步骤:
URL->HttpURLConnection->InputStream->InputStreamReader->BufferReader.readLine()
请看通用的类HttpDownloader:
package cc.ewings.download;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
public class HttpDownloader {
private URL url=null;
//本函数近适用于文本类文件的下载
public String download(String urlStr){
StringBuffer sb=new StringBuffer();
String line=null;
BufferedReader buffer = null;
try{
//URL->HttpURLConnection->InputStream->InputStreamReader->BufferReader.readLine()
url=new URL(urlStr);
HttpURLConnection urlConn=(HttpURLConnection) url.openConnection();
buffer = new BufferedReader(new InputStreamReader(urlConn.getInputStream()));
while((line=buffer.readLine()) != null){
sb.append(line);
}
} catch (Exception e){
e.printStackTrace();
} finally {
try{
buffer.close();
} catch(Exception e){
e.printStackTrace();
}
}
return sb.toString();
}
}
一 广播机制
1 创建一个继承自BroadReceiver的类MyReceiver:
package cc.ewings.BroadcastTest;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class MyReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context arg0, Intent arg1) {
// TODO Auto-generated method stub
System.out.println("received");
}
}
2 在主类中广播intent
package cc.ewings.BroadcastTest;
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;
public class BroadCastActivity extends Activity {
Button myBtn;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
myBtn=(Button) this.findViewById(R.id.myBtn);
myBtn.setOnClickListener(new MyListener());
}
class MyListener implements OnClickListener{
public void onClick(View arg0) {
// TODO Auto-generated method stub
Intent myIntent=new Intent();
myIntent.setAction(Intent.ACTION_EDIT);
BroadCastActivity.this.sendBroadcast(myIntent);
}
}
}
3 在Manifest中注册receiver
<receiver android:name=".MyReceiver">
<intent-filter>
<action android:name="android.intent.action.EDIT"/>
</intent-filter>
</receiver>
注: 在主Activity中也可以直接注册侦听,这样就不用再Manifest注册了:
package cc.ewings.BroadcastTest;
import android.app.Activity;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class BroadCastCodeDefine extends Activity {
Button myBtn;
MyReceiver receiver;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
myBtn=(Button) this.findViewById(R.id.myBtn);
myBtn.setOnClickListener(new MyListener());
receiver=new MyReceiver();
registerReceiver(receiver, new IntentFilter("cc.ewings.foodstar.refreshPage"));
}
@Override
protected void onPause() {
super.onPause();
unregisterReceiver(receiver);
}
class MyListener implements OnClickListener{
public void onClick(View arg0) {
// TODO Auto-generated method stub
System.out.println("broadcasting");
Intent myIntent=new Intent();
myIntent.setAction("cc.ewings.foodstar.refreshPage");
BroadCastCodeDefine.this.sendBroadcast(myIntent);
}
}
}
这样的好处是,可以关闭侦听。用Manifest中注册的,则关闭程序后仍然能收到侦听。
伪线程(其实还是用的主线程)
1 Handler myHandler=new Handler {handleMessage(){}}定义内部匿名handler
注:super.handleMessage(msg);//注意:不能带着一句,否则报错
2 Runnable myRunnable=new Runnable(){run(){}}实现线程
3 myHandler.post(myRunnable) 开始线程,myHandler.removeCallbacks(myRunnable);终止线程
4 myHandler.postDelayed(1000) 线程推迟执行
5 Thread.sleep(1000) 在run()里暂停线程
6 在Run里传递参数给handler,hanler里的handleMessage会接收到消息,也可以在其中再次开始线程。
Message msg=myHandler.obtainMessage();
msg.arg1=progress;
myHandler.sendMessage(msg);
真线程
用HandlerThread.getLooper()给继承自Handler的MyHandler,这样就可以开始一个新的线程了。MyHandler要起到两个作用:1 把looper传给父级;2 重写handleMessage来加上自己的逻辑
package cc.ewings.handlerTest;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.widget.Toast;
public class LooperAndBoundle extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
HandlerThread handlerThread=new HandlerThread("my thread");
handlerThread.start();
MyHandler myHandler=new MyHandler(handlerThread.getLooper());
Message msg=myHandler.obtainMessage();
Bundle b=new Bundle();
b.putString("name", "zhangsan");
b.putInt("age", 30);
msg.setData(b);
msg.sendToTarget();
}
class MyHandler extends Handler{
public MyHandler(Looper looper){
super(looper);
}
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
//super.handleMessage(msg);
Bundle data=msg.getData();
String name=(String) data.getString("name");
int age=(int) data.getInt("age");
Toast.makeText(LooperAndBoundle.this, "name: "+name+" age:"+age, Toast.LENGTH_LONG).show();
}
};
}
android开发接近尾声时需要打包apk,如果想sign,那就要生成一个keystore文件。但出现java.io.filenotfoundexception错误.
后来发现是因为jdk安装在了c盘,系统有保护,不让生成文件。于是把jdk挪到D盘,再用命令: keytool -genkey -alias android.keystore -keyalg RSA -validity 100000 -keystore android.keystore
一步一步按提示来,果然成功生成了keystore文件。Oh yeah!
在借鉴别人实例文件时,经常需要修改包名。这里介绍下在Eclipse下怎么修改包名:
1 项目名称上右键/Android Tools/Rename Application Package
2 在包上右键/Refactor/Rename
此处如果选中Rename subpackages和Update texual occurences in comments….则可以快速深入修改多个包,但也可能会导致manifest文件出点小问题。
3 批量查找原有包名
我习惯用dreameaver的查找功能,很好用,很彻底。
4 如果产生了多个R文件,删除原有的
5 清理项目文件
Project/Clean
List是比复杂的一个控件,主要复杂在是适配器(Adapter)的构建,它需要一个List、一个单独的View和另外一些参数。
下面是一个例子:
main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<ListView
android:id="@id/android:list"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:drawSelectorOnTop="false"
android:scrollbars="vertical"
/>
</LinearLayout>
list.xml,注意设置LinearLayout的格式,不然会很难看
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="5dip"
>
<TextView
android:id="@+id/user_name"
android:layout_width="150dip"
android:layout_height="30dip"
android:singleLine="true"
android:textSize="10pt"
/>
<TextView
android:id="@+id/user_ip"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="10pt"
/>
</LinearLayout>
主程序,注意继承的是ListActivity而不是Activity
package cc.ewings.test;
import java.util.ArrayList;
import java.util.HashMap;
import android.app.ListActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.Toast;
public class ListTest extends ListActivity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ArrayList> list = new ArrayList>();
HashMap map1=new HashMap();
HashMap map2=new HashMap();
HashMap map3=new HashMap();
map1.put("user_name", "adam");
map1.put("user_ip","192.168.0.1");
map2.put("user_name", "eva");
map2.put("user_ip","192.168.0.2");
map3.put("user_name", "yoyo");
map3.put("user_ip","192.168.0.3");
list.add(map1);
list.add(map2);
list.add(map3);
SimpleAdapter adapter=new SimpleAdapter(this,list,R.layout.list,new String[]{"user_name","user_ip"},new int[]{R.id.user_name,R.id.user_ip});
this.setListAdapter(adapter);
}
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
// TODO Auto-generated method stub
super.onListItemClick(l, v, position, id);
Toast.makeText(this,"position="+position, Toast.LENGTH_SHORT).show();
}
}
ProgressBar分为两种,由style来区分,style的写法是在太奇怪了,估计用20便也记不住:
<ProgressBar
android:id="@+id/bar1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
style="?android:attr/progressBarStyleHorizontal"
android:visibility="gone"
/>
<ProgressBar
android:id="@+id/bar2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="?android:attr/progressBarStyle"
android:visibility="gone"
/>
下面是一段简单的progressBar使用示例
class clickListener implements OnClickListener{
public void onClick(View v) {
// TODO Auto-generated method stub
if(i==0){
bar1.setVisibility(View.VISIBLE);
bar2.setVisibility(View.VISIBLE);
} else if(i
在XX之上/下/左/右
android:layout-above
android:layout-below
android:layout-toLeftOf
android:layout-toRightOf
与XX 基线/底/左/右/顶对齐
android:layout-alignBaseline
android:layout-alignBottom
android:layout-alignLeft
android:layout-alignRight
android:layout-alignTop
如果值为true,那么与父控件底/左/右/顶对齐
android:layout-alignParentBottom
android:layout-alignParentLeft
android:layout-alignParentRight
android:layout-alignParentTop
如果值为true,那么居中
android:layout-centerHorizental
android:layout-centerInParent
android:layout-centerVertical
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Please input"
android:id="@+id/label"
/>
<EditText
android:id="@+id/input"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="@id/label"
/>
<Button
android:id="@+id/ok"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="OK"
android:layout_below="@id/input"
android:layout_alignParentRight="true"
/>
<Button
android:id="@+id/cancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Cancel"
android:layout_below="@id/input"
android:layout_toLeftOf="@id/ok"
/>
</RelativeLayout>