第 4 章ネットワークプログラミング ているため、簡単に取り扱うことができます。 4.12 HttpCIient (Apache Http) GET / POST InputStream / OutputStream Android では Apache の HttpClient が標準で入っているので、 HttpClient も 使うことができます。こちらも先ほどと同様のアクセスをしてみましよう ( リス ト 4.26 ) 。 リスト 4.26 : HttpCIient の実装方法 try { HttpGet httpGet = new HttpGet ("http://tomorrowkey.github.i0 ” ) ; "tomorrowkey. github. iO ” ) ; httpGet. addHeader("Host" HttpC1ient httpC1ient = new Defau1tHttpC1ient ( ) ; HttpResponse httpResponse = httpC1ient.execute(httpGet) ; InputStream inputStream = httpResponse.getEntity() . getContent() ; int length ; new byte [ 1024 ] ; byte ロ buffer while ( (length = inputStream. read(buffer) ) ! = Log. d("TEST" , new String(buffer, 0 , length)) ; inputStream. close() ; } catch (Ma1formedURLException e) { throw new RuntimeException(e) ; } catch (IOException e) { throw new RuntimeException(e) ; HttpCIient では、どのような処理になるのか順番に見ていきましよう。 96 HttpGet httpGet = new HttpGet("http://tomorrowkey ・ github. i0 ” ) ; リスト 4.27 : HttpGet オプジェクトの生成 スする URL を指定します ( リスト 4.27 ) 。 GET リクエストなので、 HttpGet オプジェクトを作ります。引数にはアクセ 4.12.1 リクエストを送信する
3.10 GPS を利用した位置情報の取得 private Location mLoc; @Override protected void onCreate(Bund1e savedInstanceState) { super. onCreate (savedInstanceState) ; setContentView(). layout . activity_main) ; / / Goog1e P1ay ServiceK が実装されているか確認 final int result Goog1eP1ayServicesUti1. isGoog1eP1ayServicesAvai1ab1e(this) ; if (result ! = ConnectionResu1t . SUCCESS) { Toast . makeText (this, ” Goog1e P1ay service is not available (status= 十 result 十” ) ー Toast . LENGTH_LONG) . show() ; finish() ; mLocationC1ient @Override new LocationC1ient(this , this, this); protected void onResume() { super. onResume ( ) ; / / Goog1e P1ay Services への接続 mLocationC1ient . connect ( ) ; @Override protected VOid onPause() { super. onPause ( ) ; / / Goog1e P1ay Services との切断 if (mLocationC1ient ! = Ⅱ u11 ) { mLocationC1ient . disconnect ( ) ; @0verride Log. d("LOCATION" , ” LON: ” + 10C. getLongitude() ) ; + 10C . getLatitude()); "LAT : Log. d("LOCATION" mLOC = mLocationCIient . getLastLocation() ; / / 位置情報の取得 Toast. makeText (this, "Connected" , Toast . LENGTH_LONG) . show() ; public void onConnected(Bund1e connectionHint) { @Override Log. d("ERROR" , result . t0String() ) ; "onConnectionFai1ed't , Toast . LENGTH_LONG) . show ( ) ; Toast . makeText (this, / / Goog1e P1ay Services への接続に失敗した public VOid onConnectionFai1ed(ConnectionResu1t result) { @Override public void onDisconnected() { Toast . makeText (this, "l)isconnected" 73 Toast . LENGTH-LONG) . show ( ) ;
3.10 GPS を利用した位置情報の取得 Client#getLastLocation に現在の位置情報が非同期に更新されるので、この値 を使用します。 Google Play Services を使わずに GPS や WiFi を使って位置情報の取得も可 能ですが、 GPS や WiFi の ON/OFF を検出したり、 GPS と WiFi のステータ スを管理しなければならず、かなり面倒なのが実際です。 GoogIe PIay Services の LocationCIient を使うと、「一番良い位置情報を頼 む」ということができ、 GPS/WiFi の区別を実際には意識することはありま ” Goog1e P1ay service is not available (status=" 十 result 十 Toast . makeText (this, if (result ! = ConnectionResu1t . SUCCESS) { isGoog1eP1ayServicesAvai1ab1e(this) ; final int result = Goog1eP1ayServicesUti1. / / Goog1e P1ay Service が有効かどうかチェックを行う setContentView(). layout . activity_main) ; super. onCreate(savedInstanceState) ; protected void onCreate(Bund1e savedInstanceState) { @0verride リスト 3.15 : LocationCIient の取得 LocationCIient の取得は次のようになります ( リスト 3.15 ) 。 せん。 Toast . LENGTH-LONG) . show() ; finish() ; / / LocationC1ient の取得 mLocationC1ient = new LocationC1ient (this, this, this) ; LocationCIient を使用する場合には、 2 つのコールバックを引数に取るので、 リスナーを Activity に設定しておきます ( リスト 3.16 ) 。 リスト 3.16 : リスナーの設定 public class MainActivity extends Activity implements ConnectionCaIIbacks , OnConnectionFaiIedListener 設定されるリスナーは 3 つで、 OnConnectionFailedListener は接続に失敗し た時に呼ばれます ( リスト 3.17 ) 。 71
第 6 章 Andorid でのグラフィック処理 int ロ compi1eSuccess = new int ロ { 0 } ; g1GetShaderiv (shader , GL-COMPILE-STATUS , compi1eSuccess , 0 ) ; if (compi1eSuccess [ 0 ] = GL-FALSE) { throw new RuntimeException (g1GetShaderInf0Log(shader) ) ; 2 3 4 LO 6 7 8 0 -1 2 4 5 6 7 8 0 ) 0 -1 っ 3 4 5 6 ー 8 9 0 1 つんっ ") 4- ロ 0 6 っ′一 8 1 1 1 -1 1 1 1 1 2 つん 2 つみ 2 2 2 つん 2 っ乙 2 ) ( 0 っっ ( 0 3 3 ( 0 ( 0 っ 4 4 4 ・ 4 ・ 4- 4- 4 4 4 return shader ; * 頂点シェーダとフラグメントシェーダをリンクさせる public static int IinkShader (int vertexShader , int fragmentShader) { final int program = g1CreateProgram() ; g1AttachShader (program, vertexShader) ; g1AttachShader (program, fragmentShader) ; g1LinkProgram(program) ; / / リンクエラーをチェックする int ロ 1inkSuccess = new int ロ { 0 } ; g1GetProgramiv (program , GL-LINK-STATUS , 1inkSuccess , 0 ) ; if (1inkSuccess [ 0 ] = GL—FALSE) { throw new RuntimeException (g1GetProgramInf0Log (program) ) ; / / delete g1De1eteShader (vertexShader) ; g1De1eteShader (fragmentShader) ; return program; import を工夫してコーディングをしやすくする このサンプルコードを見て気づいたかもしれませんが、今回のサンプルでは OpenGL ES 2.0 コマンドの呼び出しから " GLES20. " の部分が省略されていま す。これは Java の機能で、次のように記述することで static メソッドや static 変数へのアクセスを容易に行えます ( リスト 6.9 、リスト 6.10 、リスト 6.11) 。 リスト 6.9 : GLES20 クラス内の全 static メソッドとフィールドにアクセスする 136
6.4 プリミテイプの描画を行う Math. random ( ) 6.4 プリミテイプの描画を行う OpenGLES2.0 は、「プログラマプルバイプライン」という仕組みを導人して います。これはプログラマが描画の仕組みを「プログラマプル」に、つまりプロ グラムによって柔軟に書き換えが行えるということです。ですがそれと同時に プログラマに対してその「パイプラインを構築する」という義務を課しています。 「やれること」が増えた代わりに、「やらなければいけないこと」もまた増えた わけです。 HeIIo WorId のプログラムから多くの変更がありますが、ひとつひとつはあま 1 : = 0 ; リスト 6.7 : Chapter01_02. java サンプルコードは次のとおりです ( リスト 6.7 ) 。 6.4.1 演習 1 : 三角形を描画する り大きくありません。 2 : 3 : 4 : 5 : 6 : 7 : 8 : 9 : 10 : 11 : 12 : 13 : 14 : 15 : 16 : 17 : 18 : 19 : 20 : 21 : import static android. opengl. GLES20. * ; public class Chapter01-02 extends Chapter01—01 { * ポリゴン色 protected int attr—pos; * attr—pos protected int program * プログラムオプジェクト 133 protected int unif—color; [ 1 ] ここから [ 1 ] ここまで [ 2 ] ここから [ 2 ] ここまで
6.5 VRAM の利用 に int 型の変数によって " ID " が管理されています ( リスト 6.22 ) 。 リスト 6.22 : テクスチャオプジェクトは int 型変数で管理される * テクスチャオプジェクト protected int texture; テクスチャの読み込み部分は団同です。 Android では画像を示すクラスと して Bitmap クラスがありますが、 Bitmap クラスだけではテクスチャとして使 用することが出来ません。 Bitmap クラスからテクスチャオプジェクトヘアップ ロードを行う必要があります。 まず、テクスチャオプジェクトの生成です ( リスト 6.23 ) 。 リスト 6.23 : テクスチャオプジェクト生成 int ロ textureld = { 0 } ; g1GenTextures(), textureld, 0 ) ; textureld [ 0 ] ; this . texture テクスチャオプジェクトの生成は glGenTextures コマンドで行います。この コマンドは第 1 引数に「何枚のテクスチャを確保するか」を指定し、第 2 引数に は戻り値の格納先となる配列を指定します。最後に、第 3 引数で「配列のどの index から使用するか」を指定します。特別な理由がない限り、第 3 引数は常に 0 で問題ありません。 Android SDK に組み込まれた OpenGL ES のコマンドは、多くの場合この 「配列のどの index から使用するか」を指定することになります。これは Java 言 語がポインタ ( メモリ ) を直接扱えないための救済措置ともいえますが、本書で は特別なことをしないため、すべて " 0 " になります。 サンプルでは 1 枚のテクスチャを textureld 配列の index() 移行に格納するた め、 gIGenTextures 内部では "textureldl()l = テクスチャオプジェクトの ID" の ような処理が行われます。 textureld は一時変数であるため、 this. texture に対して返却値を保存してテ クスチャオプジェクトの生成処理は完了です。 151
第 5 章 BIuetooth 通信 ます。 アプリケーションから Bluet 。。 th ヘルス機器への接続と状態変化通知を受け super. onHea1thAppConfigurationStatusChange (conf ig , status) ; B1uetoothHea1thAppConfiguration config, int status) { public void onHea1thAppConfigurationStatusChange ( @Override class MyB1uetoothHea1thCa11back extends B1uet00thHea1thCa11back { private B1uetoothDevice mB1uetoothDevice ; private int mChanne11d; private B1uetoothHeaIthAppConfiguration mHea1thConf ig ; リスト 5.12 : luetooth ヘルス機器への接続と状態変化通知の受信のサンプルコード 取るまでのコード例を次に示します ( リスト 5.12 ) 。 122 mB1uet00thHea1th. unregisterAppConfiguration (mHea1thConfig) ; / / アプリケーションコンフィギュレーションを登録解除する private void unregister() { B1uet00thHea1th. SINK—ROLE , mCa11back) ; mB1uet00thHea1th. registerSinkAppConfiguration ( "HEALTH-DEVICES" / / ヘルス受信機器として機能するアプリケーションコンフィギュレーションを登録する MyB1uet00thHea1thCa11back mCa11back = new MyB1uet00thHea1thCa11back ( ) ; private void register() { mB1uetoothDevice = device ; / / 接続時に使用する / / B1uetoothDevice オプジェクトを保持しておく mChanne11d = channelld ; / / この ID は切断するときに使用する / / チャンネルに関連づいた ID を保持しておく if (newState B1uet00thHea1th. STATE-CHANNEL-CONNECTED) { device, prevState, newState, fd, channelld) ; super. onHea1thChanne1StateChange (config , Parce1Fi1eDescriptor fd, int channelld) { B1uetoothDevice device, int prevState, int newState, B1uetoothHea1thAppConfiguration config , public void onHea1thChanne1StateChange ( @Override mHea1thConfig = config ; / / 登録が成功したら通信に必要なアプリケーションコンフィギュレーションを保持
第 6 章 Andorid でのグラフィック処理 2 ( 0 4- L.n ( 0 【ー 8 9 0 1 2 3 4 5 ^ 0 っー 8 0 一 1 2 3 4 5 「′ 8 0 1 つん 3 4- ロ ) ( 0 っ′ 8 0 -1 つんっ ) 4- 5 6 7 8 9 0 -1 っ乙っ ) 4- 5 冖′ 8 つみつ乙 CN つんつんつる 2 2 っ 3 っっっ 3 っっ ) ) ( 0 4 4 4 4 4- 4 4- ・ 4 4 ・に ) 5 ロ ) 5 5 LO LO 5 5 「 0 ( 0 c.D c-D CD c.D ( 0 6 6 6 っーっー「′っー「ー 7 っーーー * surface が生成されたタイミングの処理 @Override public void onSurfaceCreated(GLIO gl, EGLConfig config) { [ 3 ] ここから f inal String vertexShaderSource "attribute mediump vec4 attr—pos ; ”十 "void main() { 十 g1—Position = attr—pos; 十 f inal String fragmentShaderSource "uniform lowp vec4 unif-color; ” + "void main() { 十 g1-FragC010r = unif-color; ” + [ 3 ] ここまで [ 4 ] ここから f inal int vertexShader ES20Uti1. compi1eShader (GL-VERTEX-SHADER, vertexShaderSource) ; f inal int fragmentShader ES20Uti1. compi1eShader (GL-FRAGMENT-SHADER, fragmentShaderSource) ; [ 4 ] ここまで [ 5 ] ここから this . program ES20Uti1.1inkShader (vertexShader , fragmentShader) ; [ 5 ] ここまで [ 6 ] ここから / / location を取得する attr-pos = glGetAttribLocation(program, "attr—pos") ; assert attr—pos > = 0 ; unif-color = g1GetUniformLocation(program, "unif—color") ; assert unif—color > = 0 ; [ 6 ] ここまで [ 7 ] ここから [ 7 ] ここまで g1UseProgram(program) ; [ 8 ] ここから @Override public void onSurfaceChanged(GLIO gl, int width, int height) { g1Viewport ( 0 , 0 , width, height) ; [ 8 ] ここまで 134
6.4 プリミテイプの描画を行う 79 : 80 : 81 : 82 : 83 : 84 : 85 : 86 : 87 : 88 : 89 : 90 : 91 : 92 : 93 : 94 : 95 : 96 : 97 : 98 : 99 : 100 : 101 : 102 : 103 : 104 : 105 : 106 : 107 : 108 : 109 : 110 : 111 : g1DrawArrays (GL-TRIANGLES , 0 , 3 ) ; 112 : 113 : 114 : 115 : 116 : @Override public void onDrawFrame(GLIO (l) { g1C1earC010r(). Of, 1 . 0f , 1 .0f , 1 . 0f ) ; g1C1ear (GLIO . GL—COLOR—BUFFER—BIT) ; / / ポリゴン色をアップロードする / / 色は RGBA でアップロードする g1Uniform4f (unif-color, 1 . Of , 1 . Of ) ; 0 . 0f , 0 . 0f , / / attr-pos を有効にする g1Enab1eVertexAttribArray (attr-pos) ; / / 画面中央へ描画する final float[] position / / v0 0 . Of , 1 . 0f , / / vl 1 .0f , ー 1 .0f , / / v2 ー 1. 0f } ; ー 1 .0f , [ 9 ] ここから [ 9 ] ここまで [ 10 ] ここから [ 10 ] ここまで [ 11 ] ここから g1VertexAttribPointer(attr-pos, 2 , GL-FLOAT, false, 0 , ES20Uti1. wrap(position)); [ 11 ] ここまで [ 12 ] ここから [ 12 ] ここまで リスト 6.8 : ES20Util クラス抜粋 * 頂点シェーダー / フラグメントシェーダーのコンバイルを行う public static int compi1eShader(int GL-XXXX-SHADER, String source) { final int shader = g1CreateShader (GL-XXXX—SHADER) ; g1ShaderSource(shader, source) ; g1Compi1eShader (shader) ; / / コンパイルエラーをチェックする 1 2 っ ) 4 ・ロ ) CD ー 8 0 1 1 宀イよ 135
第 6 章 Andorid でのグラフィック処理 * UV 座標 protected int attr—uv; * テクスチャ Uniform protected int unif—texture; ( 0 【ー 8 0 ) 0 1 2 3 4- 5 c.D 「′ - 8 0 1 2 3 4 ロ 0 ( 0 っー 8 9 0 1 っ 3 4 5 6 7 8 0 ) 0 1 っ乙 ( 0 4- 5 ( 0 7 8 0 1 つん ) 4 ・ロ ) ( 0 マー 8 0 ) 0 1 2 1 1 1 1 -1 一 1 -1 イよ・ 1 1 っ乙 2 2 2 2 2 2 っ乙つんつんっっ ) っ 3 っ ) 3 3 3 っ ") ( 0 4 4 ・ 4- 4 ・ 4- 4 4 4 4 4 5 ロ 0 に ) 5 5 ロ 0 5 5 5 5 6 ( 0 ( 0 [ 1 ] ここまで [ 2 ] ここから * テクスチャオプジェクト protected int texture; @Override public void onSurfaceCreated(GLIO gl, EGLConfig config) { [ 3 ] ここから f inal String vertexShaderSource t'attribute mediump vec4 attr_pos ; ”十 "attribute mediump vec2 attr_uv; " 十 mediump vec2 vary_uv ; 十 ” void main() { ” + g1—Position = attr_pos; ”十 vary_uv = attr_uv; ”十 [ 2 ] ここまで f inal String fragmentShaderSource "uniform samp1er2D unif-texture; ” + mediump vec2 vary—uv ; " 十 "void main() { " + g1—FragC010r = texture2D(unif-texture, vary-uv) ; [ 3 ] ここまで / / コンバイルとリンクを行う this . program ES20Uti1. compi1eAndLinkShader (vertexShaderSource , fragmentShaderSource) ; / / location を取り出す attr—pos = g1GetAttribLocation(program, "attr-pos") ; assert attr—pos > = 0 ; attr—uv = g1GetAttribLocation(program, "attr-uv") ; assert attr_uv > = 0 ; unif—texture = gIGetUniformLocation (program, "unif—texture" ) ; assert unif—texture > = 0 ; / / テクスチャを読み込む 十 148