Intent sendIntent = new Intent(Intent.ACTION_SEND, Uri.parse("mms://"));
sendIntent.setType("image/jpeg");
String url = "file://sdcard//tmpPhoto.jpg";
sendIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse(url));
startActivity(Intent.createChooser(sendIntent, "MMS:"));
上面的方法应该都知道,没什么好说的,详细说先后台实现发送彩信。
看了很多博客,和别人搞的代码,基本原理:先构造出你要发送的彩信内容,即构建一个pdu,需要用到以下几个类,这些类都是从android源码的MMS应用中mms.pdu包中copy出来的。你需要将pdu包中的所有类基本上可以实现彩信的发送,但是存在很多问题。
第一,网络切换问题,只能手动切换gprs和apn后才能发送成功。
第二,pdu打包问题,pdu打包方法android源码里有,但没有提供接口,添加资源时候要注意资源类型和格式。
第三,注意区分不同运营商,不同的彩信代理不一样。
解决以上三个问题,基本保证任何网络环境下,不管联通、移动还是电信都可以发送成功。当然你要开通彩信业务。
1.点击发送按钮,检查apn不是cmwap激活apn
info = conManager
.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
String currentAPN = info.getExtraInfo();
MLog.i(TAG, currentAPN + "");
if (!"cmwap".equals(currentAPN))
{
openApn();
} else
{
mobileMmsSender(true);
}
2.激活apn,如果网络状态为"请求开始,等待连接通知,测注册广播,监听网络状态改变。
public void openApn()
{
int i = conManager.startUsingNetworkFeature(
ConnectivityManager.TYPE_MOBILE, "enableMMS");// 打开新的APN连接
switch (i)
{
case 0:
MLog.i(TAG, "APN已经激活,可以使用网络");
if (isSending == false)
{
isSending = true;
mobileMmsSender(false);
}
if (mNChangeReceiver != null && isRegisterReceiver)
{
myApp.unregisterReceiver(mNChangeReceiver);
mNChangeReceiver = null;
isRegisterReceiver = false;
}
break;
case 1:
// 注册广播
IntentFilter filter = new IntentFilter();
filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
myApp.registerReceiver(mNChangeReceiver, filter);
isRegisterReceiver = true;
MLog.i(TAG, "请求开始,等待连接通知");
break;
case 2:
MLog.i(TAG, "apn没有设置好");
break;
case 3:
MLog.i(TAG, "请求失败");
break;
case 4:
MLog.i(TAG, "系统忙,例如net已经连接");
break;
case 5:
MLog.i(TAG, "请求使用wap失败,wifi已经打开");
break;
default:
MLog.i(TAG, "请求错误,错误代码:" + i);
break;
}
}
3.设置网络,优先级,让cmwap网络优先于wifi。
private void MmsWebSet()
{
String currentAPN = info.getExtraInfo();
CommonUtils gprs = new CommonUtils();
Log.i("ss", currentAPN + "");
gprs.gprsEnabled(true, MmsContactsActivity.this);
if (wifiManager.isWifiEnabled())
{
isWifi = true;
ConnectivityManager conManager = (ConnectivityManager) this
.getSystemService(Context.CONNECTIVITY_SERVICE);
conManager
.setNetworkPreference(ConnectivityManager.TYPE_MOBILE_MMS);// 设定首选网络类型。
}
}
4.发送彩信
protected void mobileMmsSender(final boolean defuatWap)
{
// 处理网络
MmsWebSet();
SendMms sendMms = new SendMms(mmsContent, number, subject,
MmsContactsActivity.this, sendListener);
sendMms.sendMMS(defuatWap);
}
public class SendMms {
private static final String TAG = "SendMms";
private String mmsContent = null; // 彩信存放路径
private String number = null; // 选中的手机号
private String subject = ""; // 彩信主题
private Context mContext = null;
private SendMmsListener sendListener = null;
public SendMms(String mmsContent, String number, String subject,
Context mContext, SendMmsListener sendListener) {
super();
this.mmsContent = mmsContent;
this.number = number;
this.subject = subject;
this.mContext = mContext;
this.sendListener = sendListener;
}
public void sendMMS(final boolean defuatWap) {
// 组织彩信包
MakeMMSInfo makeMMs = new MakeMMSInfo();
final MMSInfo mms = makeMMs.makeMMSInfos(mmsContent, subject, mContext,
number);
// 发送并监听状态
new Thread() {
public void run() {
try {
byte[] res = MMSSender.sendMMS(mContext, mms.getMMSBytes(),
defuatWap);
// MLog.i(TAG, "彩信发送成功"+res.length);
if (res != null && res.length != 0) {
mHandler.sendEmptyMessage(0);
}
} catch (Exception e) {
MLog.e(TAG, "" + e.toString());
mHandler.sendEmptyMessage(1);
}
};
}.start();
}
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 0:
sendListener.sendComplete();
break;
case 1:
sendListener.sendFaild();
break;
}
}
};
}
第二,pdu资源打包
组织彩信包,就是按上面发送彩信代码红色部分继续。上彩信包解析和组织pdu包代码
public class MakeMMSInfo {
private String TAG = "MakeMMSInfo";
private Context mContext = null;
public MMSInfo makeMMSInfos(String mmsContent, String subject,
Context context, String number) {
this.mContext = context;
List smilParList = null; // 解析每一帧列表
// 获得smil文件名
String smilFile = FileUtils.getSmilFilesByPath(mmsContent);
// 解析出要添加 的资源
File file = new File(mmsContent + "/" + smilFile);
// 解析xmil文件返回数据
InputStream istream = null;
try {
istream = new FileInputStream(file);
smilParList = ParseSmil.parseSmilPar(istream);
} catch (FileNotFoundException e) {
MLog.e("FileNotFoundException", e.toString());
}
if (subject == null) {
subject = "无主题";
}
final MMSInfo mms = new MMSInfo(mContext, number.toString().replaceAll(
" ", ""), subject);// 发送的手机号
String path = null;
MLog.i(TAG, number.replaceAll(" ", ""));
// 添加smil资源
MLog.i(TAG, mms.getMMSBytes().toString());
mms.addSmilPart("file://mnt" + mmsContent + "/" + smilFile, smilFile);
for (int i = 0; i < smilParList.size(); i++) {
// 添加图片资源
for (int j = 0; j < smilParList.get(i).getSmilBtm().size(); j++) {
path = smilParList.get(i).getSmilBtm().get(j);
mms.addPicturePart("file://mnt" + mmsContent + "/" + path, path);// file://mnt/sdcard//1.jpg
}
// 添加文本资源
for (int j = 0; j < smilParList.get(i).getSmilText().size(); j++) {
path = smilParList.get(i).getSmilText().get(j);
mms.addTextPart(read(mmsContent + "/" + path), path);
}
// 添加音频资源
for (int j = 0; j < smilParList.get(i).getSmilAudio().size(); j++) {
path = smilParList.get(i).getSmilAudio().get(j);
mms.addAudioPart("file://mnt" + mmsContent + "/" + path, path);
}
// 添加视频资源
for (int j = 0; j < smilParList.get(i).getSmilVideo().size(); j++) {
path = smilParList.get(i).getSmilVideo().get(j);
mms.addVideoPart("file://mnt" + mmsContent + "/" + path, path);
}
}
MLog.i(TAG, "添加后:" + mms.getMMSBytes().toString());
return mms;
}
/**
* 读取文件内容
*
* @param filename
* 文件名称
*/
public String read(String filename) {
byte[] data = null;
try {
byte[] buffer = new byte[1024];
File file = new File(filename);
if (!file.exists()) {
Toast.makeText(mContext, R.string.mms_pak_error,
Toast.LENGTH_LONG).show();
return new String(data);
}
FileInputStream inStream = new FileInputStream(file);
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
int len = 0;
while ((len = inStream.read(buffer)) != -1) {
outStream.write(buffer, 0, len);
}
data = outStream.toByteArray();
return new String(data, "gbk");
} catch (IOException e) {
MLog.i(TAG, e.toString());
}
return null;
}
}
解析:根据mms资源包路径,解析smil文件或者mms资源对象,给pdu包添加不同的资源。(注意文本资源编码是gbk)
pdu添加资源代码
public class MMSInfo {
private final static String TAG = "MMSInfo";
private Context con;
private PduBody pduBody;
private String recieverNum;
private static String SUBJECT_STR = "我的主题"; // 彩信主题
public MMSInfo(Context con, String recieverNum, String subject) {
// TODO Auto-generated constructor stub
this.con = con;
this.recieverNum = recieverNum;
pduBody = new PduBody();
SUBJECT_STR = subject;
}
/**
* 添加图片资源
*
* @author
* @param uriStr
* file://mnt/sdcard//1.jpg
*/
public void addPicturePart(String uriStr, String name) {
MLog.i(TAG, "添加图片" + uriStr);
PduPart part = new PduPart();
part.setCharset(CharacterSets.UTF_8);
// part.setName(("图片" + partCount++).getBytes());
part.setName(name.getBytes());
// part.setContentType(("image/jpg" +
// getTypeFromUri(uriStr)).getBytes());// "image/png"
String type = FileUtils.getExtension(uriStr);
if (type.equals("jpg") || type.equals("JPG")) {
part.setContentType(ContentType.IMAGE_JPG.getBytes());
} else if (type.equals("jpeg") || type.equals("JPEG")) {
part.setContentType(ContentType.IMAGE_JPEG.getBytes());
} else if (type.equals("wbmp") || type.equals("WBMP")) {
part.setContentType(ContentType.IMAGE_WBMP.getBytes());
} else if (type.equals("png") || type.equals("PNG")) {
part.setContentType(ContentType.IMAGE_PNG.getBytes());
} else if (type.equals("gif") || type.equals("GIF")) {
part.setContentType(ContentType.IMAGE_GIF.getBytes());
} else {
part.setContentType(ContentType.IMAGE_UNSPECIFIED.getBytes());
}
part.setDataUri(Uri.parse(uriStr));
pduBody.addPart(part);
}
/**
* 添加文本资源
*
* @param text
*/
public void addTextPart(String text, String name) {
MLog.i(TAG, "添加文本" + text);
if (!TextUtils.isEmpty(text)) {
PduPart partPdu3 = new PduPart();
partPdu3.setCharset(CharacterSets.UTF_8);
// partPdu3.setName("mms_text.txt".getBytes());
partPdu3.setName(name.getBytes());
String type = FileUtils.getExtension(text);
if (type.equals("html") || type.equals("HTML")) {
partPdu3.setContentType(ContentType.TEXT_HTML.getBytes());
} else {
partPdu3.setContentType(ContentType.TEXT_PLAIN.getBytes());
}
partPdu3.setData(text.getBytes());
pduBody.addPart(partPdu3);
}
}
/**
* 添加smil文件
*
* @param smil
*/
public void addSmilPart(String smil, String smilFile) {
MLog.i(TAG, "添加smil" + smil);
if (!TextUtils.isEmpty(smil)) {
PduPart partPdu3 = new PduPart();
partPdu3.setCharset(CharacterSets.UTF_8);
partPdu3.setName(smilFile.getBytes());
// partPdu3.setName(name.getBytes());
partPdu3.setContentType(ContentType.APP_SMIL.getBytes());
partPdu3.setDataUri(Uri.parse(smil));//
pduBody.addPart(0, partPdu3);
}
}
/**
* 添加音频文件
*
* @param audio
*/
public void addAudioPart(String audio, String name) {
MLog.i(TAG, "添加音频" + audio);
if (!TextUtils.isEmpty(audio)) {
PduPart partPdu2 = new PduPart();
partPdu2.setCharset(CharacterSets.UTF_8);
// partPdu2.setName("speech_test.amr".getBytes());
partPdu2.setName(name.getBytes());
String type = FileUtils.getExtension(audio);
if (type.equals("amr") || type.equals("AMR")) {
partPdu2.setContentType(ContentType.AUDIO_AMR.getBytes());
} else if (type.equals("mid") || type.equals("MID")) {
partPdu2.setContentType(ContentType.AUDIO_MID.getBytes());
} else if (type.equals("midi") || type.equals("MIDI")) {
partPdu2.setContentType(ContentType.AUDIO_MIDI.getBytes());
} else if (type.equals("mp3") || type.equals("MP3")) {
partPdu2.setContentType(ContentType.AUDIO_MP3.getBytes());
} else if (type.equals("ogg") || type.equals("OGG")) {
partPdu2.setContentType(ContentType.AUDIO_OGG.getBytes());
} else if (type.equals("acc") || type.equals("ACC")) {
partPdu2.setContentType(ContentType.AUDIO_AAC.getBytes());
} else {
partPdu2.setContentType(ContentType.AUDIO_UNSPECIFIED
.getBytes());
}
partPdu2.setDataUri(Uri.parse(audio));
// partPdu2.setDataUri(Uri.fromFile(new File(audioPath)));
pduBody.addPart(partPdu2);
}
}
/**
* 添加视频文件
*
* @param video
*/
public void addVideoPart(String video, String name) {
MLog.i(TAG, "添加视频" + video);
if (!TextUtils.isEmpty(video)) {
PduPart partPdu2 = new PduPart();
partPdu2.setCharset(CharacterSets.UTF_8);
// partPdu2.setName("speech_test.amr".getBytes());
partPdu2.setName(name.getBytes());
String type = FileUtils.getExtension(video);
if (type.equals("MP4") || type.equals("MP4")) {
partPdu2.setContentType(ContentType.VIDEO_MP4.getBytes());
} else if (type.equals("3gp") || type.equals("3GP")) {
partPdu2.setContentType(ContentType.VIDEO_3GPP.getBytes());
} else {
partPdu2.setContentType(ContentType.VIDEO_UNSPECIFIED
.getBytes());
}
partPdu2.setDataUri(Uri.parse(video));
// partPdu2.setDataUri(Uri.fromFile(new File(audioPath)));
pduBody.addPart(partPdu2);
}
}
/**
* 获得彩信包数据͵"http://mmsc.monternet.com"
*
* @author
* @return
*/
public byte[] getMMSBytes() {
PduComposer composer = new PduComposer(con, initSendReq());
return composer.make();
}
/**
* 初始化SendReq
*
* @author
* @return
*/
private SendReq initSendReq() {
SendReq req = new SendReq();
EncodedStringValue[] sub = EncodedStringValue.extract(SUBJECT_STR);
if (sub != null && sub.length > 0) {
req.setSubject(sub[0]);// 添加主题
}
EncodedStringValue[] rec = EncodedStringValue.extract(recieverNum);
// if (rec != null && rec.length > 0) {
// req.addTo(rec[0]);// 添加接受者
// }
for (int i = 0; i < rec.length; i++) {
req.addTo(rec[i]);// 添加接受者
MLog.i(TAG, "添加接受者:" + rec[i]);
}
req.setBody(pduBody);
return req;
}
}
解析:添加资源时候要区分不同资源,在区分不同的资源格式,才能正常发送。
网络切换和pdu打包完成,剩下的就是调用网关发送了,我只用到移动发送,只提供移动的,想要区分,只要根据imsi卡号设置不同的网关参数即可。
public class MMSSender {
private static final String TAG = "MMSSender";
public static String mmscUrl = "http://mmsc.monternet.com";
public static String mmsProxy = "10.0.0.172";
public static int mmsProt = 80;
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";
public static byte[] sendMMS(Context context, byte[] pdu, boolean defuatWap)
throws IOException {
MLog.i(TAG, "开始发mms");
// HDR_VALUE_ACCEPT_LANGUAGE = getHttpAcceptLanguage();
HDR_VALUE_ACCEPT_LANGUAGE = HTTP.UTF_8;
if (mmscUrl == null) {
throw new IllegalArgumentException("URL must not be null.");
}
ConnectivityManager connMgr = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
int connectTimes = 0;
while (true) {
HttpClient client = null;
try {
if (!defuatWap) {
int inetAddr = lookupHost(mmsProxy);
if (!connMgr.requestRouteToHost(
ConnectivityManager.TYPE_MOBILE_MMS, inetAddr)) {
throw new IOException(
"Cannot establish route to proxy " + inetAddr);
}
}
// Make sure to use a proxy which supports CONNECT.
// client = HttpConnector.buileClient(context);
HttpHost httpHost = new HttpHost(mmsProxy, mmsProt);
HttpParams httpParams = new BasicHttpParams();
httpParams
.setParameter(ConnRouteParams.DEFAULT_PROXY, httpHost);
HttpConnectionParams.setConnectionTimeout(httpParams, 10000);
client = new DefaultHttpClient(httpParams);
HttpPost post = new HttpPost(mmscUrl);
// mms PUD START
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);
post.addHeader(
"user-agent",
"Mozilla/5.0(Linux;U;Android 2.1-update1;zh-cn;ZTE-C_N600/ZTE-C_N600V1.0.0B02;240*320;CTC/2.0)AppleWebkit/530.17(KHTML,like Gecko) Version/4.0 Mobile Safari/530.17");
// mms PUD END
HttpParams params = client.getParams();
HttpProtocolParams.setContentCharset(params, "UTF-8");
MLog.i(TAG, "执行代理请求");
// PlainSocketFactory localPlainSocketFactory =
// PlainSocketFactory.getSocketFactory();
MLog.i(TAG, post.getAllHeaders().toString());
HttpResponse response = client.execute(post);
StatusLine status = response.getStatusLine();
Log.d(TAG, "status " + status.getStatusCode());
if (status.getStatusCode() != 200) { // HTTP 200
Log.e(TAG, "!200");
throw new IOException("HTTP error: "
+ status.getReasonPhrase());
}
HttpEntity resentity = response.getEntity();
Header[] headers = response.getAllHeaders();
for (int i = 0; i < headers.length; i++) {
Log.i(TAG,
headers[i].getName() + "=" + headers[i].getValue()
+ ";");
}
byte[] body = null;
if (resentity != null) {
try {
if (resentity.getContentLength() > 0) {
body = new byte[(int) resentity.getContentLength()];
DataInputStream dis = new DataInputStream(
resentity.getContent());
try {
dis.readFully(body);
} finally {
try {
dis.close();
} catch (IOException e) {
MLog.e(TAG, "" + e.toString());
}
}
}
} finally {
if (entity != null) {
entity.consumeContent();
}
}
}
Log.d(TAG, "result:" + new String(body));
MLog.i(TAG, "返回结果" + new String(body));
return body;
} catch (Exception e) {
MLog.e(TAG, "" + e.toString());
connectTimes++;
if (connectTimes < Config.MSG_RESET_REQUEST_COUNT) {
continue;
} else {
throw new IOException("Cannect error! ");
}
}
}
}
// TODO: move this to android-common
public static int lookupHost(String hostname) {
InetAddress inetAddress;
try {
inetAddress = InetAddress.getByName(hostname);
} catch (UnknownHostException e) {
return -1;
}
byte[] addrBytes;
int addr;
addrBytes = inetAddress.getAddress();
addr = ((addrBytes[3] & 0xff) << 24) | ((addrBytes[2] & 0xff) << 16)
| ((addrBytes[1] & 0xff) << 8) | (addrBytes[0] & 0xff);
return addr;
}
}
以上为我彩信发送过程,如有问题,请多多指教。。。。