灯火互联
管理员
管理员
  • 注册日期2011-07-27
  • 发帖数41778
  • QQ
  • 火币41290枚
  • 粉丝1086
  • 关注100
  • 终身成就奖
  • 最爱沙发
  • 忠实会员
  • 灌水天才奖
  • 贴图大师奖
  • 原创先锋奖
  • 特殊贡献奖
  • 宣传大使奖
  • 优秀斑竹奖
  • 社区明星
阅读:2161回复:0

android自定义发彩信实现(不调用系统发彩信界面)

楼主#
更多 发布于:2012-09-06 13:52


最近几天,因为项目需要,发彩信界面不再是调用系统的界面,即不跳转到短信界面,这个功能起初感觉应该很简单,但是真正做起来后,发现其实没有想象中那么简单,刚做完项目,趁头脑清晰,先把代码写下来先:
这几天为了这个项目,网上找了不少资料,大都资料都差不多,对于如何不跳用系统界面发彩信都有讲解,但是这个的前提是apn必须是wap,当如果是net时,因为连接超时而无法发送,正以内发彩信必须通过wap接入点才能发送,即使是在系统界面发彩信时,如果接入点不是wap,则会自动切换过来,待发送完后再切换回去,所以这个模块的核心,其实就是,如何在调用发彩信时,切换apn至wap,待发送完毕后再切换回去。。。
首先,根据不同移动供应商,需要设置不同的url和proxy
[java] // 电信彩信中心url,代理,端口  
public static String mmscUrl_ct = "http://mmsc.vnet.mobi";
public static String mmsProxy_ct = "10.0.0.200";
// 移动彩信中心url,代理,端口  
public static String mmscUrl_cm = "http://mmsc.monternet.com";
public static String mmsProxy_cm = "010.000.000.172";
// 联通彩信中心url,代理,端口  
public static String mmscUrl_uni = "http://mmsc.vnet.mobi";
public static String mmsProxy_uni = "10.0.0.172";
// 电信彩信中心url,代理,端口
public static String mmscUrl_ct = "http://mmsc.vnet.mobi";
public static String mmsProxy_ct = "10.0.0.200";
// 移动彩信中心url,代理,端口
public static String mmscUrl_cm = "http://mmsc.monternet.com";
public static String mmsProxy_cm = "010.000.000.172";
// 联通彩信中心url,代理,端口
public static String mmscUrl_uni = "http://mmsc.vnet.mobi";
public static String mmsProxy_uni = "10.0.0.172";
方法实现如下:
[java] private static List<String> getSimMNC(Context context){
        TelephonyManager telManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);  
        String imsi = telManager.getSubscriberId();  
        if(imsi!=null){  
            ArrayList<String> list = new ArrayList<String>();
            if(imsi.startsWith("46000") ||imsi.startsWith("46002")){  
                //因为移动网络编号46000下的IMSI已经用完,所以虚拟了一个46002编号,134/159号段使用了此编号  
                //中国移动  
                list.add(mmscUrl_cm);
                list.add(mmsProxy_cm);
            }else if(imsi.startsWith("46001")){  
                //中国联通  
                list.add(mmscUrl_uni);
                list.add(mmsProxy_uni);
            }else if(imsi.startsWith("46003")){  
                //中国电信  
                list.add(mmscUrl_ct);
                list.add(mmsProxy_ct);
            }  
            shouldChangeApn(context);
            return list;
        }
        return null;
    }
private static List<String> getSimMNC(Context context){
  TelephonyManager telManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
  String imsi = telManager.getSubscriberId();
  if(imsi!=null){
   ArrayList<String> list = new ArrayList<String>();
   if(imsi.startsWith("46000") ||imsi.startsWith("46002")){
    //因为移动网络编号46000下的IMSI已经用完,所以虚拟了一个46002编号,134/159号段使用了此编号
    //中国移动
    list.add(mmscUrl_cm);
    list.add(mmsProxy_cm);
   }else if(imsi.startsWith("46001")){
    //中国联通
    list.add(mmscUrl_uni);
    list.add(mmsProxy_uni);
   }else if(imsi.startsWith("46003")){
    //中国电信
    list.add(mmscUrl_ct);
    list.add(mmsProxy_ct);
   }
   shouldChangeApn(context);
   return list;
  }
  return null;
}
当当前的apn接入点不是发彩信所需要的wap时,就需要切换:

[java] private static boolean shouldChangeApn(final Context context){
        
        final String wapId = getWapApnId(context);
        String apnId = getApn(context);
        //若当前apn不是wap,则切换至wap  
        if(!wapId.equals(apnId)){
            APN_NET_ID = apnId;
            setApn(context,wapId);
            //切换apn需要一定时间,先让等待2秒  
            try {
                Thread.sleep(2000);
            } catch (interruptedException e) {
                e.printStackTrace();
            }
            return true;
        }
        return false;
    }
private static boolean shouldChangeApn(final Context context){
  
  final String wapId = getWapApnId(context);
  String apnId = getApn(context);
  //若当前apn不是wap,则切换至wap
  if(!wapId.equals(apnId)){
   APN_NET_ID = apnId;
   setApn(context,wapId);
   //切换apn需要一定时间,先让等待2秒
   try {
    Thread.sleep(2000);
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
   return true;
  }
  return false;
}
所有的apn信息都是存在数据表里,可以通过adb pull data/data/com.Android.providers.telephony d:/ 直接拷出来,不过前提是手机有root权限:[java] private static String getApn(Context context){
        ContentResolver resoler = context.getContentResolver();
        String[] projection = new String[]{"_id"};
        Cursor cur = resoler.query(Uri.parse("content://telephony/carriers/preferapn"),projection, null, null, null);
        String apnId = null;
        if(cur!=null;;cur.moveToFirst()){
            do {
                apnId = cur.getString(cur.getColumnIndex("_id"));
            } while (cur.moveToNext());
        }
        return apnId;
    }
    /**
     * 设置接入点
     * @param id
     */
    private static void setApn(Context context ,String id){
        Uri uri = Uri.parse("content://telephony/carriers/preferapn");    
        ContentResolver resolver = context.getContentResolver();  
        ContentValues values = new ContentValues();  
        values.put("apn_id", id);  
        resolver.update(uri, values, null, null);
    }
    private static String APN_NET_ID = null;
    /**
     * 取到wap接入點的id
     * @return
     */
    private static String getWapApnId(Context context){
        ContentResolver contentResolver = context.getContentResolver();
        String[] projection = new String[]{"_id","proxy"};
        Cursor cur = contentResolver.query(Uri.parse("content://telephony/carriers"), projection, "current = 1", null, null);
        if(cur!=null;;cur.moveToFirst()){
            do {
                String id = cur.getString(0);
                String proxy = cur.getString(1);
                if(!TextUtils.isEmpty(proxy)){
                    return id;
                }
            } while (cur.moveToNext());
        }
        return null;
    }
private static String getApn(Context context){
  ContentResolver resoler = context.getContentResolver();
  String[] projection = new String[]{"_id"};
  Cursor cur = resoler.query(Uri.parse("content://telephony/carriers/preferapn"),projection, null, null, null);
  String apnId = null;
  if(cur!=null;;cur.moveToFirst()){
   do {
    apnId = cur.getString(cur.getColumnIndex("_id"));
   } while (cur.moveToNext());
  }
  return apnId;
}
/**
  * 设置接入点
  * @param id
  */
private static void setApn(Context context ,String id){
  Uri uri = Uri.parse("content://telephony/carriers/preferapn");  
  ContentResolver resolver = context.getContentResolver();
  ContentValues values = new ContentValues();
  values.put("apn_id", id);
  resolver.update(uri, values, null, null);
}
private static String APN_NET_ID = null;
/**
  * 取到wap接入點的id
  * @return
  */
private static String getWapApnId(Context context){
  ContentResolver contentResolver = context.getContentResolver();
  String[] projection = new String[]{"_id","proxy"};
  Cursor cur = contentResolver.query(Uri.parse("content://telephony/carriers"), projection, "current = 1", null, null);
  if(cur!=null;;cur.moveToFirst()){
   do {
    String id = cur.getString(0);
    String proxy = cur.getString(1);
    if(!TextUtils.isEmpty(proxy)){
     return id;
    }
   } while (cur.moveToNext());
  }
  return null;
}

取wap接入点的id方法中,就是从carriers表中读取到current=1的条目,只有这种条目能够显示在手机的apn设置中,即:





接下来这个方法,是处理发彩信请求:
[java] private static boolean sendMMMS(List<String> list,final Context context, byte[] pdu) throws Exception {
        // HDR_AVLUE_ACCEPT_LANGUAGE = getHttpAcceptLanguage();  
        if(list==null){
            myHandler.post(new Runnable() {
                
                @Override
                public void run() {
                    Toast.makeText(context, "找不到sim卡", Toast.LENGTH_LONG).show();
                }
            });
            return false;
        }
        String mmsUrl = (String) list.get(0);
        String mmsProxy = (String) list.get(1);
        HttpClient client = null;
        try {
            URI hostUrl = new URI(mmsUrl);
            HttpHost target = new HttpHost(hostUrl.getHost(),
                    hostUrl.getPort(), HttpHost.DEFAULT_SCHEME_NAME);
            client = AndroidHttpClient.newInstance("Android-Mms/2.0");
            HttpPost post = new HttpPost(mmsUrl);
            ByteArrayEntity entity = new ByteArrayEntity(pdu);
            entity.setContentType("application/vnd.wap.mms-message");
            post.setEntity(entity);
            post.addHeader(HDR_KEY_ACCEPT, HDR_VALUE_ACCEPT);
            post.addHeader(HDR_KEY_ACCEPT_LANGUAGE, HDR_VALUE_ACCEPT_LANGUAGE);

            HttpParams params = client.getParams();
            HttpProtocolParams.setContentCharset(params, "UTF-8");

            ConnRouteParams.setDefaultProxy(params, new HttpHost(mmsProxy,
                    80));
            HttpResponse response = client.execute(target, post);
            StatusLine status = response.getStatusLine();
            System.out.println("status : " + status.getStatusCode());
            if (status.getStatusCode() != 200) {
                throw new IOException("HTTP error: " + status.getReasonPhrase());
            }
            //彩信发送完毕后检查是否需要把接入点切换回来  
            if(null!=APN_NET_ID){
                setApn(context,APN_NET_ID);
            }
            return true;

        } catch (Exception e) {
            e.printStackTrace();
            Log.d(TAG, "彩信发送失败:"+e.getMessage());
            //发送失败处理  
        }
        return false;
    }
private static boolean sendMMMS(List<String> list,final Context context, byte[] pdu) throws Exception {
  // HDR_AVLUE_ACCEPT_LANGUAGE = getHttpAcceptLanguage();
  if(list==null){
   myHandler.post(new Runnable() {
    
    @Override
    public void run() {
     Toast.makeText(context, "找不到sim卡", Toast.LENGTH_LONG).show();
    }
   });
   return false;
  }
  String mmsUrl = (String) list.get(0);
  String mmsProxy = (String) list.get(1);
  HttpClient client = null;
  try {
   URI hostUrl = new URI(mmsUrl);
   HttpHost target = new HttpHost(hostUrl.getHost(),
     hostUrl.getPort(), HttpHost.DEFAULT_SCHEME_NAME);
   client = AndroidHttpClient.newInstance("Android-Mms/2.0");
   HttpPost post = new HttpPost(mmsUrl);
   ByteArrayEntity entity = new ByteArrayEntity(pdu);
   entity.setContentType("application/vnd.wap.mms-message");
   post.setEntity(entity);
   post.addHeader(HDR_KEY_ACCEPT, HDR_VALUE_ACCEPT);
   post.addHeader(HDR_KEY_ACCEPT_LANGUAGE, HDR_VALUE_ACCEPT_LANGUAGE);
   HttpParams params = client.getParams();
   HttpProtocolParams.setContentCharset(params, "UTF-8");
   ConnRouteParams.setDefaultProxy(params, new HttpHost(mmsProxy,
     80));
   HttpResponse response = client.execute(target, post);
   StatusLine status = response.getStatusLine();
   System.out.println("status : " + status.getStatusCode());
   if (status.getStatusCode() != 200) {
    throw new IOException("HTTP error: " + status.getReasonPhrase());
   }
   //彩信发送完毕后检查是否需要把接入点切换回来
   if(null!=APN_NET_ID){
    setApn(context,APN_NET_ID);
   }
   return true;
  } catch (Exception e) {
   e.printStackTrace();
   Log.d(TAG, "彩信发送失败:"+e.getMessage());
   //发送失败处理
  }
  return false;
}
发彩信程序主入口:
[java] private static String HDR_VALUE_ACCEPT_LANGUAGE = "";
    private static final String HDR_KEY_ACCEPT = "Accept";
    private static final String HDR_KEY_ACCEPT_LANGUAGE = "Accept-Language";
    private static final String HDR_VALUE_ACCEPT = "*/*, application/vnd.wap.mms-message, application/vnd.wap.sic";
    /**
     * 发彩信接口 by liuhanzhi
     * @param context
     * @param phone 手机号
     * @param subject 主题
     * @param text  文字
     * @param imagePath 图片路径    
     * @param audioPath 音频路径
     */
    public static void send(final Context context,String phone,String subject,String text,String imagePath,String audioPath) {
//      String subject = "测试彩信";  
        Log.v("MmsTestActivity", subject);
//      String recipient = "18911722352";// 138xxxxxxx  
        SendReq sendRequest = new SendReq();
        EncodedStringValue[] sub = EncodedStringValue.extract(subject);
        if (sub != null ;; sub.length > 0) {
            sendRequest.setSubject(sub[0]);
        }
        EncodedStringValue[] phoneNumbers = EncodedStringValue
                .extract(phone);
        if (phoneNumbers != null ;; phoneNumbers.length > 0) {
            sendRequest.addTo(phoneNumbers[0]);
        }
        PduBody pduBody = new PduBody();
        if(!TextUtils.isEmpty(text)){
            PduPart partPdu3 = new PduPart();
            partPdu3.setCharset(CharacterSets.UTF_8);
            partPdu3.setName("mms_text.txt".getBytes());
            partPdu3.setContentType("text/plain".getBytes());
            partPdu3.setData(text.getBytes());
            pduBody.addPart(partPdu3);
        }
        if(!TextUtils.isEmpty(imagePath)){
            PduPart partPdu = new PduPart();
            partPdu.setCharset(CharacterSets.UTF_8);
            partPdu.setName("camera.jpg".getBytes());
            partPdu.setContentType("image/png".getBytes());
//      partPdu.setDataUri(Uri.parse("http://www.atcpu.com/uploadfile/2012/0414/20120414101424728.jpg"));  
            partPdu.setDataUri(Uri.fromFile(new File(imagePath)));
            pduBody.addPart(partPdu);
        }
        if(!TextUtils.isEmpty(audioPath)){
            PduPart partPdu2 = new PduPart();
            partPdu2.setCharset(CharacterSets.UTF_8);
            partPdu2.setName("speech_test.amr".getBytes());
            partPdu2.setContentType("audio/amr".getBytes());
            // partPdu2.setContentType("audio/amr-wb".getBytes());  
//          partPdu2.setDataUri(Uri.parse("file://mnt//sdcard//.lv//audio//1326786209801.amr"));  
            partPdu2.setDataUri(Uri.fromFile(new File(audioPath)));
            pduBody.addPart(partPdu2);
        }

        sendRequest.setBody(pduBody);
        final PduComposer composer = new PduComposer(context, sendRequest);
        final byte[] bytesToSend = composer.make();
        final List<String> list = getSimMNC(context);
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                //因为在切换apn过程中需要一定时间,所以需要加上一个重试操作  
                int retry = 0;
                do {
                    Log.d(TAG, "重试次数:"+(retry+1));
                    try {
                        if (sendMMMS(list, context, bytesToSend)) {
                            myHandler.post(new Runnable() {

                                @Override
                                public void run() {
                                    Toast.makeText(context, "彩信发送成功!",
                                            Toast.LENGTH_LONG).show();
                                }
                            });
                            return;
                        }
                        retry++;
                        Thread.sleep(2000);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                } while (retry < 5);
                myHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(context, "彩信发送失败!", Toast.LENGTH_LONG).show();
                    }
                });
            }
        });
        t.start();

    }



喜欢0 评分0
游客

返回顶部