133

SMS メッセージを送受信する方法を理解しました。SMS メッセージを送信するには、クラスのsendTextMessage()およびsendMultipartTextMessage()メソッドを呼び出す必要がありました。SmsManagerSMS メッセージを受信するには、受信者を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の変数がありますServiceControllerServiceControllerクラスはどこに実装されていますか?登録済みの他の実装はあります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.

クラスのメソッドでCarriersContentProvider を照会した後、エラーがスローされます。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 を受信したことがないと言いました。

4

6 に答える 6

15

上記で説明したのとまったく同じ問題が発生しました(t-mobileUSAのGalaxyNexus)。これは、モバイルデータがオフになっているためです。

Jelly Beanでは、[設定]>[データ使用量]>[モバイルデータ]です。

MMSを送信する前、またはMMSを受信する前に、モバイルデータをオンにする必要があることに注意してください。モバイルデータがオフになっているMMSを受信すると、新しいメッセージの通知が届き、ダウンロードボタンが付いたメッセージが届きます。ただし、以前にモバイルデータがない場合、着信MMS添付ファイルは受信されません。メッセージ受信後に電源を入れても。

何らかの理由で、電話プロバイダーがMMSの送受信機能を有効にしている場合、Wi-Fiを使用している場合でも、モバイルデータを有効にする必要があります。モバイルデータが有効になっている場合は、MMSを送受信できます。 Wifiは、デバイス上でインターネットとして表示されています。

モバイルデータをオンにしている場合でも、メッセージをオンにしていないとメッセージが頻繁にハングし、デバイスの再起動が必要になる可能性があるため、これは非常に苦痛です。

于 2013-02-14T13:23:38.310 に答える
7

公式の API サポートはありません。つまり、公開用に文書化されておらず、ライブラリはいつでも変更される可能性があります。あなたがアプリケーションを離れたくないことは理解していますが、他の誰かが疑問に思っていることを意図してそれを行う方法を次に示します.

public void sendData(int num){
    String fileString = "..."; //put the location of the file here
    Intent mmsIntent = new Intent(Intent.ACTION_SEND);
    mmsIntent.putExtra("sms_body", "text");
    mmsIntent.putExtra("address", num);
    mmsIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File(fileString)));
    mmsIntent.setType("image/jpeg");
    startActivity(Intent.createChooser(mmsIntent, "Send"));

}

メッセージの配信を追跡するなどの方法を完全には理解していませんが、これで送信されるはずです。

SMS と同じ方法で、mms の受信を警告することができます。レシーバーのインテント フィルターは次のようになります。

<intent-filter>
    <action android:name="android.provider.Telephony.WAP_PUSH_RECEIVED" />
    <data android:mimeType="application/vnd.wap.mms-message" />
</intent-filter>
于 2013-01-23T18:17:42.903 に答える
3

Androidでmmsを送信するためのSDKサポートはないと思います。少なくとも私がまだ見つけていないのはここを見てください。しかし、男はそれを持っていると主張しました。この投稿をご覧ください。

AndroidのマイアプリケーションからMMSを送信する

于 2013-01-22T06:46:15.103 に答える
-2

SmsListenerClass

public class SmsListener extends BroadcastReceiver {

static final String ACTION =
        "android.provider.Telephony.SMS_RECEIVED";

@Override
public void onReceive(Context context, Intent intent) {

    Log.e("RECEIVED", ":-:-" + "SMS_ARRIVED");

    // TODO Auto-generated method stub
    if (intent.getAction().equals(ACTION)) {

        Log.e("RECEIVED", ":-" + "SMS_ARRIVED");

        StringBuilder buf = new StringBuilder();
        Bundle bundle = intent.getExtras();
        if (bundle != null) {

            Object[] pdus = (Object[]) bundle.get("pdus");

            SmsMessage[] messages = new SmsMessage[pdus.length];
            SmsMessage message = null;

            for (int i = 0; i < messages.length; i++) {

                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    String format = bundle.getString("format");
                    messages[i] = SmsMessage.createFromPdu((byte[]) pdus[i], format);
                } else {
                    messages[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
                }

                message = messages[i];
                buf.append("Received SMS from  ");
                buf.append(message.getDisplayOriginatingAddress());
                buf.append(" - ");
                buf.append(message.getDisplayMessageBody());
            }

            MainActivity inst = MainActivity.instance();
            inst.updateList(message.getDisplayOriginatingAddress(),message.getDisplayMessageBody());

        }

        Log.e("RECEIVED:", ":" + buf.toString());

        Toast.makeText(context, "RECEIVED SMS FROM :" + buf.toString(), Toast.LENGTH_LONG).show();

    }
}

アクティビティ

@Override
public void onStart() {
    super.onStart();
    inst = this;
}

public static MainActivity instance() {
    return inst;
}

public void updateList(final String msg_from, String msg_body) {

    tvMessage.setText(msg_from + " :- " + msg_body);

    sendSMSMessage(msg_from, msg_body);

}

protected void sendSMSMessage(String phoneNo, String message) {

    try {
        SmsManager smsManager = SmsManager.getDefault();
        smsManager.sendTextMessage(phoneNo, null, message, null, null);
        Toast.makeText(getApplicationContext(), "SMS sent.", Toast.LENGTH_LONG).show();
    } catch (Exception e) {
        Toast.makeText(getApplicationContext(), "SMS faild, please try again.", Toast.LENGTH_LONG).show();
        e.printStackTrace();
    }
}

マニフェスト

<uses-permission android:name="android.permission.RECEIVE_SMS"/>
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.SEND_SMS"/>

<receiver android:name=".SmsListener">
        <intent-filter>
            <action android:name="android.provider.Telephony.SMS_RECEIVED" />
        </intent-filter>
    </receiver>
于 2016-03-28T08:39:32.607 に答える