2011年2月21日月曜日



f:id:bs-android:20110217021016j:image


弊社からは今年初めてMWCに参加しました。


今年のMWCでも数多くの製品が発表され、全部紹介するのは量が多すぎて不可能なので、まとめ記事をさらにまとめて、全体の概要の解説と、注目しておくべきところをピックアップしてみました。


まとめ記事のまとめ


MWCのまとめ記事をさらにまとめてみました。







最低限知っておくべき情報は




といったところでしょうか。


デュアルコアの端末は、端末の表現能力を別次元に引き上げていて、携帯ゲーム機器と比べても何の遜色もない仕上がりになっており、ぐりぐり動くアプリが数多く開発されていて、かなりの勢いを感じました。


もはや問題は消費電力だけでしょう。


個人的に欲しいと感じたのは、MOTOROLAのAtrixとSonyEricssonのXperia Playです。



D



D


同じようなスマートフォンが山のように増えてきたので、こういったとんがった端末ももっと増えて欲しいですね。





Googleブースの様子


MWCに今年初出展したGoogleブースに置かれていた端末を見てみましょう。


端末が回転寿司のようにくるくる回っていました。動画を撮影したのですが、一周するのに、なんと7分もかかりました。



D





回転Android端末コーナーの近くにAndroid端末の情報を閲覧できるディスプレイが置いてあったので、すべて写真に収めてきました。


f:id:bs-android:20110216231441j:image


しかし、公式発表の27メーカー、170機種に全然足りておらず、109機種でした。どんな掲載基準があったのかは不明です。





































































Acer
f:id:bs-android:20110216231454j:imagebeTouch E120
beTouch E130
beTouch E140
f:id:bs-android:20110216231502j:imageLiquid MT
Liquidmini
ALCATEL onetouch
f:id:bs-android:20110216231510j:imageOT-980
ASUS
f:id:bs-android:20110216231516j:imageA10
A50
DELL
f:id:bs-android:20110216231523j:imageVenue
Aero
Streak
Streak 7
FIH(FOXCONN)
f:id:bs-android:20110216231533j:imageCSL MI410
Orange Boston
Viewsonic ViewPad7
FUJITSU
f:id:bs-android:20110216231543j:imageREGZA Phone IS04
REGZA Phone T-01C
Google
f:id:bs-android:20110216231557j:imageNEXUS S
Nexus One
HTC
f:id:bs-android:20110216231613j:imageAria
Droid Incredible
Desire
f:id:bs-android:20110216231620j:imageDesire HD
Desire S
EVO 4G
f:id:bs-android:20110216231628j:imageIncredible S
LEGEND
THUNDERBOLT
f:id:bs-android:20110216231635j:imageWILDFIRE
Wildfire S
Magic
f:id:bs-android:20110216231642j:imageG1
G2
f:id:bs-android:20110216231649j:imageMyTouch 3G Slide
MyTouch 4G
HUAWEI
f:id:bs-android:20110216231703j:imageIDEOS
IDEOS X3
IDEOS X5
f:id:bs-android:20110216231716j:imageIDEOS S7
IDEOS S7 SLIM
kt tech
f:id:bs-android:20110216231722j:imageTAKE(EV-S100)
KYOCERA
f:id:bs-android:20110216231729j:imageEcho
Zio
LG
f:id:bs-android:20110216231810j:imageGT-540
Axis
GW620
f:id:bs-android:20110216231819j:imageOptimus 2X
Optimus Black
Optimus Chat
f:id:bs-android:20110216231827j:imageOptimus Chic
Optimus M
Optimus Mach
f:id:bs-android:20110216231834j:imageOptimus Me
Optimus One
Optimus Q
f:id:bs-android:20110216231841j:imageOptimus S
Optimus T
Optimus U
f:id:bs-android:20110216231849j:imageOptimus V
Optimus Z
Shine Plus
f:id:bs-android:20110216231856j:imageRevolution
Optimus 3D
Optimus PAD
MOTOROLA
f:id:bs-android:20110216231908j:imageBravo
Charm
Defy
f:id:bs-android:20110216231915j:imageDroid 2 Global
Droid 2
Droid Pro
f:id:bs-android:20110216231922j:imageDroid X
Flipout
Backflip
f:id:bs-android:20110216231929j:imageAtrix
Xoom
NEC
f:id:bs-android:20110216231936j:imageCloud Communicator LT-S
PANTECH
f:id:bs-android:20110216231948j:imageIZAR BLACKI
MIRACH
SIRIUS ALPHA
f:id:bs-android:20110216231955j:imageSIRIUS
VEGA BLACK
VEGA X
SAMSUNG
f:id:bs-android:20110216232007j:imageCaptivate
Epic 4G
Galaxy Beam
f:id:bs-android:20110216232015j:imageGalaxy S
Galaxy Spica
Vibrant
f:id:bs-android:20110216232021j:imageGalaxy Tab
Continuum
Galaxy Ace
f:id:bs-android:20110216232028j:imageGalaxy Fit
Galaxy Mini
Galaxy Gio
f:id:bs-android:20110216232035j:imageGalaxy Tab 10.1
Galaxy S 〓
SHARP
f:id:bs-android:20110216232044j:imageIS03
SBM003SH
SH-03C
※何故かIS01、LYNX、LYNX3D、IS05は無し
Sony Ericsson
f:id:bs-android:20110216232055j:imageXperia X8
Xperia X10
Xperia X10 mini
f:id:bs-android:20110216232102j:imageXperia X10 mini pro
Xperia arc
Xperia neo
f:id:bs-android:20110216232109j:imageXperia pro
ZTE
f:id:bs-android:20110216232119j:imageV9
ZTE-C R750
ZTE-BLADE

今回発表された端末は、公式のAndroid端末比較サイトに順次掲載されていくと思います。





Googleブースの様子は以下の動画がわかりやすいです。巨大なAndroidのマスコットキャラクターがいっぱい。滑り台もありました。



D





また、会場ではAndroid関連のブースにAndroidマスコットキャラ型ピンバッジが配られていました。その種類はなんと86種類!我々はスタートが出遅れて3種類くらいしか集められませんでした。無念。


86種類全部の写真





ストラップにピンバッジをたくさん付けて首からぶら下げていると、バッジのトレードを申し込まれたりして、それをきっかけに交流が進むことも多かったようです。バッジの多い人は超人気者になっていました。


今後のGoogleのイベントではレアなピンバッジが配られたりするかも知れませんね。





Mobile World Congress 2011(MWC2011) まとめのまとめとGoogleブースに展示されていた109機種



f:id:bs-android:20110217021016j:image


弊社からは今年初めてMWCに参加しました。


今年のMWCでも数多くの製品が発表され、全部紹介するのは量が多すぎて不可能なので、まとめ記事をさらにまとめて、全体の概要の解説と、注目しておくべきところをピックアップしてみました。


まとめ記事のまとめ


MWCのまとめ記事をさらにまとめてみました。







最低限知っておくべき情報は




といったところでしょうか。


デュアルコアの端末は、端末の表現能力を別次元に引き上げていて、携帯ゲーム機器と比べても何の遜色もない仕上がりになっており、ぐりぐり動くアプリが数多く開発されていて、かなりの勢いを感じました。


もはや問題は消費電力だけでしょう。


個人的に欲しいと感じたのは、MOTOROLAのAtrixとSonyEricssonのXperia Playです。



D



D


同じようなスマートフォンが山のように増えてきたので、こういったとんがった端末ももっと増えて欲しいですね。





Googleブースの様子


MWCに今年初出展したGoogleブースに置かれていた端末を見てみましょう。


端末が回転寿司のようにくるくる回っていました。動画を撮影したのですが、一周するのに、なんと7分もかかりました。



D





回転Android端末コーナーの近くにAndroid端末の情報を閲覧できるディスプレイが置いてあったので、すべて写真に収めてきました。


f:id:bs-android:20110216231441j:image


しかし、公式発表の27メーカー、170機種に全然足りておらず、109機種でした。どんな掲載基準があったのかは不明です。





































































Acer
f:id:bs-android:20110216231454j:imagebeTouch E120
beTouch E130
beTouch E140
f:id:bs-android:20110216231502j:imageLiquid MT
Liquidmini
ALCATEL onetouch
f:id:bs-android:20110216231510j:imageOT-980
ASUS
f:id:bs-android:20110216231516j:imageA10
A50
DELL
f:id:bs-android:20110216231523j:imageVenue
Aero
Streak
Streak 7
FIH(FOXCONN)
f:id:bs-android:20110216231533j:imageCSL MI410
Orange Boston
Viewsonic ViewPad7
FUJITSU
f:id:bs-android:20110216231543j:imageREGZA Phone IS04
REGZA Phone T-01C
Google
f:id:bs-android:20110216231557j:imageNEXUS S
Nexus One
HTC
f:id:bs-android:20110216231613j:imageAria
Droid Incredible
Desire
f:id:bs-android:20110216231620j:imageDesire HD
Desire S
EVO 4G
f:id:bs-android:20110216231628j:imageIncredible S
LEGEND
THUNDERBOLT
f:id:bs-android:20110216231635j:imageWILDFIRE
Wildfire S
Magic
f:id:bs-android:20110216231642j:imageG1
G2
f:id:bs-android:20110216231649j:imageMyTouch 3G Slide
MyTouch 4G
HUAWEI
f:id:bs-android:20110216231703j:imageIDEOS
IDEOS X3
IDEOS X5
f:id:bs-android:20110216231716j:imageIDEOS S7
IDEOS S7 SLIM
kt tech
f:id:bs-android:20110216231722j:imageTAKE(EV-S100)
KYOCERA
f:id:bs-android:20110216231729j:imageEcho
Zio
LG
f:id:bs-android:20110216231810j:imageGT-540
Axis
GW620
f:id:bs-android:20110216231819j:imageOptimus 2X
Optimus Black
Optimus Chat
f:id:bs-android:20110216231827j:imageOptimus Chic
Optimus M
Optimus Mach
f:id:bs-android:20110216231834j:imageOptimus Me
Optimus One
Optimus Q
f:id:bs-android:20110216231841j:imageOptimus S
Optimus T
Optimus U
f:id:bs-android:20110216231849j:imageOptimus V
Optimus Z
Shine Plus
f:id:bs-android:20110216231856j:imageRevolution
Optimus 3D
Optimus PAD
MOTOROLA
f:id:bs-android:20110216231908j:imageBravo
Charm
Defy
f:id:bs-android:20110216231915j:imageDroid 2 Global
Droid 2
Droid Pro
f:id:bs-android:20110216231922j:imageDroid X
Flipout
Backflip
f:id:bs-android:20110216231929j:imageAtrix
Xoom
NEC
f:id:bs-android:20110216231936j:imageCloud Communicator LT-S
PANTECH
f:id:bs-android:20110216231948j:imageIZAR BLACKI
MIRACH
SIRIUS ALPHA
f:id:bs-android:20110216231955j:imageSIRIUS
VEGA BLACK
VEGA X
SAMSUNG
f:id:bs-android:20110216232007j:imageCaptivate
Epic 4G
Galaxy Beam
f:id:bs-android:20110216232015j:imageGalaxy S
Galaxy Spica
Vibrant
f:id:bs-android:20110216232021j:imageGalaxy Tab
Continuum
Galaxy Ace
f:id:bs-android:20110216232028j:imageGalaxy Fit
Galaxy Mini
Galaxy Gio
f:id:bs-android:20110216232035j:imageGalaxy Tab 10.1
Galaxy S 〓
SHARP
f:id:bs-android:20110216232044j:imageIS03
SBM003SH
SH-03C
※何故かIS01、LYNX、LYNX3D、IS05は無し
Sony Ericsson
f:id:bs-android:20110216232055j:imageXperia X8
Xperia X10
Xperia X10 mini
f:id:bs-android:20110216232102j:imageXperia X10 mini pro
Xperia arc
Xperia neo
f:id:bs-android:20110216232109j:imageXperia pro
ZTE
f:id:bs-android:20110216232119j:imageV9
ZTE-C R750
ZTE-BLADE

今回発表された端末は、公式のAndroid端末比較サイトに順次掲載されていくと思います。





Googleブースの様子は以下の動画がわかりやすいです。巨大なAndroidのマスコットキャラクターがいっぱい。滑り台もありました。



D





また、会場ではAndroid関連のブースにAndroidマスコットキャラ型ピンバッジが配られていました。その種類はなんと86種類!我々はスタートが出遅れて3種類くらいしか集められませんでした。無念。


86種類全部の写真





ストラップにピンバッジをたくさん付けて首からぶら下げていると、バッジのトレードを申し込まれたりして、それをきっかけに交流が進むことも多かったようです。バッジの多い人は超人気者になっていました。


今後のGoogleのイベントではレアなピンバッジが配られたりするかも知れませんね。





2011年1月27日木曜日



Android2.3で搭載されたNFCの、P2Pモードについて調べました。


P2Pモードとは、NFCデバイス同士がP2P通信を行うためのモードです。このモードで動作するNFCデバイス同士は、Bluetoothのペアリングのような煩雑な手順を経ずにデータの送受信が可能になります。


Android2.3のNFCはデフォルトで、ICカードリーターとして振舞うリーダーモードとして動作しています。そのため、P2Pモードとして動作するようにNFCのサービスに指示する必要があります。


しかし、結論から言うとタイトルの通り、Android2.3はP2Pモードになることができません。次のAOSPのコミットメッセージのとおり、リリース段階でP2Pモードは無効になってしまったようです。









ざんねん。。








文責:技術部 ますい





Android 2.3 のNFCはP2Pモードが使えない



Android2.3で搭載されたNFCの、P2Pモードについて調べました。


P2Pモードとは、NFCデバイス同士がP2P通信を行うためのモードです。このモードで動作するNFCデバイス同士は、Bluetoothのペアリングのような煩雑な手順を経ずにデータの送受信が可能になります。


Android2.3のNFCはデフォルトで、ICカードリーターとして振舞うリーダーモードとして動作しています。そのため、P2Pモードとして動作するようにNFCのサービスに指示する必要があります。


しかし、結論から言うとタイトルの通り、Android2.3はP2Pモードになることができません。次のAOSPのコミットメッセージのとおり、リリース段階でP2Pモードは無効になってしまったようです。









ざんねん。。








文責:技術部 ますい





2011年1月11日火曜日



f:id:bs-android:20110107175909j:image,w400,h300
[Nexus SからHTC Desireに電話してる様子]


Android2.3(gingerbread)で追加されたAPIの一つであるSIP APIを試してみました。
Android SDK 2.3に同梱されているSipDemoというプロジェクトを使ってどの様な手順でSIP通話を実現しているか解説します。


実施環境


発信側:
  端末:Nexus S
  アプリ:SipDemo


着信側:
  端末:HTC Desire (android2.2)
  アプリ:Sipdroid version 2.0.1 beta





準備


まずSIPで通話する為にSIPアカウントを取得しました。Android2.3ではSIP通話の為の各種APIを提供してくれますが、SIPアカウントやSIPプロバイダまでは提供してくれません。いっそGoogleがSIPプロバイダ買収して統合しちゃってくれるとうれしいんですが・・・。
今回はiptel.orgという無料のSIPプロバイダを利用しました。
ここで発信、着信用の二つのアカウントを作成しました。iptel.orgのページの下部の「Subscribe!」から新規アカウントの作成ができます。





通話してみる


とりあえず通話をしてみます。
SipDemoをビルドしてNexus Sにインストールし、起動すると以下の様な画面が現れます。
f:id:bs-android:20110110171031p:image,w320,h480


自分のSIPアカウントを設定していない場合は以下のダイアログが表示されます。
OKを選択するとアカウント設定画面が開きます。
f:id:bs-android:20110110163805p:image,w320,h480


アカウント設定画面で、SIPアカウント、パスワード、SIPプロバイダのドメインを設定します。
f:id:bs-android:20110110163804p:image,w320,h480


設定が完了すると、SIPプロバイダにREGISTERを試みます。成功すると、「Ready」の文字列が表示されます。
f:id:bs-android:20110110163803p:image,w320,h480


「Ready」の状態でメニューを表示し、「Call someone」を選択します。
f:id:bs-android:20110110163802p:image,w320,h480


発信する相手先を入力するダイアログが表示されます。
ここに相手のSIPURI(例:moge@sip.hoge.jp)を入力し、「OK」ボタンを押下すると相手にINVAITEします。
f:id:bs-android:20110110163801p:image,w320,h480


通話に成功した場合、マイクをタッチしている間、自分の声を相手に送信します。


f:id:bs-android:20110110164442p:image,w320,h480








SipDemoおよびAPIの説明


■SipDemoの場所
 「Android SDK Samples for Android API 9, revision 1」がインストールされていれば下記の場所にプロジェクトがあるはずです。


    <android-sdk>/samples/android-9/SipDemo





■SipDemoの構成
 SipDemoのファイル構成です。XMLファイル類は特に気にするようなものは無かったので割愛します。


  IncomingCallReceiver.java //着信を受けるBroadcastReceiver
  SipSettings.java //SIPプロファイルの設定を行うPreferenceActivity
  WalkieTalkieActivity.java //SIPプロファイルの初期化、REGISTER、発信等を行うActivity





■AndroidManifest.xml
 AndroidでSIPを利用する場合、AndroidManifest.xmlに以下のuses-permissionを追加してあげる必要があります。


  android.permission.USE_SIP
  android.permission.INTERNET
  android.permission.ACCESS_WIFI_STATE
  android.permission.WAKE_LOCK
  android.permission.RECORD_AUDIO
  android.permission.MODIFY_AUDIO_SETTINGS


 SipDemoではこのうち「android.permission.MODIFY_AUDIO_SETTINGS」の設定が抜けていますので追記してやる必要があります。「android.permission.MODIFY_AUDIO_SETTINGS」が無くても動作しますが、音声設定周りが無効になってしまいます。





■利用するクラス
 SIP通話を行うために利用するクラスです。以下のクラスを使うだけでSIP通話を実現する事ができます。


  android.net.sip.SipManager       //SIPプロバイダへのREGISTERや発信、着信を管理するクラス
  android.net.sip.SipProfile        //自分のSIPプロファイル
  android.net.sip.SipRegistrationListener //SIPプロバイダにREGISTERする際のリスナ
  android.net.sip.SipAudioCall      //SIP通話の音声を管理する
  android.net.sip.SipAudioCall.Listener  //SIP通話の確立や切断、エラー等のリスナ
  android.net.sip.SipException      //SIP周りの例外








発信までの手順


 発信の処理はWalkieTalkieActivity.javaで行っています。




  1. SipManagerを作成する

  2. SipProfileを作成する

  3. SipManager#open(String, SipRegistrationListener)でSIPプロバイダにREGISTERする

  4. SipManager#makeAudioCall(String ,String, SipAudioCall.Listener, int)で相手先に電話をかける

  5. SipAudioCall.Listener#onCallEstablished(SipAudioCall)で音声通話を開始する





1.SipManagerを作成する

 SipManagerはWalkieTalkieActivity.javaの106行目、initializeManager()で作成しています。
 単純にメンバ変数managerがnullの場合SipManager#newInstance(Context)を呼び出しているだけです。



public void initializeManager() {
if(manager == null) {
manager = SipManager.newInstance(this);
}
initializeLocalProfile();
}








2.SipProfileを作成する

 WalkieTalkieActivity.javaの138行目、initializeLocalProfile()内でSipProfileを作成しています。
 SipProfileの作成はSipProfile.Builderクラスを使って行います。コンストラクタにSIPプロバイダで取得したアカウント名、SIPプロバイダのドメイン名を設定します。(例:hoge@sip.moge.jpの場合、「hoge」がアカウント名で「sip.moge.jp」がドメイン名となります。)
 BuilderをnewしたあとsetPassword(String)でアカウントのパスワードをセットします。最後にSipProfile.Builder#build()を呼び出しSipProfileを作成します。



SipProfile.Builder builder = new SipProfile.Builder(username, domain);
builder.setPassword(password);
me = builder.build(); //meはメンバ変数。SipProfile型








3.SipManager#open(SipProfile, String, SipRegistrationListener)でSIPプロバイダにREGISTERする

 WalkieTalkieActivity.javaの142行目、initializeLocalProfile()内でSipProfileを作成した後、SipManager#openでSIPプロバイダに対してREGISTERを行います。
 openする際にSipRegistrationListenerでREGISTERの結果を受け取ります。何故かリスナのセットはSipManager#openを呼び出した後にしろ、との事。
 SipRegistrationListenerは以下の3つのコールバックを持ちます。




  • public void onRegistering(String localProfileUri)                       //REGISTER中

  • public void onRegistrationDone(String localProfileUri, long expiryTime)            //REGISTER成功

  • public void onRegistrationFailed(String localProfileUri, int errorCode, String errorMessage)  //REGISTER失敗


 SipDemoではこれらのコールバック時に、画面に各種状態の文字列を表示させています。
 SipManager#openをする際にPendingIntentをセットしていますが、これは着信の為に利用します。説明は後ほどします。



Intent i = new Intent();i.setAction("android.SipDemo.INCOMING_CALL");
PendingIntent pi = PendingIntent.getBroadcast(this, 0, i, Intent.FILL_IN_DATA);
manager.open(me, pi, null);


// This listener must be added AFTER manager.open is called,
// Otherwise the methods aren't guaranteed to fire.

manager.setRegistrationListener(me.getUriString(), new SipRegistrationListener() {
public void onRegistering(String localProfileUri) {
updateStatus("Registering with SIP Server...");
}

public void onRegistrationDone(String localProfileUri, long expiryTime) {
updateStatus("Ready");
}

public void onRegistrationFailed(String localProfileUri, int errorCode,
String errorMessage) {
updateStatus("Registration failed. Please check settings.");
}
});









4.SipManager#makeAudioCall(String ,String, SipAudioCall.Listener, int)で相手先に電話をかける

 WalkieTalkieActivity.javaの197行目、initiateCall()内でSipManager#makeAudioCall(String, String, SipAudioCall.Listener, int)を呼び出します。引数は自分のSIPURI, 相手のSIPURI,SipAudioCall.Listener,タイムアウト秒です。
 SipAudioCall.Listenerはリスナという名前のくせにクラスです。コールバックの種類が結構多いのでinterfaceだと煩雑だと考えたのでしょうか?必要なコールバックだけオーバーライドして利用します。SipDemoでは相手が着信後200 OKを返し、通信が確立された際に呼び出されるonCallEstablished(SipAudioCall)と、通話を切断した場合に呼び出されるonCallEnded(SipAudioCall)をオーバーライドしています。



SipAudioCall.Listener listener = new SipAudioCall.Listener() {
// Much of the client's interaction with the SIP Stack will
// happen via listeners. Even making an outgoing call, don't
// forget to set up a listener to set things up once the call is established.
@Override
public void onCallEstablished(SipAudioCall call) {
call.startAudio();
call.setSpeakerMode(true);
call.toggleMute();
updateStatus(call);
}

@Override
public void onCallEnded(SipAudioCall call) {
updateStatus("Ready.");
}
};

call = manager.makeAudioCall(me.getUriString(), sipAddress, listener, 30);









5.SipAudioCall.Listener#onCallEstablished(SipAudioCall)で音声通話を開始する

 WalkieTalkieActivity.javaの202行目、SipAudioCall.Listener#onCallEstablished(SipAudioCall)でSipAudioCall#startAudio()を呼び出し音声通話を開始します。
 SipAudioCall#setSpeakerMode(boolean)にtrueをセットしています。これでハンズオンの状態で通話が開始されます。また、SipAudipCall#toggleMute()を呼び出しています。これで自分の音声はミュートされます。このミュートはタッチ処理の中で「タッチされている間だけオン」といった感じで実装されています。普通の電話の様な動作にしたい場合はcall.toggleMute()の行とタッチイベントの処理を削除するだけで実現できます。



@Override
public void onCallEstablished(SipAudioCall call) {
call.startAudio();
call.setSpeakerMode(true);
call.toggleMute();
updateStatus(call);
}











着信-通話までの手順


 着信はIncomingCallReceiver.javaで行います。IncomingCallReceiverはBroadcastReceiverを継承しており、WalkieTalkieActivityが実行されている間だけ着信を受けます。




  1. IncomingCallReceiverをシステムに登録する

  2. SipManagerに着信時に実行されるPendingIntentを登録する

  3. SipManagerを作成する

  4. SipProfileを作成する

  5. SipManager#open(String, SipRegistrationListener)でSIPプロバイダにREGISTERする

  6. IncomingCallReceiver#onReceive(Context, Intent)で通話を開始する





1.IncomingCallReceiverをシステムに登録する

 WalkieTalkieActivity.javaの69行目、onCreate(Bundle)内でIncomingCallReceiverをシステムに登録します。
 IntentFilterには"android.SipDemo.INCOMING_CALL"を指定しています。"android.SipDemo.INCOMING_CALL"のアクションを持つIntentがBroadcastされた場合に受け取る、という事です。



// Set up the intent filter. This will be used to fire an
// IncomingCallReceiver when someone calls the SIP address used by this
// application.
IntentFilter filter = new IntentFilter();
filter.addAction("android.SipDemo.INCOMING_CALL");
callReceiver = new IncomingCallReceiver();
this.registerReceiver(callReceiver, filter);











2.SipManagerに着信時に実行されるPendingIntentを登録する

 WalkieTalkieActivity.javaの142行目、initializeLocalProfile()内でPendingIntentを作成し、SipManager#openで登録しています。このPendingIntentは着信があった場合に実行されます。
 SipDemoでは"android.SipDemo.INCOMING_CALL"のアクションをBroadcastするPendingIntentを登録しています。このアクションはIncomingCallReceiverをシステムに登録する際に指定したIntentFilterと一致します。



Intent i = new Intent();i.setAction("android.SipDemo.INCOMING_CALL");
PendingIntent pi = PendingIntent.getBroadcast(this, 0, i, Intent.FILL_IN_DATA);
manager.open(me, pi, null);





3.SipManagerを作成する

発信と同じなので省略


4.SipProfileを作成する

発信と同じなので省略


5.SipManager#open(String, SipRegistrationListener)でSIPプロバイダにREGISTERする

発信と同じなので省略





6.IncomingCallReceiver#onReceive(Context, Intent)で通話を開始する

 IncomingCallReceiver.javaの37行目,onReceive(Context, Intent)で着信の処理を行っています。
ContextをWalkieTalkieActivityにキャストし、SipManager#takeAudioCall(Intent, SipAudioCall.Listener)を呼び出しています。SipManager#takeAudioCallを実行したら、次にSipAudioCall.Listener#onRinging(SipAudioCall, SipProfile)が呼び出されます。おそらく内部で100 TRYING、180 RINGINGを発信側に返してonRinging(SipAudioCall, SipProfile)を呼び出しているのだと思います。ここでSipAudioCall#answerCall(int)を呼び出します。javadocを読んでもいまいち動作が不明ですが、200 OKを返しているのでは無いかと思います。onRingingの後にincamingCall.answerCall(30)を実行しています。未確認ですが、この二回目のanswerCallは不要なんじゃないかなーと思います。
 その後SipAudioCall#startAudio()で通話を開始しています。
 wtActivity.call = incomingCall;でWalkieTalkieActivityのメンバ変数にSipAudioCallを設定していますが、WalkieTalkieActivityを終了したり、メニューの「End Current Call」を選択した時にSipAudioCall#endCall()を実行させる為です。



@Override
public void onReceive(Context context, Intent intent) {
SipAudioCall incomingCall = null;
try {

SipAudioCall.Listener listener = new SipAudioCall.Listener() {
@Override
public void onRinging(SipAudioCall call, SipProfile caller) {
try {
call.answerCall(30);
} catch (Exception e) {
e.printStackTrace();
}
}
};

WalkieTalkieActivity wtActivity = (WalkieTalkieActivity) context;

incomingCall = wtActivity.manager.takeAudioCall(intent, listener);
incomingCall.answerCall(30);
incomingCall.startAudio();
incomingCall.setSpeakerMode(true);
if(incomingCall.isMuted()) {
incomingCall.toggleMute();
}

wtActivity.call = incomingCall;

wtActivity.updateStatus(incomingCall);

} catch (Exception e) {
if (incomingCall != null) {
incomingCall.close();
}
}
}












最後に


SIPに関する面倒なほとんどの処理をSIP APIが抽象化してくれました。
上記で説明した手順だけでSIP通話が行えます。SIP APIを使って、例えばAccountManagerに登録されているGMailのアドレスから自動的にSIPアカウント払い出しを行ってすぐ通話できるアプリ、とか割と簡単に作成できそうですね。



文責:技術部 八木 俊広 (新人/Androidアプリケーション技術者認定試験ベーシック合格(笑)/品川)





概説SipDemo(Android2.3 SIP APIを試す)



f:id:bs-android:20110107175909j:image,w400,h300
[Nexus SからHTC Desireに電話してる様子]


Android2.3(gingerbread)で追加されたAPIの一つであるSIP APIを試してみました。
Android SDK 2.3に同梱されているSipDemoというプロジェクトを使ってどの様な手順でSIP通話を実現しているか解説します。


実施環境


発信側:
  端末:Nexus S
  アプリ:SipDemo


着信側:
  端末:HTC Desire (android2.2)
  アプリ:Sipdroid version 2.0.1 beta





準備


まずSIPで通話する為にSIPアカウントを取得しました。Android2.3ではSIP通話の為の各種APIを提供してくれますが、SIPアカウントやSIPプロバイダまでは提供してくれません。いっそGoogleがSIPプロバイダ買収して統合しちゃってくれるとうれしいんですが・・・。
今回はiptel.orgという無料のSIPプロバイダを利用しました。
ここで発信、着信用の二つのアカウントを作成しました。iptel.orgのページの下部の「Subscribe!」から新規アカウントの作成ができます。





通話してみる


とりあえず通話をしてみます。
SipDemoをビルドしてNexus Sにインストールし、起動すると以下の様な画面が現れます。
f:id:bs-android:20110110171031p:image,w320,h480


自分のSIPアカウントを設定していない場合は以下のダイアログが表示されます。
OKを選択するとアカウント設定画面が開きます。
f:id:bs-android:20110110163805p:image,w320,h480


アカウント設定画面で、SIPアカウント、パスワード、SIPプロバイダのドメインを設定します。
f:id:bs-android:20110110163804p:image,w320,h480


設定が完了すると、SIPプロバイダにREGISTERを試みます。成功すると、「Ready」の文字列が表示されます。
f:id:bs-android:20110110163803p:image,w320,h480


「Ready」の状態でメニューを表示し、「Call someone」を選択します。
f:id:bs-android:20110110163802p:image,w320,h480


発信する相手先を入力するダイアログが表示されます。
ここに相手のSIPURI(例:moge@sip.hoge.jp)を入力し、「OK」ボタンを押下すると相手にINVAITEします。
f:id:bs-android:20110110163801p:image,w320,h480


通話に成功した場合、マイクをタッチしている間、自分の声を相手に送信します。


f:id:bs-android:20110110164442p:image,w320,h480








SipDemoおよびAPIの説明


■SipDemoの場所
 「Android SDK Samples for Android API 9, revision 1」がインストールされていれば下記の場所にプロジェクトがあるはずです。


    <android-sdk>/samples/android-9/SipDemo





■SipDemoの構成
 SipDemoのファイル構成です。XMLファイル類は特に気にするようなものは無かったので割愛します。


  IncomingCallReceiver.java //着信を受けるBroadcastReceiver
  SipSettings.java //SIPプロファイルの設定を行うPreferenceActivity
  WalkieTalkieActivity.java //SIPプロファイルの初期化、REGISTER、発信等を行うActivity





■AndroidManifest.xml
 AndroidでSIPを利用する場合、AndroidManifest.xmlに以下のuses-permissionを追加してあげる必要があります。


  android.permission.USE_SIP
  android.permission.INTERNET
  android.permission.ACCESS_WIFI_STATE
  android.permission.WAKE_LOCK
  android.permission.RECORD_AUDIO
  android.permission.MODIFY_AUDIO_SETTINGS


 SipDemoではこのうち「android.permission.MODIFY_AUDIO_SETTINGS」の設定が抜けていますので追記してやる必要があります。「android.permission.MODIFY_AUDIO_SETTINGS」が無くても動作しますが、音声設定周りが無効になってしまいます。





■利用するクラス
 SIP通話を行うために利用するクラスです。以下のクラスを使うだけでSIP通話を実現する事ができます。


  android.net.sip.SipManager       //SIPプロバイダへのREGISTERや発信、着信を管理するクラス
  android.net.sip.SipProfile        //自分のSIPプロファイル
  android.net.sip.SipRegistrationListener //SIPプロバイダにREGISTERする際のリスナ
  android.net.sip.SipAudioCall      //SIP通話の音声を管理する
  android.net.sip.SipAudioCall.Listener  //SIP通話の確立や切断、エラー等のリスナ
  android.net.sip.SipException      //SIP周りの例外








発信までの手順


 発信の処理はWalkieTalkieActivity.javaで行っています。




  1. SipManagerを作成する

  2. SipProfileを作成する

  3. SipManager#open(String, SipRegistrationListener)でSIPプロバイダにREGISTERする

  4. SipManager#makeAudioCall(String ,String, SipAudioCall.Listener, int)で相手先に電話をかける

  5. SipAudioCall.Listener#onCallEstablished(SipAudioCall)で音声通話を開始する





1.SipManagerを作成する

 SipManagerはWalkieTalkieActivity.javaの106行目、initializeManager()で作成しています。
 単純にメンバ変数managerがnullの場合SipManager#newInstance(Context)を呼び出しているだけです。



public void initializeManager() {
if(manager == null) {
manager = SipManager.newInstance(this);
}
initializeLocalProfile();
}








2.SipProfileを作成する

 WalkieTalkieActivity.javaの138行目、initializeLocalProfile()内でSipProfileを作成しています。
 SipProfileの作成はSipProfile.Builderクラスを使って行います。コンストラクタにSIPプロバイダで取得したアカウント名、SIPプロバイダのドメイン名を設定します。(例:hoge@sip.moge.jpの場合、「hoge」がアカウント名で「sip.moge.jp」がドメイン名となります。)
 BuilderをnewしたあとsetPassword(String)でアカウントのパスワードをセットします。最後にSipProfile.Builder#build()を呼び出しSipProfileを作成します。



SipProfile.Builder builder = new SipProfile.Builder(username, domain);
builder.setPassword(password);
me = builder.build(); //meはメンバ変数。SipProfile型








3.SipManager#open(SipProfile, String, SipRegistrationListener)でSIPプロバイダにREGISTERする

 WalkieTalkieActivity.javaの142行目、initializeLocalProfile()内でSipProfileを作成した後、SipManager#openでSIPプロバイダに対してREGISTERを行います。
 openする際にSipRegistrationListenerでREGISTERの結果を受け取ります。何故かリスナのセットはSipManager#openを呼び出した後にしろ、との事。
 SipRegistrationListenerは以下の3つのコールバックを持ちます。




  • public void onRegistering(String localProfileUri)                       //REGISTER中

  • public void onRegistrationDone(String localProfileUri, long expiryTime)            //REGISTER成功

  • public void onRegistrationFailed(String localProfileUri, int errorCode, String errorMessage)  //REGISTER失敗


 SipDemoではこれらのコールバック時に、画面に各種状態の文字列を表示させています。
 SipManager#openをする際にPendingIntentをセットしていますが、これは着信の為に利用します。説明は後ほどします。



Intent i = new Intent();i.setAction("android.SipDemo.INCOMING_CALL");
PendingIntent pi = PendingIntent.getBroadcast(this, 0, i, Intent.FILL_IN_DATA);
manager.open(me, pi, null);


// This listener must be added AFTER manager.open is called,
// Otherwise the methods aren't guaranteed to fire.

manager.setRegistrationListener(me.getUriString(), new SipRegistrationListener() {
public void onRegistering(String localProfileUri) {
updateStatus("Registering with SIP Server...");
}

public void onRegistrationDone(String localProfileUri, long expiryTime) {
updateStatus("Ready");
}

public void onRegistrationFailed(String localProfileUri, int errorCode,
String errorMessage) {
updateStatus("Registration failed. Please check settings.");
}
});









4.SipManager#makeAudioCall(String ,String, SipAudioCall.Listener, int)で相手先に電話をかける

 WalkieTalkieActivity.javaの197行目、initiateCall()内でSipManager#makeAudioCall(String, String, SipAudioCall.Listener, int)を呼び出します。引数は自分のSIPURI, 相手のSIPURI,SipAudioCall.Listener,タイムアウト秒です。
 SipAudioCall.Listenerはリスナという名前のくせにクラスです。コールバックの種類が結構多いのでinterfaceだと煩雑だと考えたのでしょうか?必要なコールバックだけオーバーライドして利用します。SipDemoでは相手が着信後200 OKを返し、通信が確立された際に呼び出されるonCallEstablished(SipAudioCall)と、通話を切断した場合に呼び出されるonCallEnded(SipAudioCall)をオーバーライドしています。



SipAudioCall.Listener listener = new SipAudioCall.Listener() {
// Much of the client's interaction with the SIP Stack will
// happen via listeners. Even making an outgoing call, don't
// forget to set up a listener to set things up once the call is established.
@Override
public void onCallEstablished(SipAudioCall call) {
call.startAudio();
call.setSpeakerMode(true);
call.toggleMute();
updateStatus(call);
}

@Override
public void onCallEnded(SipAudioCall call) {
updateStatus("Ready.");
}
};

call = manager.makeAudioCall(me.getUriString(), sipAddress, listener, 30);









5.SipAudioCall.Listener#onCallEstablished(SipAudioCall)で音声通話を開始する

 WalkieTalkieActivity.javaの202行目、SipAudioCall.Listener#onCallEstablished(SipAudioCall)でSipAudioCall#startAudio()を呼び出し音声通話を開始します。
 SipAudioCall#setSpeakerMode(boolean)にtrueをセットしています。これでハンズオンの状態で通話が開始されます。また、SipAudipCall#toggleMute()を呼び出しています。これで自分の音声はミュートされます。このミュートはタッチ処理の中で「タッチされている間だけオン」といった感じで実装されています。普通の電話の様な動作にしたい場合はcall.toggleMute()の行とタッチイベントの処理を削除するだけで実現できます。



@Override
public void onCallEstablished(SipAudioCall call) {
call.startAudio();
call.setSpeakerMode(true);
call.toggleMute();
updateStatus(call);
}











着信-通話までの手順


 着信はIncomingCallReceiver.javaで行います。IncomingCallReceiverはBroadcastReceiverを継承しており、WalkieTalkieActivityが実行されている間だけ着信を受けます。




  1. IncomingCallReceiverをシステムに登録する

  2. SipManagerに着信時に実行されるPendingIntentを登録する

  3. SipManagerを作成する

  4. SipProfileを作成する

  5. SipManager#open(String, SipRegistrationListener)でSIPプロバイダにREGISTERする

  6. IncomingCallReceiver#onReceive(Context, Intent)で通話を開始する





1.IncomingCallReceiverをシステムに登録する

 WalkieTalkieActivity.javaの69行目、onCreate(Bundle)内でIncomingCallReceiverをシステムに登録します。
 IntentFilterには"android.SipDemo.INCOMING_CALL"を指定しています。"android.SipDemo.INCOMING_CALL"のアクションを持つIntentがBroadcastされた場合に受け取る、という事です。



// Set up the intent filter. This will be used to fire an
// IncomingCallReceiver when someone calls the SIP address used by this
// application.
IntentFilter filter = new IntentFilter();
filter.addAction("android.SipDemo.INCOMING_CALL");
callReceiver = new IncomingCallReceiver();
this.registerReceiver(callReceiver, filter);











2.SipManagerに着信時に実行されるPendingIntentを登録する

 WalkieTalkieActivity.javaの142行目、initializeLocalProfile()内でPendingIntentを作成し、SipManager#openで登録しています。このPendingIntentは着信があった場合に実行されます。
 SipDemoでは"android.SipDemo.INCOMING_CALL"のアクションをBroadcastするPendingIntentを登録しています。このアクションはIncomingCallReceiverをシステムに登録する際に指定したIntentFilterと一致します。



Intent i = new Intent();i.setAction("android.SipDemo.INCOMING_CALL");
PendingIntent pi = PendingIntent.getBroadcast(this, 0, i, Intent.FILL_IN_DATA);
manager.open(me, pi, null);





3.SipManagerを作成する

発信と同じなので省略


4.SipProfileを作成する

発信と同じなので省略


5.SipManager#open(String, SipRegistrationListener)でSIPプロバイダにREGISTERする

発信と同じなので省略





6.IncomingCallReceiver#onReceive(Context, Intent)で通話を開始する

 IncomingCallReceiver.javaの37行目,onReceive(Context, Intent)で着信の処理を行っています。
ContextをWalkieTalkieActivityにキャストし、SipManager#takeAudioCall(Intent, SipAudioCall.Listener)を呼び出しています。SipManager#takeAudioCallを実行したら、次にSipAudioCall.Listener#onRinging(SipAudioCall, SipProfile)が呼び出されます。おそらく内部で100 TRYING、180 RINGINGを発信側に返してonRinging(SipAudioCall, SipProfile)を呼び出しているのだと思います。ここでSipAudioCall#answerCall(int)を呼び出します。javadocを読んでもいまいち動作が不明ですが、200 OKを返しているのでは無いかと思います。onRingingの後にincamingCall.answerCall(30)を実行しています。未確認ですが、この二回目のanswerCallは不要なんじゃないかなーと思います。
 その後SipAudioCall#startAudio()で通話を開始しています。
 wtActivity.call = incomingCall;でWalkieTalkieActivityのメンバ変数にSipAudioCallを設定していますが、WalkieTalkieActivityを終了したり、メニューの「End Current Call」を選択した時にSipAudioCall#endCall()を実行させる為です。



@Override
public void onReceive(Context context, Intent intent) {
SipAudioCall incomingCall = null;
try {

SipAudioCall.Listener listener = new SipAudioCall.Listener() {
@Override
public void onRinging(SipAudioCall call, SipProfile caller) {
try {
call.answerCall(30);
} catch (Exception e) {
e.printStackTrace();
}
}
};

WalkieTalkieActivity wtActivity = (WalkieTalkieActivity) context;

incomingCall = wtActivity.manager.takeAudioCall(intent, listener);
incomingCall.answerCall(30);
incomingCall.startAudio();
incomingCall.setSpeakerMode(true);
if(incomingCall.isMuted()) {
incomingCall.toggleMute();
}

wtActivity.call = incomingCall;

wtActivity.updateStatus(incomingCall);

} catch (Exception e) {
if (incomingCall != null) {
incomingCall.close();
}
}
}












最後に


SIPに関する面倒なほとんどの処理をSIP APIが抽象化してくれました。
上記で説明した手順だけでSIP通話が行えます。SIP APIを使って、例えばAccountManagerに登録されているGMailのアドレスから自動的にSIPアカウント払い出しを行ってすぐ通話できるアプリ、とか割と簡単に作成できそうですね。



文責:技術部 八木 俊広 (新人/Androidアプリケーション技術者認定試験ベーシック合格(笑)/品川)





Related Posts Plugin for WordPress, Blogger...