Android彩信发送

彩信发送,首先直接上调用系统app发彩信的代码:

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;
	}

}


以上为我彩信发送过程,如有问题,请多多指教。。。。

 


 

          

你可能感兴趣的:(android,功能实现技巧,移动通信-学习记录)