Android中服务类似windows中的服务,服务一般没有用户界面操作,它运行于系统中不容易被用户发觉,可以使用它开发如监控之类的程序。服务的开发比较简单,如下:
第一步:继承Service类
public class SMSService extends Service{}
第二步:在清单文件中的<application>节点里对服务进行配置
<service android:name=”.SMSService”
服务不能自己运行,需要通过调用Context.startService()或Context.bindService方法启动服务。这两个方法都可以启动服务,但是它们的使用场合不同。
使用startService()方法启动服务,访问者与服务之间没有关联,即使访问者退出了,服务仍然运行。
使用bindService()方法启动服务,访问者和服务绑定在了一起,访问者一旦退出,服务也就终止,大有“不求同时生,但求同时死”的特点。
采用Context.startService()方法启动服务,只能调用Context.stopService()方法结束服务,服务结束时会调用onDestroy()方法。
一、本地服务
通过startService()和stopService()启动服务。适用于服务与访问者直接没有交互的情况。如果服务和访问者直接需要方法调用或参数传递,则需要使用bindService()和bindService()方法启动关闭服务。
采用Context.bindService()方法启动服务,在服务未被创建时,系统会先调用服务的onCreate()方法,接着调用onBind()方法。这个时候访问者和服务绑定在了一起。如果访问者要与服务进行通信,那么onBind()方法必须返回Ibinder对象。如果访问者退出了,系统就会先调用服务的onUnbind()方法,接着调用onDestroy()方法。如果调用bindService()方法前服务已经被绑定,多次调用bindService()方法并不会导致多次创建服务及绑定(也就是说onCreate()和onBind()方法并不会多次调用)。如果访问者希望与正在绑定的服务解除绑定,可以调用unBindService()方法,调用该方法也会导致系统调用服务的onUnbind()->onDestroy()方法。
public class MainActivity extends Activity
{
private EditText studentno;
private ServiceConnection conn = new StudentServiceConnection();
private IStundent iStundent;
private TextView resultView;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
resultView = (TextView) this.findViewById(R.id.resultView);
studentno = (EditText) this.findViewById(R.id.studentno);
Button button = (Button) this.findViewById(R.id.button);
button.setOnClickListener(new ButtonClickListener());
Intent service = new Intent(this, StudentService.class);
bindService(service, conn, BIND_AUTO_CREATE);
}
private class StudentServiceConnection implements ServiceConnection
{
public void onServiceConnected(ComponentName name, IBinder service)
{
iStundent = (IStundent)service;
}
public void onServiceDisconnected(ComponentName name)
{
iStundent = null;
}
}
@Override
protected void onDestroy()
{
unbindService(conn);
super.onDestroy();
}
private finalclass ButtonClickListener implements View.OnClickListener
{
public void onClick(View v)
{
String no = studentno.getText().toString();
String name = iStundent.queryStudent(Integer.valueOf(no));
resultView.setText(name);
}
}
}
public interface IStundent
{
public String queryStudent(int no);
}
public class StudentService extends Service
{
private String[] names = {"张飞","李小龙","赵薇"};
private IBinder binder = new StundentBinder();
public String query(int no){
if(no>0 && no<4){
return names[no - 1];
}
return null;
}
public IBinder onBind(Intent intent) {
return binder;
}
private class StundentBinder extends Binder implements Istundent{
public String queryStudent(int no) {
return query(no);
}
}
}
二、远程服务
使用AIDL(Android Interface Definition Language)和远程服务实现进程通信
要构建远程服务,执行以下步骤:
(1).编写一个AIDL文件来向客户端定义接口。包名与Android项目同。
(2).将AIDL文件添加到Eclipse项目的src目录下。编译器将在gen下自动生成java接口。
(3).实现一个服务并从onBind()方法返回所生成的接口。
(4).将服务配置添加到AndroidManifest.xml文件中。
AIDL语法:
(1).AIDL定义接口的源代码必须以.aidl结尾;
(2).AIDL接口中用到的数据类型,除了基本类型,String,List,Map,CharSequence之外,其他类型全部都需要导包,即使在同一个包中也需要导包。
StudentQuery.aidl文件(在服务端和客户端都须包含该文件)
//AIDL
interface StudentQuery
{
String queryStudent(int number);
}
在gen目录下会自动生成StudentQuery.java文件
Service类
public class StudentQueryService extends Service
{
private String[] names = {"张飞", "李静", "赵薇"};
private IBinder binder = new StudentQueryBinder();
@Override
public IBinder onBind(Intent intent) {
return binder;
}
private String query(int number){
if(number > 0 && number < 4){
return names[number - 1];
}
return null;
}
private final class StudentQueryBinder extends StudentQuery.Stub{
public String queryStudent(int number) throws RemoteException {
return query(number);
}
}
}
//配置文件,隐式意图
<service android:name=".StudentQueryService">
<intent-filter >
<action android:name="com.zouyong.student.query"/>
</intent-filter>
</service>
客户端代码:
//采用隐式意图绑定服务
Intent service = new Intent("com.zouyong.student.query");
bindService(service, conn, BIND_AUTO_CREATE);
private StudentQuery studentQuery;
private StudentConnection conn = new StudentConnection();
public void queryStudent(View v)
{
String number = numberText.getText().toString();
int num = Integer.valueOf(number);
try {
resultView.setText(studentQuery.queryStudent(num));
} catch (RemoteException e) {
e.printStackTrace();
}
}
protected void onDestroy() {
unbindService(conn);
super.onDestroy();
}
private final class StudentConnection implements ServiceConnection {
public void onServiceConnected(ComponentName name, IBinder service){
// StudentQuery.Stub.asInterface系统生成方法
studentQuery = StudentQuery.Stub.asInterface(service);
}
public void onServiceDisconnected(ComponentName name) {
studentQuery = null;
}
}
传递复杂数据的AIDL Service(传递的数据类型是自定义类型,需要序列化)
Person.aidl文件
parcelable Person;
Person.java
public class Person implements Parcelable
{
private Integer id;
private String name;
private String pass;
public Person(){}
public Person(Integer id, String name, String pass)
{
super();
this.id = id;
this.name = name;
this.pass = pass;
}
.........//省略setter和getter方法
@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((pass == null) ? 0 : pass.hashCode());
return result;
}
@Override
public boolean equals(Object obj)
{
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Person other = (Person) obj;
if (name == null)
{
if (other.name != null)
return false;
}
else if (!name.equals(other.name))
return false;
if (pass == null)
{
if (other.pass != null)
return false;
}
else if (!pass.equals(other.pass))
return false;
return true;
}
// 实现Parcelable接口必须实现的方法
@Override
public int describeContents()
{
return 0;
}
// 实现Parcelable接口必须实现的方法
@Override
public void writeToParcel(Parcel dest, int flags)
{
//把该对象所包含的数据写到Parcel
dest.writeInt(id);
dest.writeString(name);
dest.writeString(pass);
}
// 添加一个静态成员,名为CREATOR,该对象实现了Parcelable.Creator接口
public static final Parcelable.Creator<Person> CREATOR
= new Parcelable.Creator<Person>() //①
{
@Override
public Person createFromParcel(Parcel source)
{
// 从Parcel中读取数据,返回Person对象
return new Person(source.readInt()
, source.readString()
, source.readString());
}
@Override
public Person[] newArray(int size)
{
return new Person[size];
}
};
}
Pet.aidl文件
parcelable Pet;
Pet.java
public class Pet implements Parcelable
{
private String name;
private double weight;
public Pet()
{
}
public Pet(String name, double weight)
{
super();
this.name = name;
this.weight = weight;
}
........//省略Setter和Getter方法
@Override
public int describeContents()
{
return 0;
}
/* (non-Javadoc)
* @see android.os.Parcelable#writeToParcel(android.os.Parcel, int)
*/
@Override
public void writeToParcel(Parcel dest, int flags)
{
//把该对象所包含的数据写到Parcel
dest.writeString(name);
dest.writeDouble(weight);
}
// 添加一个静态成员,名为CREATOR,该对象实现了Parcelable.Creator接口
public static final Parcelable.Creator<Pet> CREATOR
= new Parcelable.Creator<Pet>()
{
@Override
public Pet createFromParcel(Parcel source)
{
// 从Parcel中读取数据,返回Person对象
return new Pet(source.readString()
, source.readDouble());
}
@Override
public Pet[] newArray(int size)
{
return new Pet[size];
}
};
@Override
public String toString()
{
return "Pet [name=" + name + ", weight=" + weight + "]";
}
}
IPet.aidl
package org.crazyit.service;
import org.crazyit.service.Pet;
import org.crazyit.service.Person;
interface IPet
{
// 定义一个Person对象作为传入参数
List<Pet> getPets(in Person owner); //in:参数传递方式
}
ComplexService.java 服务类
public class ComplexService extends Service
{
private PetBinder petBinder;
private static Map<Person , List<Pet>> pets
= new HashMap<Person , List<Pet>>();
static
{
// 初始化pets Map集合
ArrayList<Pet> list1 = new ArrayList<Pet>();
list1.add(new Pet("旺财" , 4.3));
list1.add(new Pet("来福" , 5.1));
pets.put(new Person(1, "sun" , "sun") , list1);
ArrayList<Pet> list2 = new ArrayList<Pet>();
list2.add(new Pet("kitty" , 2.3));
list2.add(new Pet("garfield" , 3.1));
pets.put(new Person(2, "bai" , "bai") , list2);
}
// 继承Stub,也就是实现额IPet接口,并实现了IBinder接口
public class PetBinder extends Stub
{
@Override
public List<Pet> getPets(Person owner) throws RemoteException
{
// 返回Service内部的数据
return pets.get(owner);
}
}
@Override
public void onCreate()
{
super.onCreate();
petBinder = new PetBinder();
}
@Override
public IBinder onBind(Intent arg0)
{
/* 返回catBinder对象
* 在绑定本地Service的情况下,该catBinder对象会直接
* 传给客户端的ServiceConnection对象
* 的onServiceConnected方法的第二个参数;
* 在绑定远程Service的情况下,只将catBinder对象的代理
* 传给客户端的ServiceConnection对象
* 的onServiceConnected方法的第二个参数;
*/
return petBinder; //①
}
@Override
public void onDestroy()
{
}
}
ComplexClient.java 客户端
public class ComplexClient extends Activity
{
private IPet petService;
private Button get;
EditText personView;
ListView showView;
private ServiceConnection conn = new ServiceConnection()
{
@Override
public void onServiceConnected(ComponentName name
, IBinder service)
{
// 获取远程Service的onBind方法返回的对象的代理
petService = IPet.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name)
{
petService = null;
}
};
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
personView = (EditText) findViewById(R.id.person);
showView = (ListView) findViewById(R.id.show);
get = (Button) findViewById(R.id.get);
// 创建所需绑定的Service的Intent
Intent intent = new Intent();
intent.setAction("org.crazyit.aidl.action.COMPLEX_SERVICE");
// 绑定远程Service
bindService(intent, conn, Service.BIND_AUTO_CREATE);
get.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View arg0)
{
try
{
String personName = personView.getText().toString();
// 调用远程Service的方法
List<Pet> pets = petService.getPets(new Person(1,
personName, personName)); //①
// 将程序返回的List包装成ArrayAdapter
ArrayAdapter<Pet> adapter = new ArrayAdapter<Pet>(
ComplexClient.this,
android.R.layout.simple_list_item_1, pets);
showView.setAdapter(adapter);
}
catch (RemoteException e)
{
e.printStackTrace();
}
}
});
}
@Override
public void onDestroy()
{
super.onDestroy();
// 解除绑定
this.unbindService(conn);
}
}
注:在客户端中需要把IPet.aidl, Person.java ,Person.aidl, Pet.java ,Pet.aidl复制过去。
三、IntentService
IntentService具有如下特征:
(1).IntentService会创建单独的worker来处理所有的Intent请求;
(2).IntentService会创建单独的worker线程来处理onHandleIntent()方法实现的代码,无须处理多线程问题;
(3).当所有请求处理完成后,会自动停止,无须调用stopSelf()方法来停止Service;
(4).为Service的onBind()方法提供了默认的实现,默认实现的onBind()方法返回null;
(5).为Service的onStartCommand()方法提供了默认实现,该实现会将请求Intent添加到队列中。
IntentService 实际上是Looper,Handler,Service 的集合体,他不仅有服务的功能,还有处理和循环消息的功能.
不管是何种Service,它默认都是在应用程序的主线程(亦即UI线程)中运行的。所以,如果你的Service将要运行非常耗时或者可能被阻塞的操作时,你的应用程序将会被挂起,甚至会出现ANR错误。为了避免这一问题,你应该在Service中重新启动一个新的线程来进行这些操作。现有两种方法:
1.直接在Service的onStartCommand()方法中重启一个线程来执行
2.使用IntentService
四、服务生命周期
服务的生命周期跟启动服务的方法有关:
1.当采用Context.startService()方法启动服务,与之有关的生命周期方法:
onCreate()->onStartCommand()->onDestroy()
onCreate():服务被创建时调用,只会被调用一次,无论调用多少次startService()或bindService()方法,服务也只被创建一次。
onStartCommand():只有采用Context.startService()方法启动服务时才会回调该方法。在服务开始运行时被调用,多次调用startService()方法尽管不会多次创建服务,但onStart()会被多次调用。
onDestroy():该方法在服务被终止时调用.
2.当采用Context.bindService()方法启动服务,与之有关的生命周期方法:
onCreate()->onBind()->onUnbind()->onDestroy()
onBind()::只有采用Context.bindService()方法启动服务时才会回调该方法。该方法在调用者与服务绑定时被调用,当调用者与服务已经绑定,多次调用Context.bindService()方法不会导致该方法被多次调用。
onUnbind()方法:只有采用Context.bindService()方法启动服务时才会回调该方法。该方法在调用者与服务解除绑定时被调用。
3.如果先采用startService()方法启动服务,然后调用bindService()方法绑定服务,再调用unbindService()方法解除绑定,最后调用bindService()方法再次绑定到服务,触发的生命周期方法如下:
onCreate()->onStartCommand()->onBind()->onUnbind()[重载后的方法需返回true]->onRebind();
五、 系统服务
电话管理器(TelephoneyManager)
短信管理器(SmsManager)
音频管理器(AudioManager)
振动器(Vibrator)
手机闹钟服务(AlarmManager)
壁纸管理(WallpaperManager)
获取网络和SIM卡信息
public class TelephonyStatus extends Activity
{
ListView showView;
// 声明代表状态名的数组
String[] statusNames;
// 声明代表手机状态的集合
ArrayList<String> statusValues = new ArrayList<String>();
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// 获取系统的TelephonyManager对象
TelephonyManager tManager = (TelephonyManager)
getSystemService(Context.TELEPHONY_SERVICE);
// 获取各种状态名称的数组
statusNames = getResources().getStringArray(R.array.statusNames);
// 获取代表SIM卡状态的数组
String[] simState = getResources()
.getStringArray(R.array.simState);
// 获取代表电话网络类型的数组
String[] phoneType = getResources().getStringArray(
R.array.phoneType);
// 获取设备编号
statusValues.add(tManager.getDeviceId());
// 获取系统平台的版本
statusValues.add(tManager.getDeviceSoftwareVersion()
!= null ? tManager.getDeviceSoftwareVersion() : "未知");
// 获取网络运营商代号
statusValues.add(tManager.getNetworkOperator());
// 获取网络运营商名称
statusValues.add(tManager.getNetworkOperatorName());
// 获取手机网络类型
statusValues.add(phoneType[tManager.getPhoneType()]);
// 获取设备所在位置
statusValues.add(tManager.getCellLocation() != null ? tManager
.getCellLocation().toString() : "未知位置");
// 获取SIM卡的国别
statusValues.add(tManager.getSimCountryIso());
// 获取SIM卡序列号
statusValues.add(tManager.getSimSerialNumber());
// 获取SIM卡状态
statusValues.add(simState[tManager.getSimState()]);
// 获得ListView对象
showView = (ListView) findViewById(R.id.show);
ArrayList<Map<String, String>> status =
new ArrayList<Map<String, String>>();
// 遍历statusValues集合,将statusNames、statusValues
// 的数据封装到List<Map<String , String>>集合中
for (int i = 0; i < statusValues.size(); i++)
{
HashMap<String, String> map = new HashMap<String, String>();
map.put("name", statusNames[i]);
map.put("value", statusValues.get(i));
status.add(map);
}
// 使用SimpleAdapter封装List数据
SimpleAdapter adapter = new SimpleAdapter(this, status,
R.layout.line, new String[] { "name", "value" }
, new int[] { R.id.name, R.id.value });
// 为ListView设置Adapter
showView.setAdapter(adapter);
}
}
监听手机来电
public class MonitorPhone extends Activity
{
TelephonyManager tManager;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// 取得TelephonyManager对象
tManager = (TelephonyManager)
getSystemService(Context.TELEPHONY_SERVICE);
// 创建一个通话状态监听器
PhoneStateListener listener = new PhoneStateListener()
{
@Override
public void onCallStateChanged(int state, String number)
{
switch (state)
{
// 无任何状态
case TelephonyManager.CALL_STATE_IDLE:
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
break;
// 来电铃响时
case TelephonyManager.CALL_STATE_RINGING:
OutputStream os = null;
try
{
os = openFileOutput("phoneList", MODE_APPEND);
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
PrintStream ps = new PrintStream(os);
// 将来电号码记录到文件中
ps.println(new Date() + " 来电:" + number);
ps.close();
break;
default:
break;
}
super.onCallStateChanged(state, number);
}
};
// 监听电话通话状态的改变
tManager.listen(listener, PhoneStateListener.LISTEN_CALL_STATE);
}
}
黑名单来电自动挂断
需要调用系统远程AIDL Service,需要将com.android.internal.telephony包下的Itelephony.aidl和android.telephony包下的NeighboringCellInfo.aidl复制到项目下。
public class BlockMain extends Activity
{
// 记录黑名单的List
ArrayList<String> blockList = new ArrayList<String>();
TelephonyManager tManager;
// 监听通话状态的监听器
CustomPhoneCallListener cpListener;
public class CustomPhoneCallListener extends PhoneStateListener
{
@Override
public void onCallStateChanged(int state, String number)
{
switch (state)
{
case TelephonyManager.CALL_STATE_IDLE:
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
break;
// 当电话呼入时
case TelephonyManager.CALL_STATE_RINGING:
// 如果该号码属于黑名单
if (isBlock(number))
{
System.out.println("~~~挂断电话~~~");
try
{
Method method = Class.forName(
"android.os.ServiceManager")
.getMethod("getService"
, String.class);
// 获取远程TELEPHONY_SERVICE的IBinder对象的代理
IBinder binder = (IBinder) method.invoke(null,
new Object[] { TELEPHONY_SERVICE });
// 将IBinder对象的代理转换为ITelephony对象
ITelephony telephony = ITelephony.Stub
.asInterface(binder);
// 挂断电话
telephony.endCall();
}
catch (Exception e)
{
e.printStackTrace();
}
}
break;
}
super.onCallStateChanged(state, number);
}
}
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// 获取系统的TelephonyManager管理器
tManager = (TelephonyManager)
getSystemService(TELEPHONY_SERVICE);
cpListener = new CustomPhoneCallListener();
// 通过TelephonyManager监听通话状态的改变
tManager.listen(cpListener
, PhoneStateListener.LISTEN_CALL_STATE);
// 获取程序的按钮,并为它的单击事件绑定监听器
findViewById(R.id.managerBlock).setOnClickListener(
new OnClickListener()
{
@Override
public void onClick(View v)
{
// 查询联系人的电话号码
final Cursor cursor = getContentResolver()
.query(ContactsContract.CommonDataKinds
.Phone.CONTENT_URI, null, null, null, null);
BaseAdapter adapter = new BaseAdapter()
{
@Override
public int getCount()
{
return cursor.getCount();
}
@Override
public Object getItem(int position)
{
return position;
}
@Override
public long getItemId(int position)
{
return position;
}
@Override
public View getView(int position,
View convertView, ViewGroup parent)
{
cursor.moveToPosition(position);
CheckBox rb = new CheckBox(BlockMain.this);
// 获取联系人的电话号码,并去掉中间的中划线、空格
String number = cursor
.getString(cursor.getColumnIndex(
ContactsContract.CommonDataKinds
.Phone.NUMBER))
.replace("-", "")
.replace(" ", "");
rb.setText(number);
// 如果该号码已经被加入黑名单、默认勾选该号码
if (isBlock(number))
{
rb.setChecked(true);
}
return rb;
}
};
// 加载list.xml布局文件对应的View
View selectView = getLayoutInflater().inflate(
R.layout.list, null);
// 获取selectView中的名为list的ListView组件
final ListView listView = (ListView) selectView
.findViewById(R.id.list);
listView.setAdapter(adapter);
new AlertDialog.Builder(BlockMain.this)
.setView(selectView)
.setPositiveButton("确定",
new DialogInterface.OnClickListener()
{
@Override
public void onClick(
DialogInterface dialog, int which)
{
// 清空blockList集合
blockList.clear();
// 遍历listView组件的每个列表项
for (int i = 0; i < listView
.getCount(); i++)
{
CheckBox checkBox = (CheckBox)
listView.getChildAt(i);
// 如果该列表项被勾选
if (checkBox.isChecked())
{
// 添加该列表项的电话号码
blockList.add(checkBox
.getText().toString());
}
}
System.out.println(blockList);
}
}).show();
}
});
}
// 判断某个电话号码是否在黑名单之内
public boolean isBlock(String phone)
{
System.out.println("呼入号码:" + phone);
System.out.println("--------" + blockList);
for (String s1 : blockList)
{
if (s1.equals(phone))
{
return true;
}
}
return false;
}
}
发送短信
private final class sendSMSListener implements View.OnClickListener
{
public void onClick(View v)
{
String number=mobilenumber.getText().toString();
String content=smscontent.getText().toString();
SmsManager smsManager=SmsManager.getDefault();
ArrayList<String> message=smsManager.divideMessage(content);
for(String sms:message)
{
smsManager.sendTextMessage(number, null, sms, null, null);
}
Toast.makeText(getApplicationContext(), "Send success", Toast.LENGTH_LONG).show();
}
}
<uses-permission android:name="android.permission.SEND_SMS"/>
群发短信
public class GroupSend extends Activity
{
EditText numbers, content;
Button select, send;
SmsManager sManager;
// 记录需要群发的号码列表
ArrayList<String> sendList = new ArrayList<String>();
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
sManager = SmsManager.getDefault();
// 获取界面上的文本框、按钮组件
numbers = (EditText) findViewById(R.id.numbers);
content = (EditText) findViewById(R.id.content);
select = (Button) findViewById(R.id.select);
send = (Button) findViewById(R.id.send);
// 为send按钮的单击事件绑定监听器
send.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
for (String number : sendList)
{
// 创建一个PendingIntent对象
PendingIntent pi = PendingIntent.getActivity(
GroupSend.this, 0, new Intent(), 0);
// 发送短信
sManager.sendTextMessage(number, null, content
.getText().toString(), pi, null);
}
// 提示短信群发完成
Toast.makeText(GroupSend.this, "短信群发完成"
, Toast.LENGTH_SHORT).show();
}
});
// 为select按钮的单击事件绑定监听器
select.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
// 查询联系人的电话号码
final Cursor cursor = getContentResolver().query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null, null, null, null);
BaseAdapter adapter = new BaseAdapter()
{
@Override
public int getCount()
{
return cursor.getCount();
}
@Override
public Object getItem(int position)
{
return position;
}
@Override
public long getItemId(int position)
{
return position;
}
@Override
public View getView(int position, View convertView,
ViewGroup parent)
{
cursor.moveToPosition(position);
CheckBox rb = new CheckBox(GroupSend.this);
// 获取联系人的电话号码,并去掉中间的中划线、空格
String number = cursor
.getString(cursor.getColumnIndex(ContactsContract
.CommonDataKinds.Phone.NUMBER))
.replace("-", "")
.replace(" " , "");
rb.setText(number);
// 如果该号码已经被加入发送人名单、默认勾选该号码
if (isChecked(number))
{
rb.setChecked(true);
}
return rb;
}
};
// 加载list.xml布局文件对应的View
View selectView = getLayoutInflater().inflate(
R.layout.list, null);
// 获取selectView中的名为list的ListView组件
final ListView listView = (ListView) selectView
.findViewById(R.id.list);
listView.setAdapter(adapter);
new AlertDialog.Builder(GroupSend.this)
.setView(selectView)
.setPositiveButton("确定",
new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialog,
int which)
{
// 清空sendList集合
sendList.clear();
// 遍历listView组件的每个列表项
for (int i = 0; i < listView.getCount(); i++)
{
CheckBox checkBox = (CheckBox) listView
.getChildAt(i);
// 如果该列表项被勾选
if (checkBox.isChecked())
{
// 添加该列表项的电话号码
sendList.add(checkBox.getText()
.toString());
}
}
numbers.setText(sendList.toString());
}
}).show();
}
});
}
// 判断某个电话号码是否已在群发范围内
public boolean isChecked(String phone)
{
for (String s1 : sendList)
{
if (s1.equals(phone))
{
return true;
}
}
return false;
}
}
音乐播放器
public class AudioTest extends Activity
{
Button play, up, down;
ToggleButton mute;
AudioManager aManager;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// 获取系统的音频服务
aManager = (AudioManager) getSystemService(
Service.AUDIO_SERVICE);
// 获取界面中3个按钮和一个ToggleButton控件
play = (Button) findViewById(R.id.play);
up = (Button) findViewById(R.id.up);
down = (Button) findViewById(R.id.down);
mute = (ToggleButton) findViewById(R.id.mute);
// 为play按钮的单击事件绑定监听器
play.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View source)
{
// 初始化MediaPlayer对象,准备播放音乐
MediaPlayer mPlayer = MediaPlayer.create(
AudioTest.this, R.raw.earth);
// 设置循环播放
mPlayer.setLooping(true);
// 开始播放
mPlayer.start();
}
});
up.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View source)
{
// 指定调节音乐的音频,增大音量,而且显示音量图形示意
aManager.adjustStreamVolume(AudioManager.STREAM_MUSIC,
AudioManager.ADJUST_RAISE, AudioManager.FLAG_SHOW_UI);
}
});
down.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View source)
{
// 指定调节音乐的音频,降低音量,而且显示音量图形示意
aManager.adjustStreamVolume(AudioManager.STREAM_MUSIC,
AudioManager.ADJUST_LOWER, AudioManager.FLAG_SHOW_UI);
}
});
mute.setOnCheckedChangeListener(new OnCheckedChangeListener()
{
@Override
public void onCheckedChanged(CompoundButton source,
boolean isChecked)
{
// 指定调节音乐的音频,根据isChecked确定是否需要静音
aManager.setStreamMute(AudioManager.STREAM_MUSIC,
isChecked);
}
});
}
}
控制手机振动
public class VibratorTest extends Activity
{
Vibrator vibrator;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// 获取系统的Vibrator服务
vibrator = (Vibrator) getSystemService(
Service.VIBRATOR_SERVICE);
}
// 重写onTouchEvent方法,当用户触碰触摸屏时触发该方法
@Override
public boolean onTouchEvent(MotionEvent event)
{
Toast.makeText(this, "手机振动"
, Toast.LENGTH_LONG).show();
// 控制手机震动2秒
vibrator.vibrate(2000);
return super.onTouchEvent(event);
}
}
定时自动切换壁纸
public class AlarmChangeWallpaper extends Activity
{
// 定义AlarmManager对象
AlarmManager aManager;
Button start, stop;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
start = (Button) findViewById(R.id.start);
stop = (Button) findViewById(R.id.stop);
aManager = (AlarmManager) getSystemService(
Service.ALARM_SERVICE);
// 指定启动ChangeService组件
Intent intent = new Intent(AlarmChangeWallpaper.this,
ChangeService.class);
// 创建PendingIntent对象
final PendingIntent pi = PendingIntent.getService(
AlarmChangeWallpaper.this, 0, intent, 0);
start.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View arg0)
{
// 设置每隔5秒执行pi代表的组件一次
aManager.setRepeating(AlarmManager.RTC_WAKEUP
, 0, 5000, pi);
start.setEnabled(false);
stop.setEnabled(true);
Toast.makeText(AlarmChangeWallpaper.this
, "壁纸定时更换启动成功啦",
Toast.LENGTH_SHORT).show();
}
});
stop.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View arg0)
{
start.setEnabled(true);
stop.setEnabled(false);
// 取消对pi的调度
aManager.cancel(pi);
}
});
}
}
public class ChangeService extends Service
{
// 定义定时更换的壁纸资源
int[] wallpapers = new int[]{
R.drawable.shuangta,
R.drawable.lijiang,
R.drawable.qiao,
R.drawable.shui
};
// 定义系统的壁纸管理服务
WallpaperManager wManager;
// 定义当前所显示的壁纸
int current = 0;
@Override
public int onStartCommand(Intent intent, int flags, int startId)
{
// 如果到了最后一张,系统重新开始
if(current >= 4)
current = 0;
try
{
// 改变壁纸
wManager.setResource(wallpapers[current++]);
}
catch (Exception e)
{
e.printStackTrace();
}
return START_STICKY;
}
@Override
public void onCreate()
{
super.onCreate();
// 初始化WallpaperManager
wManager = WallpaperManager.getInstance(this);
}
@Override
public IBinder onBind(Intent intent)
{
return null;
}
}
闹钟
public class AlarmActivity extends Activity
{
MediaPlayer alarmMusic;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// 加载指定音乐,并为之创建MediaPlayer对象
alarmMusic = MediaPlayer.create(this, R.raw.alarm);
alarmMusic.setLooping(true);
// 播放音乐
alarmMusic.start();
// 创建一个对话框
new AlertDialog.Builder(AlarmActivity.this).setTitle("闹钟")
.setMessage("闹钟响了,Go!Go!Go!")
.setPositiveButton("确定", new OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which)
{
// 停止音乐
alarmMusic.stop();
// 结束该Activity
AlarmActivity.this.finish();
}
}).show();
}
}
public class AlarmTest extends Activity
{
Button setTime;
AlarmManager aManager;
Calendar currentTime = Calendar.getInstance();
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// 获取程序界面的按钮
setTime = (Button) findViewById(R.id.setTime);
// 获取AlarmManager对象
aManager = (AlarmManager) getSystemService(
Service.ALARM_SERVICE);
// 为“设置闹铃”按钮绑定监听器。
setTime.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View source)
{
Calendar currentTime = Calendar.getInstance();
// 创建一个TimePickerDialog实例,并把它显示出来。
new TimePickerDialog(AlarmTest.this, 0, // 绑定监听器
new TimePickerDialog.OnTimeSetListener()
{
@Override
public void onTimeSet(TimePicker tp,
int hourOfDay, int minute)
{
// 指定启动AlarmActivity组件
Intent intent = new Intent(AlarmTest.this,
AlarmActivity.class);
// 创建PendingIntent对象
PendingIntent pi = PendingIntent.getActivity(
AlarmTest.this, 0, intent, 0);
Calendar c = Calendar.getInstance();
// 根据用户选择时间来设置Calendar对象
c.set(Calendar.HOUR, hourOfDay);
c.set(Calendar.MINUTE, minute);
// 设置AlarmManager将在Calendar对应的时间启动指定组件
aManager.set(AlarmManager.RTC_WAKEUP,
c.getTimeInMillis(), pi);
// 显示闹铃设置成功的提示信息
Toast.makeText(AlarmTest.this, "闹铃设置成功啦"
, Toast.LENGTH_SHORT).show();
}
}, currentTime.get(Calendar.HOUR_OF_DAY), currentTime
.get(Calendar.MINUTE), false).show();
}
});
}
}