SMS メッセージを送受信する方法を理解しました。SMS メッセージを送信するには、クラスのsendTextMessage()
およびsendMultipartTextMessage()
メソッドを呼び出す必要がありました。SmsManager
SMS メッセージを受信するには、受信者をAndroidMainfest.xml
ファイルに登録する必要がありました。onReceive()
次に、のメソッドをオーバーライドする必要がありましたBroadcastReceiver
。以下に例を示します。
MainActivity.java
public class MainActivity extends Activity {
private static String SENT = "SMS_SENT";
private static String DELIVERED = "SMS_DELIVERED";
private static int MAX_SMS_MESSAGE_LENGTH = 160;
// ---sends an SMS message to another device---
public static void sendSMS(String phoneNumber, String message) {
PendingIntent piSent = PendingIntent.getBroadcast(mContext, 0, new Intent(SENT), 0);
PendingIntent piDelivered = PendingIntent.getBroadcast(mContext, 0,new Intent(DELIVERED), 0);
SmsManager smsManager = SmsManager.getDefault();
int length = message.length();
if(length > MAX_SMS_MESSAGE_LENGTH) {
ArrayList<String> messagelist = smsManager.divideMessage(message);
smsManager.sendMultipartTextMessage(phoneNumber, null, messagelist, null, null);
}
else
smsManager.sendTextMessage(phoneNumber, null, message, piSent, piDelivered);
}
}
//More methods of MainActivity ...
}
SMSReceiver.java
public class SMSReceiver extends BroadcastReceiver {
private final String DEBUG_TAG = getClass().getSimpleName().toString();
private static final String ACTION_SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED";
private Context mContext;
private Intent mIntent;
// Retrieve SMS
public void onReceive(Context context, Intent intent) {
mContext = context;
mIntent = intent;
String action = intent.getAction();
if(action.equals(ACTION_SMS_RECEIVED)){
String address, str = "";
int contactId = -1;
SmsMessage[] msgs = getMessagesFromIntent(mIntent);
if (msgs != null) {
for (int i = 0; i < msgs.length; i++) {
address = msgs[i].getOriginatingAddress();
contactId = ContactsUtils.getContactId(mContext, address, "address");
str += msgs[i].getMessageBody().toString();
str += "\n";
}
}
if(contactId != -1){
showNotification(contactId, str);
}
// ---send a broadcast intent to update the SMS received in the
// activity---
Intent broadcastIntent = new Intent();
broadcastIntent.setAction("SMS_RECEIVED_ACTION");
broadcastIntent.putExtra("sms", str);
context.sendBroadcast(broadcastIntent);
}
}
public static SmsMessage[] getMessagesFromIntent(Intent intent) {
Object[] messages = (Object[]) intent.getSerializableExtra("pdus");
byte[][] pduObjs = new byte[messages.length][];
for (int i = 0; i < messages.length; i++) {
pduObjs[i] = (byte[]) messages[i];
}
byte[][] pdus = new byte[pduObjs.length][];
int pduCount = pdus.length;
SmsMessage[] msgs = new SmsMessage[pduCount];
for (int i = 0; i < pduCount; i++) {
pdus[i] = pduObjs[i];
msgs[i] = SmsMessage.createFromPdu(pdus[i]);
}
return msgs;
}
/**
* The notification is the icon and associated expanded entry in the status
* bar.
*/
protected void showNotification(int contactId, String message) {
//Display notification...
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.myexample"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="16"
android:targetSdkVersion="17" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.WRITE_SMS" />
<uses-permission android:name="android.permission.RECEIVE_MMS" />
<uses-permission android:name="android.permission.WRITE" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:debuggable="true"
android:icon="@drawable/ic_launcher_icon"
android:label="@string/app_name" >
<activity
//Main activity...
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
//Activity 2 ...
</activity>
//More acitivies ...
// SMS Receiver
<receiver android:name="com.myexample.receivers.SMSReceiver" >
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
</application>
</manifest>
ただし、同様の方法で MMS メッセージを送受信できるかどうかは疑問でした。いくつかの調査を行った後、ブログで提供されている多くの例は、単純Intent
にネイティブ メッセージ アプリケーションに を渡しています。アプリケーションを終了せずに MMS を送信しようとしています。MMS を送受信する標準的な方法はないようです。誰かがこれを機能させましたか?
また、SMS/MMS ContentProvider が公式の Android SDK の一部ではないことは承知していますが、誰かがこれを実装できたのではないかと考えていました。どんな助けでも大歓迎です。
アップデート
MMS メッセージを受信する BroadcastReceiver
ためにファイルにを追加しましたAndroidManifest.xml
<receiver android:name="com.sendit.receivers.MMSReceiver" >
<intent-filter>
<action android:name="android.provider.Telephony.WAP_PUSH_RECEIVED" />
<data android:mimeType="application/vnd.wap.mms-message" />
</intent-filter>
</receiver>
MMSReceiver クラスでは、onReceive()
メソッドはメッセージの送信元である phoneNumber のみを取得できます。メディア添付ファイル (画像/オーディオ/ビデオ) へのファイル パスや MMS 内のテキストなど、MMS から他の重要なものをどのように取得しますか?
MMSReceiver.java
public class MMSReceiver extends BroadcastReceiver {
private final String DEBUG_TAG = getClass().getSimpleName().toString();
private static final String ACTION_MMS_RECEIVED = "android.provider.Telephony.WAP_PUSH_RECEIVED";
private static final String MMS_DATA_TYPE = "application/vnd.wap.mms-message";
// Retrieve MMS
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
String type = intent.getType();
if(action.equals(ACTION_MMS_RECEIVED) && type.equals(MMS_DATA_TYPE)){
Bundle bundle = intent.getExtras();
Log.d(DEBUG_TAG, "bundle " + bundle);
SmsMessage[] msgs = null;
String str = "";
int contactId = -1;
String address;
if (bundle != null) {
byte[] buffer = bundle.getByteArray("data");
Log.d(DEBUG_TAG, "buffer " + buffer);
String incomingNumber = new String(buffer);
int indx = incomingNumber.indexOf("/TYPE");
if(indx>0 && (indx-15)>0){
int newIndx = indx - 15;
incomingNumber = incomingNumber.substring(newIndx, indx);
indx = incomingNumber.indexOf("+");
if(indx>0){
incomingNumber = incomingNumber.substring(indx);
Log.d(DEBUG_TAG, "Mobile Number: " + incomingNumber);
}
}
int transactionId = bundle.getInt("transactionId");
Log.d(DEBUG_TAG, "transactionId " + transactionId);
int pduType = bundle.getInt("pduType");
Log.d(DEBUG_TAG, "pduType " + pduType);
byte[] buffer2 = bundle.getByteArray("header");
String header = new String(buffer2);
Log.d(DEBUG_TAG, "header " + header);
if(contactId != -1){
showNotification(contactId, str);
}
// ---send a broadcast intent to update the MMS received in the
// activity---
Intent broadcastIntent = new Intent();
broadcastIntent.setAction("MMS_RECEIVED_ACTION");
broadcastIntent.putExtra("mms", str);
context.sendBroadcast(broadcastIntent);
}
}
}
/**
* The notification is the icon and associated expanded entry in the status
* bar.
*/
protected void showNotification(int contactId, String message) {
//Display notification...
}
}
android.provider.Telephonyのドキュメントによると:
ブロードキャスト アクション: 新しいテキスト ベースの SMS メッセージがデバイスによって受信されました。インテントには、次の追加の値があります。
pdus
-メッセージを構成する PDU を含む のObject[]
An 。byte[]
getMessagesFromIntent(android.content.Intent)
このインテントの処理中に BroadcastReceiver がエラーに遭遇した場合、結果コードを適切に設定する必要があります。@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String SMS_RECEIVED_ACTION = "android.provider.Telephony.SMS_RECEIVED";
ブロードキャスト アクション: 新しいデータ ベースの SMS メッセージがデバイスによって受信されました。インテントには、次の追加の値があります。
pdus
-メッセージを構成する PDU を含む のObject[]
An 。byte[]
追加の値は、getMessagesFromIntent(android.content.Intent) を使用して抽出できます。このインテントの処理中に BroadcastReceiver でエラーが発生した場合は、結果コードを適切に設定する必要があります。
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String DATA_SMS_RECEIVED_ACTION = "android.intent.action.DATA_SMS_RECEIVED";
ブロードキャスト アクション: 新しい WAP PUSH メッセージがデバイスによって受信されました。インテントには、次の追加の値があります。
transactionId (Integer)
- WAP トランザクション ID
pduType (Integer)
- WAP PDU タイプ`
header (byte[])
- メッセージのヘッダー
data (byte[])
- メッセージのデータ ペイロード
contentTypeParameters (HashMap<String,String>)
- コンテンツ タイプに関連付けられたパラメータ (WSP コンテンツ タイプ ヘッダーからデコード)このインテントの処理中に BroadcastReceiver でエラーが発生した場合は、結果コードを適切に設定する必要があります。contentTypeParameters の追加値は、名前をキーとするコンテンツ パラメータのマップです。割り当てられていない既知のパラメーターが検出された場合、マップのキーは「unassigned/0x...」になります。ここで、「...」は割り当てられていないパラメーターの 16 進値です。パラメータに No-Value がある場合、マップ内の値は null になります。
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String WAP_PUSH_RECEIVED_ACTION = "android.provider.Telephony.WAP_PUSH_RECEIVED";
アップデート #2
PendingIntent
によって受信されるようにエクストラを渡す方法を理解しましたBroadcastReceiver
:
Android PendingIntent エクストラ、BroadcastReceiver によって受信されない
ただし、エクストラはSMSReceiver ではなくSendBroadcastReceiverに渡されます。SMSReceiverにエクストラを渡すにはどうすればよいですか?
アップデート #3
MMS の受信
そのため、さらに調査を行った後、 を登録するいくつかの提案を見ましたContentObserver
。こうすることで、コンテンツ プロバイダーに変更があったことを検出できるため、content://mms-sms/conversations
着信 MMS を検出できます。私が見つけたこれを機能させるための最も近い例を次に示します。MMS の受信
mainActivity
ただし、 typeの変数がありますServiceController
。ServiceController
クラスはどこに実装されていますか?登録済みの他の実装はありますContentObserver
か?
MMS の送信
MMS の送信に関しては、次の例に出くわしました: Send MMS
問題は、Android v4.2.2 の Nexus 4 でこのコードを実行しようとしたところ、次のエラーが表示されたことです。
java.lang.SecurityException: No permission to write APN settings: Neither user 10099 nor current process has android.permission.WRITE_APN_SETTINGS.
クラスのメソッドでCarriers
ContentProvider を照会した後、エラーがスローされます。getMMSApns()
APNHelper
final Cursor apnCursor = this.context.getContentResolver().query(Uri.withAppendedPath(Carriers.CONTENT_URI, "current"), null, null, null, null);
どうやらAndroid 4.2 で APNs を読み取れないようです
モバイルデータを使用して操作 (MMS の送信など) を実行し、デバイスに存在するデフォルトの APN 設定がわからないすべてのアプリケーションの代替手段は何ですか?
アップデート #4
MMS の送信
この例に従ってみました: MMS を送信
@Samが彼の答えで示唆したように:
You have to add jsoup to the build path, the jar to the build path and import com.droidprism.*; To do that in android, add the jars to the libs directory first, then configure the project build path to use the jars already in the libs directory, then on the build path config click order and export and check the boxes of the jars and move jsoup and droidprism jar to the top of the build order.
そのため、SecurityException エラーは発生しなくなりました。現在、Android KitKat の Nexus 5 でテストしています。サンプル コードを実行すると、次の呼び出しの後に 200 応答コードが返されます。
MMResponse mmResponse = sender.send(out, isProxySet, MMSProxy, MMSPort);
ただし、MMS を送信しようとした相手に確認しました。そして、彼らは MMS を受信したことがないと言いました。