别的类能通过sendBroadcast()方法收到intent.有两种方式注册一个receiver,一种是动态注册:context.registerReceiver().另一种是静态注册即:通过写<receiver>标签到AndroidManifest.xml.如果你在Activity.onResume()方法里注册一个receiver,你应该反注册它在Activity.onPause().(当pause的时候,你将收不到intent),不要反注册在Activity.onSaveInstanceState()方法里,因为它不会被call,如果用户返回。
        有两个主要的broadcast类能收到:
常规的broadcast:用context.sendBroadcast()方法发送,异步完成。这时所有的broadcast运行在一个没有定义的命令上在同一时间,但是这是很有效率的,同时也意味着接收者不能用这结果或者阻止APIs包含在这。
命令模式的broadcast:用context.sendOrderedBroadcast方法发送,一次交付给一个receiver, 并且每个receiver依次执行,它能传值给下一个receiver. 或者它能完全的阻止broadcast为了使它不能通过其它的receiver. 命令receiver依照优先级运行,同样的优先级将运行在一个任意的命令上。
        甚至在常规的broadcast情况下,系统也许在一些情况下也是一次交付给一个broadcast。特殊情况下,对于接收者也学要求创建一个新的进程,为了避免加载新进程的系统一个仅仅运行一次,在这种情况下,然而,不是命令模式的broadcast仍然不能返回结果或者阻止他们的broadcast.
注意,尽管intent类被用于发送和收到那些broadcast,但是与启动一个Activity是完全不一样的。当用startActivity方法的时候,接收者是没有方法看到或者获得intent的。同样当你广播一个intent,你将永远都不能发现或者开启一个Activity.这 两个操作在语义上是非常不同的:开启一个Activity是前台操作,广播一个intent是一个后台操作。
       Receiver的生命周期
       一个接收者仅仅有效的时间是从被call到执行onReceive(Context, Intent)方法,只要执行过这个方法,系统就会被完成并且不在活动。
重要的一点是你能完成你想做的在onReceive(Context, Intent)方法里。任何要求异步操作都不是有效的,因为你将需要返回值从那个方法处理那个异步操作,但是,在那个点上BroadcastReceiver将不再活动。
在特殊情况下,你也许不能展现一个dialog或者绑定一个服务在BroadcastReceiver里,对于前者,你应该用NotificationManager替代,对于后者,你能用Context.startService()启动一个service.
posted @ 2011-05-05 15:48 AndrewHan 阅读(593) 评论(2) 编辑

前几天我在做android程序的时候,由于一些错误,导致我emulator出错,再运行的时候就会报:emulator: ERROR: the user data image is used by another emulator. aborting。后来我check了一下,我总结了两种方式来解决这种问题:

第一种是:打开C盘下的users --> your login name --> .android --> avd --> your name of avd, 然后你就会发现有几个文件夹名字是以.lock结尾,你需要做的就是把这些文件夹删除,重启一下你的emulator, 再运行你的程序就没问题了。

第二种:打开dos控制器,在里面输入adb kill-server,然后再输入adb start-server,两个指令搞定,然后你就能顺利的运行你的程序了。

以上两种方法,你喜欢哪种就用哪种,不过,我推荐用第二种,方便,快捷。不用重启那个虚拟机,启动那个东西实在是太慢了。

posted @ 2011-05-02 16:34 AndrewHan 阅读(747) 评论(0) 编辑

AIDL服务只支持有限的数据类型,因此,如果用AIDL服务传递一些复杂的数据就需要做更一步处理。AIDL服务支持的数据类型如下:

1.Java的简单类型(int、char、boolean等)。不需要导入(import)。

2.String和CharSequence。不需要导入(import)。

3.List和Map。但要注意, List和Map对象的元素类型必须是AIDL服务支持的数据类型。不需要导入(import)。

4.AIDL自动生成的接口。需要导入(import)。

5.实现android.os.Parcelable接口的类。需要导入(import)。

以下是需要import进行导入的操作。

Step 1:

先建立一个IMyService.aidl文件:

package org.aidl.service;
import org.aidl.service.Product;

interface IMyService{
//in 表示这个值被客户端设置;out 表示这个值被服务器设置;inout表示这个值既能被客户端设置,又能被服务器设置。
Map getMap(in String country, in Product product);
Product getProduct();
}

Step 2:

编写Product类:

package org.aidl.service;

import android.os.Parcel;
import android.os.Parcelable;

public class Product implements Parcelable{
private int id;
private String name;
private float price;

public static final Parcelable.Creator<Product> CREATOR = new Parcelable.Creator<Product>() {

@Override
public Product createFromParcel(Parcel in) {
return new Product(in);
}

@Override
public Product[] newArray(int size) {
return new Product[size];
}
};

public Product(){

}

public Product(Parcel in){
readFromParcel(in);
}

public void readFromParcel(Parcel in) {
id
= in.readInt();
name
= in.readString();
price
= in.readFloat();
}

@Override
public void writeToParcel(Parcel dest, int flags){
dest.writeInt(id);
dest.writeString(name);
dest.writeFloat(price);
}

@Override
public int describeContents() {
return 0;
}

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 float getPrice() {
return price;
}

public void setPrice(float price) {
this.price = price;
}

public static Parcelable.Creator<Product> getCreator() {
return CREATOR;
}
}

Step 3:

建立一个Product.aidl文件,并输入以下内容:

parcelable Product;

Step 4:

编写一个MyService类:

package org.aidl.service;

import java.util.HashMap;
import java.util.Map;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;

public class MyService extends Service {

public class MyServiceImpl extends IMyService.Stub{

@Override
public Map getMap(String country, Product product)
throws RemoteException {
Map map
= new HashMap<String, String>();
map.put(
"country", country);
map.put(
"id", product.getId());
map.put(
"name", product.getName());
map.put(
"price", product);
return map;
}

@Override
public Product getProduct() throws RemoteException {
Product product
= new Product();
product.setId(
1234);
product.setName(
"汽车");
product.setPrice(
31000);
return product;
}


}

@Override
public IBinder onBind(Intent arg0) {
return new MyServiceImpl();
}

}

Step 5:

在AndroidManifest.xml文件中配置MyService类,代码如下:

<service android:name=".MyService">
<intent-filter>
<action android:name="org.aidl.service.IMyService" />
</intent-filter>
</service>

上面是server端,以下是client端:

首先,你应该把IMyService.java和Product.java文件复制到客户端工程,IMyService.java文件不能直接拷,你应该先在client项目中建一个存放IMyService.aidl跟server端一样的包,然后把IMyService.aidl文件拷到那个包里,这样程序会自动给你创建一个IMyService.java文件。

现在可以在Activity里创建并调用服务了,代码如下:

package org.aidl.client;

import org.aidl.service.IMyService;

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.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class Main extends Activity implements OnClickListener{
private IMyService myService = null;
private Button btnInvokeAIDLService;
private Button btnBindAIDLService;
private TextView textView;
private ServiceConnection serviceConnection = new ServiceConnection()
{

@Override
public void onServiceConnected(ComponentName name, IBinder service)
{
myService
= IMyService.Stub.asInterface(service);
btnInvokeAIDLService.setEnabled(
true);

}

@Override
public void onServiceDisconnected(ComponentName name)
{

}
};

public void onClick(View view)
{
switch (view.getId())
{
case R.id.btnBindAIDLService:
bindService(
new Intent("org.aidl.service.IMyService"),
serviceConnection, Context.BIND_AUTO_CREATE);
break;

case R.id.btnInvokeAIDLService:
try
{
String s
= "";
s
= "Product.id = " + myService.getProduct().getId() + "\n";
s
+= "Product.name = " + myService.getProduct().getName()
+ "\n";
s
+= "Product.price = " + myService.getProduct().getPrice()
+ "\n";

s
+= myService.getMap("China", myService.getProduct()).toString();
textView.setText(s);
}
catch (Exception e)
{

}
break;
}

}

@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
btnInvokeAIDLService
= (Button) findViewById(R.id.btnInvokeAIDLService);
btnBindAIDLService
= (Button) findViewById(R.id.btnBindAIDLService);
btnInvokeAIDLService.setEnabled(
false);
textView
= (TextView) findViewById(R.id.textview);
btnInvokeAIDLService.setOnClickListener(
this);
btnBindAIDLService.setOnClickListener(
this);
}
}

好了,你在运行的时候,先绑定AIDL服务,然后再调用服务,这样的话,你就会发现一些从服务器端读的数据。就写到这吧!晚安 for me!

posted @ 2011-03-22 01:12 AndrewHan 阅读(1604) 评论(0) 编辑

  我在写这篇文章之前,我对Java内部类也不是很清楚,只知道简单的应用。前几天有个朋友问我怎么理解Java内部类,我当时就有点傻了,想了半天也没有说出来,我想,如果让大家来回答这个问题,大家该怎么回答呢?我估计,总有一些人回答不上来的,或者说回答的不够完整。我特意查了查,自己又总结了总结,在这给大家分享一下。 在说之前,我先列出几个问题:

    1.外部类(非主类)通过怎样的方式访问内部类?

    2.内部类能不能访问主类私有的属性,为什么?

    3.内部类能不能继承别的类和接口?

    4.内部类能不能是static的?

    5.在主类的方法里面可不可以定义内部类?

    6.初始化主类的时候是不是也把内部类给初始化了?为什么?

    7.怎样写一个匿名的内部类?

  我目前想到的就这些,在我给大家陈述之前,希望大家好好想想,再往下看:

  第一个问题:外部类是怎样引用内部类的?这个问题,我想,可能有的人就会这样写:

  这是内部类:InnerClass.

1 public class MainClass {
2
3 public class InnerClass{
4 public String name = "name";
5
6 public String getName() {
7 return name;
8 }
9
10 public void setName(String name) {
11 this.name = name;
12 }
13 }
14 }

  以下是引用:

 

1 public class CheckClass {
2 public static void main(String[] args) {
3 InnerClass innerClass = new InnerClass();
4 System.out.println(innerClass.getName());
5 }
6 }

  如果这样写的话,会报编译错误。那么为什么会报错呢?因为在Java的设计中,如果想访问一个类的内部类,你必须通过宿主类去取它,然后,再对它进行操作,Java就是想这样把内部类给封闭起来的,好吧,正确的写法,我给大家贴出来:

  以下是内部类的写法:

  

1 public class MainClass {
2 public InnerClass getInnerClass() {
3 return new InnerClass();
4 }
5
6 public class InnerClass {
7 public String name = "name";
8
9 public String getName() {
10 return name;
11 }
12
13 public void setName(String name) {
14 this.name = name;
15 }
16 }
17 }

  如果你想访问Java内部类,你必须先拿到它的宿主类,这样你才能对内部类进行操作:

 

1 public class CheckClass {
2 public static void main(String[] args) {
3 MainClass mainClass = new MainClass();
4 System.out.println(mainClass.getInnerClass().getName());
5 }
6 }

  这样的话,编译就不会报错了。

 

 

 

  好了,该回答第二个问题了,就是内部类能不能访问宿主类的私有属性?回答是可以的。如果,你会看JVM的源码的话,你就会看到,在编译内部类调用主类私有变量时,会把它们转换成一种特殊的符号,JVM会把这种符号解析成公有的,然后让内部类调用。代码很简单,我就不贴了。

  接着回答第三个和第四个问题:就是内部类能不能继承别的类和接口?内部类能不能是static的?为什么不能,当然可以,这些并没有什么约束。你自己可以试一下。

  该第五个问题了:在主类的方法里面可不可以定义内部类?其实,这个问题,在我回答第一个问题的时候,已经把答案告诉了大家,就是在getInnerClass()方法里面,不就是new了一个内部类吗。

  第六个问题:初始化主类的时候是不是也把内部类给初始化了?为什么?这个嘛,如果反过来说就对了,因为如果,你想调用内部类,你就得初始化它的主类,因此,你在初始化内部类时就初始化了主类,但是,你初始化主类,如果不是显示的去初始化,你就不可能初始化它的内部类,尽管内部类是在主类的里面。如果,你有时间,你可以到编译的主类文件去看看。

  最后一个问题就是:怎样写一个匿名的内部类?如果大家搞过Java Swing或者Android开发,这个问题对你来说很简单,因为在随便的一些事件里,你就可以定义一个匿名的内部类,然后实现它的方法。不过,为了让更多的人明白,我把代码贴出来,以下是我的代码:

  这是要实现的那个接口:

1 public interface SuperInterface {
2 public void print();
3 }

  以下是主类的代码:

1 public class MainClass {
2
3 public SuperInterface print(){
4
5 return new SuperInterface(){
6
7 public void print() {
8 System.out.println("Hello Anonymity Interface");
9 }};
10 }
11 }

  其实上面的一段代码就是一个匿名内部类,为什么叫匿名内部类呢?因为,你没有给那个内部类起名字,而是直接实现那个接口,所以叫匿名内部类。

  好吧,我看写的也不少了,不过,可能我还会有疏漏的地方,希望大家能参与进来共同讨论。

 

 

  

 

posted @ 2010-12-26 17:06 AndrewHan 阅读(2943) 评论(4) 编辑

  安装Android 2.3有两种方法:1.从官方直接下载Android 2.3 SDK。 2.从SDK 2.2更新到2.3。

  在这,我就不说第一种了,没什么可说的。我就说说第二种吧。

  我是在Windows下的android-sdk-windows里更新的,并没有去Eclipse更新,我就给大家说说我更新的步骤吧:

  第一步:打开你的Android SDK and AVD Manager,先别急着下载什么的,因为你现在什么也下载不了,因为你必须先在Setting里面的Misc下面勾上Force https://......sources to be fetched using http://....这一项。看下面的截图:

    

  第二步:现在你可以点击Available packages选项了。然后,把那些需要更新的东东都打上对勾,再点击Install Selected按钮。然后,按照它的指示进行操作就行了,挺简单的。下面是截图:

    

  第三步:当你上面的工作做完后,你会发现在你的C:\android-sdk-windows\tools目录下并没有adb.exe这个可执行文件。并且当你打开Eclipse时,有关Android的插件会报错。这时你就应该这样做:首先,改一下你的环境变量,把原来的C:\android-sdk-windows\tools改成C:\android-sdk-windows\platform-tools。其次,把C:\android-sdk-windows\platform-tools目录下的adb.exe,AdbWinApi.dll,AdbWinUsbApi.dll 这三个文件拷到你C:\android-sdk-windows\tools目录下,然后把其它文件都拷贝到C:\android-sdk-windows\platforms\android-9\tools目录下,这时你就有疑问了,在C:\android-sdk-windows\platforms\android-9 这个目录下并没有tools文件夹,这时就需要你建一个新的文件夹,把它们放到里面。到这,大部分工作已经完成,现在你可以重启你Eclipse了,不过它会提示你更新Android插件,这时,你按照提示做就OK了。

  下面是我成功安装后,Android 2.3的界面:

  

  看上去也没太大的变化啊!不过图标变的好看多了。好吧,写到这,也就写完了,如果大家有什么问题,可以问我,我会尽量回答的。

posted @ 2010-12-12 00:50 AndrewHan 阅读(2882) 评论(1) 编辑
摘要: 搞Android有一段时间了,但是并没写过有关Android的博客,今天给大家介绍一下SharedPreferences。  使用SharedPreferences保存key-value对的步骤如下:  (1)使用Activity类的getSharedPreferences方法获得SharedPreferences对象,其中存储key-value的文件的名称由getSharedPreference...阅读全文
posted @ 2010-12-08 14:28 AndrewHan 阅读(3528) 评论(2) 编辑
摘要: 这是最后一篇有关内存管理的文章,其实内存管理有许多技巧和方式,在这,我给大家介绍一下。 (1)要尽早的释放无用对象的引用。如果,该对象不用了,你可以把它设置为null。但要注意,如果该对象是某方法的返回值,千万不要这样处理,否则你从该方法中得到的返回值永远为空,而且这种错误不易被发现,因此这时很难及时抓住、排除NullPointerException异常。(2)尽量少用finalize函数。因为它会加大GC的工作量,因此尽量少用finalize方式回收资源。  (3)如果需要使用经常用到的图片,可以使用soft应用类型(也就是转换为软引用类型),它可以尽可能将图片保存在内存中,供程序调用,而不阅读全文
posted @ 2010-12-07 22:38 AndrewHan 阅读(946) 评论(0) 编辑
摘要: 我们知道类中的静态变量在程序运行期间,其内存空间对所有该类的对象实例而言是共享的,为了节省系统内存开销、共享资源,应该将一些变量声明为静态变量。通过下面的例子,你就会发现有什么不同。代码一:[代码]代码二:[代码]我想大家应该发现上面那两个类的区别了吧!代码一会在内存中保存20000个weeks的副本,而代码二则在内存中保存1个weeks的副本,然后共享该副本,这样的话就不会造成内存的浪费。虽然静态的变量能节约大量的内存,但是并不是所有的地方都适合用,建议大家在下列条件都符合的情况下,尽量用静态变量:(1)变量所包含的对象体积较大,占用内存较多。(2)变量所包含的对象生命周期较长。(3)变量所阅读全文
posted @ 2010-12-07 21:52 AndrewHan 阅读(1228) 评论(1) 编辑
摘要: 上次说到了JVM的垃圾回收机制和JVM中对象的生命周期,今天给大家讲个方法,叫做析构方法finalize,我想搞过C++的人都知道,而且是内存管理技术中相当重要的一部分。但是,在Java中好像没有这个概念,这是因为,理论上JVM负责对象的析构(销毁与回收)工作,finalize是Object类中的一个方法,并且是protected,由于所有的类都继承了Object对象,因此,就都隐式的继承了改方法,不过可以重写这个方法,如果重写此方法,最后一句必须写上super.finalize()语句,因为finalize方法没有自动实现递归调用。那我们在什么时候要重写它呢?当有一些不容易控制并且非常重要的阅读全文
posted @ 2010-12-06 11:50 AndrewHan 阅读(1337) 评论(5) 编辑
摘要: 最近在看Java优化这方面的书,那必然会涉及到内存管理,我想和大家共同提高,于是写出来,如果有问题,希望能提出来,共同进步嘛!呵呵,不说这些了,好,现在开始你的知识之旅吧! 在做Java开发的时候常用的JVM内存管理有两种,一种是堆内存,一种是栈内存。堆内存主要用来存储程序在运行时创建或实例化的对象与变量,例如:我们通过new MyClass()创建的类MyClass的对象。而栈内存则是用来存储程序代码中声明为静态(或非静态)的方法。下面我给大家举个例子:代码就拿上面的例子来说,放在栈内存中的有:main,makeThings,放在堆内存中有:Test,list,object。JVM中对象的生阅读全文
posted @ 2010-12-04 16:53 AndrewHan 阅读(1308) 评论(2) 编辑