今天搞了個小程序,可以修改你自己android手機的任何一條短信。
直接進入正題,先放兩張效果圖:
主界面就是四個按鈕加一個顯示短信的listview:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/linearlayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<Button
android:id="@+id/btnAll"
android:layout_weight="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="所有短信"
/>
<Button
android:id="@+id/btnInbox"
android:layout_weight="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="收件箱短信"
/>
</LinearLayout>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<Button
android:id="@+id/btnSend"
android:layout_weight="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="發件箱短信"
/>
<Button
android:id="@+id/btnDraft"
android:layout_weight="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="草稿箱短信"
/>
</LinearLayout>
<ListView
android:id="@+id/listview"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:clickable="true"
/>
</LinearLayout>
還有一個StaticValues類放置一些常量
package com.jackchan.sms;
public class StaticValues {
//android系統短信數據庫的字段
public static final String _ID = "_id";
public static final String PERSON = "person";
public static final String BODY = "body";
public static final String ADDRESS = "address";
public static final String DATE = "date";
public static final String TYPE = "type";
}
主類代碼如下,重點在getSmsInPhone()這個方法,通過ContentResolver分別傳入收件箱、發件箱、草稿的Uri獲取你想要的字段,
sms相關的字段如下:
_id 一個自增字段,從1開始 ,每條短信_id都不一樣,根據這個唯一性可以修改短信
thread_id 序號,同一發信人的id相同
address 發件人手機號碼
person 聯繫人列表裏的序號,陌生人爲null
date 發件日期
protocol 協議,分爲: 0 SMS_RPOTO, 1 MMS_PROTO
read 是否閱讀 0未讀, 1已讀
status 狀態 -1接收,0 complete, 64 pending, 128 failed
type
ALL = 0;
INBOX = 1;
SENT = 2;
DRAFT = 3;
OUTBOX = 4;
FAILED = 5;
QUEUED = 6;
body 短信內容
service_center 短信服務中心號碼編號
subject 短信的主題
reply_path_present TP-Reply-Path
package com.jackchan.sms;
import java.sql.Date;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.jackchan.sms.ChangeSMSWindow.onOkClick;
import android.app.Activity;
import android.content.ContentResolver;
import android.database.Cursor;
import android.database.sqlite.SQLiteException;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.ListView;
public class SMS extends Activity {
private List<Map<String, Object>> list = new ArrayList<Map<String,Object>>(); //已發送信息列表
private SMSAdapter adapter;
private Button btnAll;
private Button btnInbox;
private Button btnSend;
private Button btnDraft;
public static String url;
private ListView listView;
private final String SMS_URI_ALL = "content://sms/";
private final String SMS_URI_INBOX = "content://sms/inbox";
private final String SMS_URI_SEND = "content://sms/sent";
private final String SMS_URI_DRAFT = "content://sms/draft";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
initComponet();
setBtnClick();
url = SMS_URI_ALL;//默認獲取全部短信
adapter = new SMSAdapter(this, getSmsInPhone());
listView.setAdapter(adapter);
listView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
// TODO Auto-generated method stub
ChangeSMSWindow change = new ChangeSMSWindow(SMS.this, list.get(arg2).get(StaticValues.BODY).toString(),
(Long) list.get(arg2).get(StaticValues._ID));
change.setOkClick(new onOkClick() {
@Override
public void dataChange() {
listChange();
}
});
change.showAtLocation(listView,
//LayoutInflater.from(context).inflate(R.layout.main, null),
Gravity.CENTER_HORIZONTAL|Gravity.CENTER_VERTICAL,
0, 0);
}
});
}
private void initComponet(){
listView = (ListView)findViewById(R.id.listview);
btnAll = (Button)findViewById(R.id.btnAll);
btnInbox = (Button)findViewById(R.id.btnInbox);
btnSend = (Button)findViewById(R.id.btnSend);
btnDraft = (Button)findViewById(R.id.btnDraft);
}
private void setBtnClick(){
btnAll.setOnClickListener(click);
btnInbox.setOnClickListener(click);
btnSend.setOnClickListener(click);
btnDraft.setOnClickListener(click);
}
/*
* listview數據發生改變
*/
private void listChange(){
adapter.clearList();
adapter.changeList(getSmsInPhone());
adapter.notifyDataSetChanged();
}
private btnClick click = new btnClick();
private class btnClick implements OnClickListener{
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(v == btnAll){
url = SMS_URI_ALL;
}
else if(v == btnInbox){
url = SMS_URI_INBOX;
}
else if(v == btnSend){
url = SMS_URI_SEND;
}
else if(v == btnDraft){
url = SMS_URI_DRAFT;
}
listChange();
}
}
/*
* 獲取指定類型短信
*/
public List<Map<String, Object>> getSmsInPhone()
{
try{
ContentResolver cr = getContentResolver();
String[] projection = new String[]{"_id", "address", "person",
"body", "date", "type"};
Uri uri = Uri.parse(url);
Cursor cur = cr.query(uri, projection, null, null, "date desc");
if (cur.moveToFirst()) {
long id;
String name;
String phoneNumber;
String smsbody;
String date;
String type;
int idColumn = cur.getColumnIndex(StaticValues._ID);
int nameColumn = cur.getColumnIndex(StaticValues.PERSON);
int phoneNumberColumn = cur.getColumnIndex(StaticValues.ADDRESS);
int smsbodyColumn = cur.getColumnIndex(StaticValues.BODY);
int dateColumn = cur.getColumnIndex(StaticValues.DATE);
int typeColumn = cur.getColumnIndex(StaticValues.TYPE);
do{
id = cur.getLong(idColumn);
name = cur.getString(nameColumn);
phoneNumber = cur.getString(phoneNumberColumn);
smsbody = cur.getString(smsbodyColumn);
SimpleDateFormat dateFormat = new SimpleDateFormat(
"yyyy-MM-dd hh:mm:ss");
Date d = new Date(Long.parseLong(cur.getString(dateColumn)));
date = dateFormat.format(d);
int typeId = cur.getInt(typeColumn);
if(typeId == 1){
type = "接收";
} else if(typeId == 2){
type = "發送";
}else if(typeId == 3){
type = "草稿";
} else {
type = "";
}
if(smsbody == null)
smsbody = "";
Map<String, Object> map = new HashMap<String, Object>();
map.put(StaticValues._ID, id);
map.put(StaticValues.PERSON, name);
map.put(StaticValues.ADDRESS, phoneNumber);
map.put(StaticValues.BODY, smsbody);
map.put(StaticValues.DATE, date);
map.put(StaticValues.TYPE, type);
list.add(map);
}while(cur.moveToNext());
cur.close();
}
} catch(SQLiteException ex) {
Log.d("SQLiteException in getSmsInPhone", ex.getMessage());
}
return list;
}
}
listview中item.xml的佈局文件如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="@+id/person"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="姓名:"
/>
<TextView
android:id="@+id/address"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="地址:"
/>
<TextView
android:id="@+id/body"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="內容:"
/>
<TextView
android:id="@+id/date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="日期:"
/>
<TextView
android:id="@+id/type"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="類型:"
/>
</LinearLayout>
然後還有一個類用來適配主界面的listview
package com.jackchan.sms;
import java.util.List;
import java.util.Map;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
public class SMSAdapter extends BaseAdapter{
private Context context;//當前上下文內容
private List<Map<String, Object>> list; //已發送信息列表
private class ViewHolder{
TextView person;
TextView address;
TextView body;
TextView date;
TextView type;
}
public SMSAdapter(Context context, List<Map<String, Object>> list) {
super();
this.context = context;
this.list = list;
}
public void changeList(List<Map<String, Object>> list){
this.list = list;
}
public void clearList(){
list.clear();
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return list.size();
}
@Override
public Object getItem(int arg0) {
// TODO Auto-generated method stub
return null;
}
@Override
public long getItemId(int arg0) {
// TODO Auto-generated method stub
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder = null;
if(convertView == null){
viewHolder = new ViewHolder();
convertView = LayoutInflater.from(context).inflate(R.layout.item, null);
viewHolder.person = (TextView)convertView.findViewById(R.id.person);
viewHolder.address = (TextView)convertView.findViewById(R.id.address);
viewHolder.body = (TextView)convertView.findViewById(R.id.body);
viewHolder.date = (TextView)convertView.findViewById(R.id.date);
viewHolder.type = (TextView)convertView.findViewById(R.id.type);
convertView.setTag(viewHolder);
}
else{
viewHolder = (ViewHolder)convertView.getTag();
}
//獲取短信基本信息
viewHolder.person.setText("姓名:" + list.get(position).get(StaticValues.PERSON));
viewHolder.address.setText("號碼:" + list.get(position).get(StaticValues.ADDRESS));
viewHolder.body.setText("內容:" + list.get(position).get(StaticValues.BODY));
viewHolder.date.setText("日期:" + list.get(position).get(StaticValues.DATE));
viewHolder.type.setText("類型:" + list.get(position).get(StaticValues.TYPE));
return convertView;
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/bg_popupwindow"
android:orientation="vertical" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="輸入修改後的內容:"
android:textColor="#000000"
android:textSize="20sp"
/>
<EditText
android:id="@+id/edittext"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:selectAllOnFocus="true"
/>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<Button
android:id="@+id/btnOk"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="確認"
/>
<Button
android:id="@+id/btnCancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="取消"
/>
</LinearLayout>
</LinearLayout>
彈出界面背景bg_popupwindow.xml
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle"
><!-- android:shape="" 表示是圓角矩形還是橢圓等等 -->
<solid android:color="#FFFF00"/>
<!-- 四個角的弧度 -->
<corners android:radius="4dip"/>
<!-- padding 表示內部空間距離背景圖片內部邊距 的距離 -->
</shape>
彈出界面實現代碼
package com.jackchan.sms;
import android.content.ContentValues;
import android.content.Context;
import android.net.Uri;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.PopupWindow;
/*
* 修改短信內容彈出框
* @author:jack chan
*/
public class ChangeSMSWindow extends PopupWindow{
private Context context;
private EditText editText;
private Button btnOk;
private Button btnCancel;
private ContentValues cv = new ContentValues(); //存放修改信息
private String body = null;//短信內容
private long id = -1;//短信編號
public ChangeSMSWindow(Context context, String body, long id) {
super(context);
this.context = context;
this.body = body;
this.id = id;
LayoutInflater inflater = LayoutInflater.from(context);
View view = inflater.inflate(R.layout.dialog, null);
setContentView(view);
this.setFocusable(true);
this.setOutsideTouchable(true);
editText = (EditText)view.findViewById(R.id.edittext);
btnOk = (Button)view.findViewById(R.id.btnOk);
btnCancel = (Button)view.findViewById(R.id.btnCancel);
this.setWidth(LinearLayout.LayoutParams.WRAP_CONTENT);
this.setHeight(LinearLayout.LayoutParams.WRAP_CONTENT);
editText.setText(body);
btnClick click = new btnClick();
btnOk.setOnClickListener(click);
btnCancel.setOnClickListener(click);
}
private class btnClick implements OnClickListener{
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(v.getId() == R.id.btnOk){
cv.put(StaticValues.BODY, editText.getText().toString());
context.getContentResolver().update(Uri.parse(SMS.url),
cv, StaticValues._ID + "=?", new String[]{id+""});
if(okClick != null)
okClick.dataChange();
}
if(isShowing())
dismiss();
}
}
public interface onOkClick{
void dataChange();
}
private onOkClick okClick;
public void setOkClick(onOkClick okClick) {
this.okClick = okClick;
}
}
最後在Mainfiest裏添加讀寫權限
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.WRITE_SMS" />
大功告成,現在就完成需求了。