2010年11月16日

[android] XPERIAでAndroid標準の音楽アプリと音声レコーダーを起動する

Gallery3Dと同じようにAndroid標準の音楽アプリと音声レコーダーもランチャーに表示されません。
起動するためのadbコマンドです
// 音楽アプリ
adb shell am start -a android.intent.action.MAIN -n com.android.music/.MusicBrowserActivity

// 音声レコーダー
adb shell am start -a android.intent.action.MAIN -n com.android.soundrecorder/.SoundRecorder
音楽アプリの起動画面
music.png

ボイスレコーダーの起動画面
voice_recorder.png
起動するためのapkをアップしておきます
音楽アプリランチャー:LaunchMusic.apk
音声レコーダーランチャー:LaunchSoundRecorder.apk
posted by meloncake at 04:29| Comment(4) | TrackBack(0) | Android

2010年11月12日

[android] XPERIA(SO-01B) 2.1でGallery3Dを起動する

XPERIA SO-01BのAndroid 2.1にGallery3Dが導入されていますが、mediascapeと機能がバッティングするためか、標準のランチャーに表示されません。

試しに、adbで以下のコマンドを実行するとGallery3Dが起動します
adb shell am start -a android.intent.action.MAIN -n com.cooliris.media/.Gallery

gallery3D.png
下記コードでもGallery3Dの起動が可能です。
private void launchGallery3D() {
  Intent i = new Intent();
  i.setClassName("com.cooliris.media", "com.cooliris.media.Gallery");
  i.setAction(Intent.ACTION_MAIN);
  startActivity(i);
}
Gallery3Dを起動するためのapkを作成しましたのでアップしておきます。 LaunchGallery3D.apk
posted by meloncake at 04:19| Comment(6) | TrackBack(0) | Android

2010年10月24日

[android] iモードとSPモードのWAP PUSH信号(PDU)をデコードしてみた

WAP_PUSH信号を受信した時、WapPushOverSmsクラスが
10-23 13:10:27.779: DEBUG/WAP PUSH(1015): Rx: 000605b0af02800202066a00850903646f636f6d6f2e6e652e6a703f50493d30360001
のようなログを出力します。Rx: 以降に出力されているのが受信したWAP PUSHのPDU(Protocol Data Unit)です。このログを使って、iモードとSPモードのメール受信時のWAP PUSH信号(PDU)をデコードしてみます。

WiFi接続時のiモードメール受信時のPDU
さきほどのログがWiFi接続時のiモードメール受信時のログです。このPDUをデコードしてみます
// WSP header
0x00 - transaction ID
0x06 - pdu type(0x06: push)
0x05 - header length: 0x05
0xb0 - content-type: application/vnd.wap.slc
0xaf - X-Wap-Application-Id
0x02 - length of the Multi-octet-integer
0x80 0x02 - x-wap-docomo:imode.mail.ua

// push data
0x02 - WBXML Version 1.2
0x06 - "-//WAPFORUM//DTD SL 1.0//EN" (Service Loading 1.0)
0x6a - Charset UTF-8
0x00 - String Table Length ( = 0 )
0x85 - <sl>
0x09 - href
0x03 - start of string
0x64 6f 63 6f 6d 6f 2e 6e 65 2e 6a 70 3f 50 49 3d 30 36 - "docomo.ne.jp?PI=06"
0x00 - end of string
0x01 - </sl>
WAP PUSHのSL(service loading)データのhrefに"docomo.ne.jp?PI=06"が設定されるようです。次にSPモードメール着信のケースでデコードしてみます

SPモードメールのメール受信時のPDU
SPモードメールを受信した時のログです。
10-23 23:29:27.823: DEBUG/WAP PUSH(1016): Rx: 0006080302030aaf02905c030d6a008507036d656c6f6e63616b6540******************2e6a700005c3072010102314293001
10-23 23:29:28.116: DEBUG/WAP PUSH(1016): dispatchWapPdu_MailPush Start : appId = 36956
10-23 23:29:28.232: DEBUG/WAP PUSH(1016): call startService : Intent { act=android.provider.Telephony.WAP_PUSH_RECEIVED typ=application/vnd.wap.emn+wbxml cmp=jp.co.nttdocomo.carriermail/.SMSService (has extras) }
SPモードメールのPDUをデコードしてみます(不明点が多くデコードできていない箇所が残っています・・・)。
// WSP header
0x00 - transaction ID
0x06 - pdu type(0x06: push)
0x08 - header length: 0x08
0x03 - length of content-type
0x02 - length of the Multi-octet-integer
0x03 0x0a - application/vnd.wap.emn+wbxml
0xaf - X-Wap-Application-Id
0x02 - length of the Multi-octet-integer
0x90 0x5c - x-oma-docomo:xmd.mail.ua

// push data
0x03 - WBXML Version 1.3
0x0d - "-//WAPFORUM//DTD CHANNEL 1.2//EN" (Channel 1.2)
0x6a - Charset UTF-8
0x00 - String Table Length ( = 0 )
0x85 - <channel>
0x07 - href
0x03 - start of string
** ** ** ** ** ** ** ** ** 40 64 6f 63 6f 6d 6f 2e 6e 65 2e 6a 70: *********@docomo.ne.jp(SPモードメールのメールアドレスのようです)
0x00 - end of string
0x05 - 不明
0xc3 - 不明
0x07 - 不明
0x20 - 不明
0x10 - 不明
0x10 - 不明
0x23 - 不明
0x14 - 不明
0x29 - 不明
0x30 - 不明
0x01 - </channel>
残念ながら、SPモードメールのメール受信時のWAP_PUSHは前回記事のコードでは受信できません。

content-type: application/vnd.wap.emn+wbxml 且つ X-Wap-Application-Id:x-oma-docomo:xmd.mail.uaの WAP PUSHメッセージは明示的にjp.co.nttdocomo.carriermail/.SMSServiceサービスのインテントを呼び出すよう WapPushOverSmsがカスタマイズされているからと思われます。

WAPの技術資料はOMA(OpenMobileAlliance)に掲載されています。
WAPのネーミング規則はOMNA(Open Mobile Naming Authority)にて定義されています。
続きを読む
posted by meloncake at 04:42| Comment(1) | TrackBack(0) | Android

2010年10月23日

[android] SMSでのWAP PUSHを受信するには

android端末でSMSでのWAP PUSHを受信するには、WAP_PUSH_RECEIVEDのブロードキャスト通知を受信します。

IntentFilterの設定
端末がSMSのWAP_PUSHを受信すると"android.provider.Telephony.WAP_PUSH_RECEIVED"アクションのインテント通知がブロードキャストされます。BroadcastReceiverのインテントフィルターにWAP_PUSH_RECEIVEDアクションを登録して、WAP_PUSHの受信通知を受け取ります。このブロードキャスト処理はcom.android.internal.telephony.WapPushOverSmsクラスのdispatchWapPdu_defaultメソッドから発行されているようです。

  
    
    
  


Permissionの設定
WAP_PUSH_RECEIVEDを受信するにはRECEIVE_WAP_PUSH"のパーミッションが必要です。


BroadcastReceiverの処理
dispatchWapPdu_defaultから発行されたWAP_PUSH_RECEIVEDインテントには以下のExtraデータが格納されています
キー名内容備考
transactionIdPush信号のトランザクションID
pduTypePDUタイプ(Push信号なら0x06)詳細は"WAP-230-WSP-20010705-a"のTable 34(PDU Type Assignments)
headerWSP(Wireless Session Protocol)のヘッダ詳細は"WAP-230-WSP-20010705-a" の8.2.4章(Push and Confirmed Push Facilities)
dataPUSH信号の本体WBXML(Wireless Binary XML)形式

public class WapPushReceiver extends BroadcastReceiver {
  private static final String WAP_PUSH_RECEIVED_ACTION = "android.provider.Telephony.WAP_PUSH_RECEIVED";
  private static final String TAG = "WAP_PUSH";

  @Override
  public void onReceive(Context context, Intent intent) {
    if (WAP_PUSH_RECEIVED_ACTION.equals(intent.getAction())) {
      Bundle extras = intent.getExtras();
      if (extras != null) {
        int transactionId = extras.getInt("transactionId");
        int pduType = extras.getInt("pduType");
        byte[] header = extras.getByteArray("header");
        byte[] data = extras.getByteArray("data");
        
        Log.d(TAG, "contentType: " + ((intent.getType() != null) ? intent.getType() : ""));
        Log.d(TAG, "transactionId: " + Integer.toString(transactionId));
        Log.d(TAG, "pduType: " + Integer.toString(pduType));

        if (header != null) {
          for (int i = 0; i < header.length; i++) {
            Log.d(TAG, String.format("header[%03d]: 0x%02x (%s)", i, header[i], (char) header[i]));
          }
        } else {
          Log.d(TAG, "header is null");
        }

        if (data != null) {
          for (int i = 0; i < data.length; i++) {
            Log.d(TAG, String.format("data[%03d]: 0x%02x (%s)", i, data[i], (char) data[i]));
          }
        } else {
          Log.d(TAG, "data is null");
        }
      }
    }
  }
}

動作ログ
WiFi接続時にiモードのメール受信通知がブロードキャストされた時のログです
10-23 13:10:28.263: DEBUG/WAP_PUSH(22039): contentType: application/vnd.wap.slc
10-23 13:10:28.263: DEBUG/WAP_PUSH(22039): transactionId: 0
10-23 13:10:28.263: DEBUG/WAP_PUSH(22039): pduType: 6
10-23 13:10:28.263: DEBUG/WAP_PUSH(22039): header is null
10-23 13:10:28.273: DEBUG/WAP_PUSH(22039): data[000]: 0x02 ( )
10-23 13:10:28.283: DEBUG/WAP_PUSH(22039): data[001]: 0x06 ( )
10-23 13:10:28.303: DEBUG/WAP_PUSH(22039): data[002]: 0x6a (j)
10-23 13:10:28.313: DEBUG/WAP_PUSH(22039): data[003]: 0x00 ( )
10-23 13:10:28.323: DEBUG/WAP_PUSH(22039): data[004]: 0x85 ( )
10-23 13:10:28.333: DEBUG/WAP_PUSH(22039): data[005]: 0x09 ( )
10-23 13:10:28.343: DEBUG/WAP_PUSH(22039): data[006]: 0x03 ( )
10-23 13:10:28.353: DEBUG/WAP_PUSH(22039): data[007]: 0x64 (d)
10-23 13:10:28.363: DEBUG/WAP_PUSH(22039): data[008]: 0x6f (o)
10-23 13:10:28.373: DEBUG/WAP_PUSH(22039): data[009]: 0x63 (c)
10-23 13:10:28.383: DEBUG/WAP_PUSH(22039): data[010]: 0x6f (o)
10-23 13:10:28.393: DEBUG/WAP_PUSH(22039): data[011]: 0x6d (m)
10-23 13:10:28.403: DEBUG/WAP_PUSH(22039): data[012]: 0x6f (o)
10-23 13:10:28.413: DEBUG/WAP_PUSH(22039): data[013]: 0x2e (.)
10-23 13:10:28.423: DEBUG/WAP_PUSH(22039): data[014]: 0x6e (n)
10-23 13:10:28.433: DEBUG/WAP_PUSH(22039): data[015]: 0x65 (e)
10-23 13:10:28.443: DEBUG/WAP_PUSH(22039): data[016]: 0x2e (.)
10-23 13:10:28.453: DEBUG/WAP_PUSH(22039): data[017]: 0x6a (j)
10-23 13:10:28.463: DEBUG/WAP_PUSH(22039): data[018]: 0x70 (p)
10-23 13:10:28.473: DEBUG/WAP_PUSH(22039): data[019]: 0x3f (?)
10-23 13:10:28.483: DEBUG/WAP_PUSH(22039): data[020]: 0x50 (P)
10-23 13:10:28.493: DEBUG/WAP_PUSH(22039): data[021]: 0x49 (I)
10-23 13:10:28.503: DEBUG/WAP_PUSH(22039): data[022]: 0x3d (=)
10-23 13:10:28.523: DEBUG/WAP_PUSH(22039): data[023]: 0x30 (0)
10-23 13:10:28.533: DEBUG/WAP_PUSH(22039): data[024]: 0x36 (6)
10-23 13:10:28.543: DEBUG/WAP_PUSH(22039): data[025]: 0x00 ( )
10-23 13:10:28.553: DEBUG/WAP_PUSH(22039): data[026]: 0x01 ( )

posted by meloncake at 23:59| Comment(0) | TrackBack(0) | Android

2010年10月12日

[android] SMSを受信するには

SMS(Short Message Service)を受信するにはSMS_RECEIVEDのブロードキャスト通知を受信します。

IntentFilterの設定
端末がSMSを受信すると"android.provider.Telephony.SMS_RECEIVED"アクションのインテント通知がブロードキャストされます。BroadcastReceiverのインテントフィルターにSMS_RECEIVEDアクションを登録して、SMSの受信通知を受け取ります。

  
    
  


Permissionの設定
SMS_RECEIVEDを受信するにはRECEIVE_SMSのパーミッション、SMSを読み取るにはREAD_SMSのパーミッションが必要です。



BroadcastReceiverの処理
SMS_RECEIVEDインテントのExtra(キー名:"pdus")にメッセージデータが格納されています。Object[]形式でメッセージが複数格納されていますので、for文等でメッセージを単体に分割します。メッセージ単体はPDU(protocol description unit)形式のbyte[]文字列ですのでSmsMessageクラスのcreateFromPdu(bute[] pdu)メソッドを呼び出し、byte[]形式のPDUデータをSmsMessageインスタンスへデコードします。

public class SMSReceiver extends BroadcastReceiver {
  private static final String SMS_RECEIVED_ACTION = "android.provider.Telephony.SMS_RECEIVED";
  private static final String TAG = "SMSReceiver";

  @Override
  public void onReceive(Context context, Intent intent) {
    if (SMS_RECEIVED_ACTION.equals(intent.getAction())) {
      Bundle extras = intent.getExtras();
      if (extras != null) {
        // pduのデコードとログ出力
        // サンプルのためBroadcastReceiverで処理(本来はServiceで)
        Object[] pdus = (Object[]) extras.get("pdus");
        for (Object pdu: pdus) {
          SmsMessage smsMessage = SmsMessage.createFromPdu((byte[]) pdu);
          Log.d(TAG, "from:" + smsMessage.getOriginatingAddress());
          Log.d(TAG, "time:" + Long.toString(smsMessage.getTimestampMillis()));
          Log.d(TAG, "body:" + smsMessage.getMessageBody().replaceAll("\n", "\t"));
        }
      }
    }
  }
}

※SmsMessageクラスはAPIレベル4(Donuts)を境に機能とパスが変更されています(Donuts以降、android.telephony.gsm.SmsMessageはdeprecated)

API Levelクラス備考
Cupcake(3)までandroid.telephony.gsm.SmsMessageGSMのみ
Donuts(4)以降android.telephony.SmsMessageGSMとCDMA

docomoの電源OFF・圏外時着信通知を受信した時のログです
10-12 01:33:18.840: DEBUG/SMSReceiver(5272): from:DoCoMo SMS
10-12 01:33:18.840: DEBUG/SMSReceiver(5272): time:1286814795000
10-12 01:33:18.840: DEBUG/SMSReceiver(5272): body:10/12 01:29     090********

posted by meloncake at 02:05| Comment(1) | TrackBack(0) | Android