MMS不調用系統函數實現流程

最近有個需求,不去調用系統界面發送彩信功能。做過發送短信功能的同學可能第一反應是這樣: 
不使用 StartActivity,像發短信那樣,調用一個類似於發短信的方法 
SmsManager smsManager = SmsManager.getDefault(); 
smsManager.sendTextMessage(phoneCode, null, text, null, null); 
可以實現嗎? 答案是否定的,因爲android上根本就沒有提供發送彩信的接口,如果你想發送彩信,對不起,請調用系統彩信app界面,如下: 

  1.        Intent sendIntent = new Intent(Intent.ACTION_SEND,  Uri.parse("mms://"));  
  2. sendIntent.setType("image/jpeg");  
  3. String url = "file://sdcard//tmpPhoto.jpg";  
  4. sendIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse(url));  
  5. startActivity(Intent.createChooser(sendIntent, "MMS:"));  

但是這種方法往往不能滿足我們的需求,能不能不調用系統界面,自己實現發送彩信呢?經過幾天的努力,終於找到了解決辦法。 
第一步:先構造出你要發送的彩信內容,即構建一個pdu,需要用到以下幾個類,這些類都是從android源碼的MMS應用中mms.pdu包中copy出來的。你需要將pdu包中的所有類 

都拷貝到你的工程中,然後自己酌情調通。 
Java代碼  收藏代碼
  1.    final SendReq sendRequest = new SendReq();  
  2.    final PduBody pduBody = new PduBody();  
  3. final PduPart part = new PduPart();//存放附件,每個附件是一個part,如果添加多個附件,就想body中add多個part。  
  4.   
  5.    pduBody.addPart(partPdu);  
  6.    sendRequest.setBody(pduBody);  
  7.    final PduComposer composer = new PduComposer(ctx, sendRequest);  
  8. final byte[] bytesToSend = composer.make(); //將彩信的內容以及主題等信息轉化成byte數組,準備通過http協議//發送到 ”http://mmsc.monternet.com”;  

第二步:發送彩信到彩信中心。 
構建pdu的代碼: 
Java代碼  收藏代碼
  1.                     String subject = "測試彩信";  
  2.             String recipient = "接收彩信的號碼";//138xxxxxxx  
  3.             final SendReq sendRequest = new SendReq();  
  4.             final EncodedStringValue[] sub = EncodedStringValue.extract(subject);  
  5.             if (sub != null && sub.length > 0) {  
  6.                 sendRequest.setSubject(sub[0]);  
  7.             }  
  8.             final EncodedStringValue[] phoneNumbers = EncodedStringValue.extract(recipient);  
  9.             if (phoneNumbers != null && phoneNumbers.length > 0) {  
  10.                 sendRequest.addTo(phoneNumbers[0]);  
  11.             }  
  12.             final PduBody pduBody = new PduBody();  
  13.             final PduPart part = new PduPart();  
  14.             part.setName("sample".getBytes());  
  15.             part.setContentType("image/png".getBytes());  
  16.             String furl = "file://mnt/sdcard//1.jpg";  
  17.    
  18.                     final PduPart partPdu = new PduPart();  
  19.                     partPdu.setCharset(CharacterSets.UTF_8);//UTF_16  
  20.                     partPdu.setName(part.getName());  
  21.                     partPdu.setContentType(part.getContentType());  
  22.                     partPdu.setDataUri(Uri.parse(furl));  
  23.                     pduBody.addPart(partPdu);     
  24.    
  25.             sendRequest.setBody(pduBody);  
  26.             final PduComposer composer = new PduComposer(ctx, sendRequest);  
  27.             final byte[] bytesToSend = composer.make();  
  28.    
  29.             Thread t = new Thread(new Runnable() {  
  30.    
  31.                 @Override  
  32.                 public void run() {  
  33.                     try {  
  34.                         HttpConnectInterface.sendMMS(ctx,  bytesToSend);  
  35. //  
  36.                     } catch (IOException e) {  
  37.                         e.printStackTrace();  
  38.                     }  
  39.                 }  
  40.             });  
  41.             t.start();  
  42. 發送pdu到彩信中心的代碼:  
  43.         public static String mmscUrl = "http://mmsc.monternet.com";  
  44. //  public static String mmscUrl = "http://www.baidu.com/";  
  45.     public static String mmsProxy = "10.0.0.172";  
  46.     public static String mmsProt = "80";  
  47.    
  48.        private static String HDR_VALUE_ACCEPT_LANGUAGE = "";  
  49.     // Definition for necessary HTTP headers.  
  50.        private static final String HDR_KEY_ACCEPT = "Accept";  
  51.        private static final String HDR_KEY_ACCEPT_LANGUAGE = "Accept-Language";  
  52.    
  53.     private static final String HDR_VALUE_ACCEPT =  
  54.         "*/*, application/vnd.wap.mms-message, application/vnd.wap.sic";  
  55. public static byte[] sendMMS(Context context, byte[] pdu)throws IOException{  
  56.         HDR_VALUE_ACCEPT_LANGUAGE = getHttpAcceptLanguage();  
  57.    
  58.         if (mmscUrl == null) {  
  59.             throw new IllegalArgumentException("URL must not be null.");  
  60.         }  
  61.    
  62.         HttpClient client = null;  
  63.         try {  
  64.             // Make sure to use a proxy which supports CONNECT.  
  65.             client = HttpConnector.buileClient(context);  
  66.             HttpPost post = new HttpPost(mmscUrl);  
  67.             //mms PUD START  
  68.             ByteArrayEntity entity = new ByteArrayEntity(pdu);  
  69.             entity.setContentType("application/vnd.wap.mms-message");  
  70.             post.setEntity(entity);  
  71.             post.addHeader(HDR_KEY_ACCEPT, HDR_VALUE_ACCEPT);  
  72.             post.addHeader(HDR_KEY_ACCEPT_LANGUAGE, HDR_VALUE_ACCEPT_LANGUAGE);  
  73.             //mms PUD END  
  74.             HttpParams params = client.getParams();  
  75.             HttpProtocolParams.setContentCharset(params, "UTF-8");  
  76.             HttpResponse response = client.execute(post);  
  77.    
  78.             LogUtility.showLog(tag, "111");  
  79.             StatusLine status = response.getStatusLine();  
  80.             LogUtility.showLog(tag, "status "+status.getStatusCode());  
  81.             if (status.getStatusCode() != 200) { // HTTP 200 is not success.  
  82.                 LogUtility.showLog(tag, "!200");  
  83.                 throw new IOException("HTTP error: " + status.getReasonPhrase());  
  84.             }  
  85.             HttpEntity resentity = response.getEntity();  
  86.             byte[] body = null;  
  87.             if (resentity != null) {  
  88.                 try {  
  89.                     if (resentity.getContentLength() > 0) {  
  90.                         body = new byte[(int) resentity.getContentLength()];  
  91.                         DataInputStream dis = new DataInputStream(resentity.getContent());  
  92.                         try {  
  93.                             dis.readFully(body);  
  94.                         } finally {  
  95.                             try {  
  96.                                 dis.close();  
  97.                             } catch (IOException e) {  
  98.                                 Log.e(tag, "Error closing input stream: " + e.getMessage());  
  99.                             }  
  100.                         }  
  101.                     }  
  102.                 } finally {  
  103.                     if (entity != null) {  
  104.                         entity.consumeContent();  
  105.                     }  
  106.                 }  
  107.             }  
  108.             LogUtility.showLog(tag, "result:"+new String(body));  
  109.             return body;  
  110.         }  catch (IllegalStateException e) {  
  111.             LogUtility.showLog(tag, "",e);  
  112. //            handleHttpConnectionException(e, mmscUrl);  
  113.         } catch (IllegalArgumentException e) {  
  114.             LogUtility.showLog(tag, "",e);  
  115. //            handleHttpConnectionException(e, mmscUrl);  
  116.         } catch (SocketException e) {  
  117.             LogUtility.showLog(tag, "",e);  
  118. //            handleHttpConnectionException(e, mmscUrl);  
  119.         } catch (Exception e) {  
  120.             LogUtility.showLog(tag, "",e);  
  121.             //handleHttpConnectionException(e, mmscUrl);  
  122.         } finally {  
  123.             if (client != null) {  
  124. //                client.;  
  125.             }  
  126.         }  
  127.         return new byte[0];  
  128.     }  

更多詳細內容請瀏覽我的博客http://www.91dota.com/ 
至此,彩信的發送算是完成了。 
總結:android的彩信相關操作都是沒有api的,包括彩信的讀取、發送、存儲。這些過程都是需要手動去完成的。想要弄懂這些過程,需要仔細閱讀android源碼中的mms這個app。還有就是去研究mmssms.db數據庫,因爲彩信的讀取和存儲其實都是對mmssms.db這個數據庫的操作過程。而且因爲這個是共享的數據庫,所以只能用ContentProvider這個組件去操作db。 

總之,想要研究彩信這塊(包括普通短信),你就必須的研究mmssms.db的操作方法,多多瞭解每個表對應的哪個uri,每個uri能提供什麼樣的操作,那些字段代表短信的那些屬性等。 
最後推薦個好用的sqlite查看工具:SQLite Database Browser。 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章