2013年9月25日水曜日

Volleyを使ってみる(ベーシック認証編)

Volleyを使ってAPIとの連動をさせようとしたらベーシック認証が必要だったのでその際のメモになります(ΦωΦ)フフフ…

Volleyでベーシック認証を適用するやり方としては次の2つ?があるみたいです。
・newRequestQueueの第2引数でネットワークの設定を行う。(NetworkImageViewを利用する場合にはこちらだけ?)
・getHeadersをオーバーライドする方法。

今回は、getHeadersをオーバーライドする方法で行いたいと思います!(`・ω・´)シャキーン
処理は主に以前の「Volleyを使ってみる(StringRequest編) 」をそのまま利用して、
ベーシック認証の処理だけを追加している感じになっています。

Base64エンコードにはこちらのサイトのものをそのまま拝借させてもらいました。ありがとうございますъ(゚Д゚)グッジョブ!!
twitter APIに接続するためのjavaコード

ベーシック認証でエラーになっている場合には、次のようなエラーが表示されていると思います。
09-25 09:54:01.166: E/Volley(1556): [15] BasicNetwork.performRequest: Unexpected response code 401 for リクエストURL

■AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.volleyexample4"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="8" />

    <!-- インターネットへのアクセスを許可 -->
    <uses-permission android:name="android.permission.INTERNET"/>
    
    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.volleyexample4.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
■activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >
</RelativeLayout>

■MainActivity.java
package com.example.volleyexample4;

import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;

import com.android.volley.AuthFailureError;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;

import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.widget.Toast;

public class MainActivity extends Activity {

 //ログ出力時のタグ名
 private static final String TAG_LOG = "Log";
 //Volleyでリクエスト時に設定するタグ名。キャンセル時に利用する。
 private static final Object TAG_REQUEST_QUEUE = new Object();
 //リクエスト先
 private static final String REQUEST_URL_RESEPONSE_STRING = "リクエスト先";
 //RequestQueueのインスタンス用
 private RequestQueue mRequestQueue;
 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  
  //RequestQueueのインスタンス用を取得
  mRequestQueue = Volley.newRequestQueue(getApplicationContext());
  
 }

 /*
  * onCreateの後に呼び出される。
  */
 @Override
 public void onStart(){
  super.onStart();
  //HTTPリクエストを行う
  requestString();
 }
 
 /*
  * アプリが見えなくなったときに呼び出される。
  * (他のアプリを立ち上げたりした時など)
  */
 @Override
 public void onStop(){
  super.onStop();
  mRequestQueue.cancelAll(TAG_REQUEST_QUEUE);
 }
 /*
  * 
  */
 private void requestString(){
  
  //リクエスト&レスポンス情報の設定
  //StringRequestの場合
  StringRequest request = new StringRequest(
   //送信方法 GET/POST
   Request.Method.GET, 
   //送信先
   REQUEST_URL_RESEPONSE_STRING,
   //レスポンス成功時のリスナー
   new Response.Listener<String>() {
    @Override 
    public void onResponse(String response) {
     
     //レスポンス受け取り時の処理
     if (response == null){
      //空の場合
      return;
     }
     //
     Toast.makeText(getApplicationContext(), response, Toast.LENGTH_LONG).show();
    }
   },
   //レスポンス失敗時のリスナー
   new Response.ErrorListener() {
    @Override 
    public void onErrorResponse(VolleyError error) {
     //エラー時の処理
     Toast.makeText(getApplicationContext(), "onErrorResponse", Toast.LENGTH_LONG).show();

    }
   }
  ){
  @Override
   public Map<String, String> getHeaders() throws AuthFailureError {
    Map<String, String> headers = super.getHeaders();
    // Add BASIC AUTH HEADER
    Map<String, String> newHeaders = new HashMap<String, String>();
    newHeaders.putAll(headers);
    String password = createAuthorization("アカウントID", "アカウントパスワード");
    newHeaders.put("Authorization", "Basic "+password+"======");
    return newHeaders;
   }
  };

  //タグを設定する
  request.setTag(TAG_REQUEST_QUEUE);
  
  //リクエスト&レスポンス情報の設定を追加
  mRequestQueue.add(request);

  //リクエスト開始
  mRequestQueue.start();  
 }

 /**
  * BASIC認証用のヘッダ文字列を作成する。
  * @param in_username ユーザ名
  * @param in_password パスワード
  * @return BASIC認証用のヘッダ文字列
  */
 public static String createAuthorization( String in_username, String in_password ) {

  String string = in_username + ":" + in_password;

  byte[] tmp = getAsciiBytes( string );

  String encoded = base64Encode( tmp );

  return encoded;
 }

 /**
  * 文字列をASCIIのバイト配列に変換します。
  * @param text 対象の文字列
  * @return 変換後のバイト配列
  */
 private static byte[] getAsciiBytes( String text ) {

  byte[] ascii;
  try {
   ascii = text.getBytes( "ASCII" );
  } catch ( UnsupportedEncodingException e ) {
   throw new RuntimeException( e );
  }

  return ascii;
 }

 /**
  * バイト配列をBASE64エンコードします。
  * @param ascii 対象のバイト配列
  * @return エンコード後の文字列
  */
 private static String base64Encode( byte[] ascii ) {

  // ASCIIをビットパターンに変換します。
  StringBuffer bitPattern = new StringBuffer();
  for ( int i = 0; i < ascii.length; ++i ) {
   int i_tmp = ascii[i] & 0xff;
   String bin_tmp = Integer.toBinaryString( i_tmp );
   while ( bin_tmp.length() < 8 ) {
    bin_tmp = "0" + bin_tmp;
   }
   bitPattern.append( bin_tmp );
  }

  // ビットパターンのビット数が6の倍数にするため、末尾に0を追加します。
  while ( bitPattern.length() % 6 != 0 ) {
   bitPattern.append( "0" );
  }

  // 変換表
  final String[] table = {
    "A", "B", "C", "D", "E", "F", "G", "H",
    "I", "J", "K", "L", "M", "N", "O", "P",
    "Q", "R", "S", "T", "U", "V", "W", "X",
    "Y", "Z", "a", "b", "c", "d", "e", "f",
    "g", "h", "i", "j", "k", "l", "m", "n",
    "o", "p", "q", "r", "s", "t", "u", "v",
    "w", "x", "y", "z", "0", "1", "2", "3",
    "4", "5", "6", "7", "8", "9", "+", "/"
  };

  // 変換表を利用して、ビットパターンを4ビットずつ文字に変換します。
  StringBuffer encoded = new StringBuffer();
  for ( int i = 0; i < bitPattern.length(); i += 6 ) {
   String tmp = bitPattern.substring( i, i + 6 );
   int index = Integer.parseInt( tmp, 2 );
   encoded.append( table[index] );
  }

  // 変換後の文字数を4の倍数にするため、末尾に=を追加します。
  while ( encoded.length() % 4 != 0 ) {
   encoded.append( "=" );
  }

  return encoded.toString();
 }
}
以上です(`・ω・´)ゞビシッ!!

参考URL

2013年9月20日金曜日

GridViewを使ってみる(枠線をつける)

今回はGridViewに枠線をつけたいと思います

枠線をつけるために、Viewのbackground属性を利用すると出来るそうですφ(`д´)メモメモ...
まずは、background属性に枠デザイン用のxmlを用意します。


Package Explorerでプロジェクトのresディレクトリを右クリックして、
New > Folder を選択する。


次に、resディレクトリを選択して、
Folder nameに「drawble」と入力して「Finishi」を押す


先ほど作ったディレクトリにxmlファイルを作成します。
先ほど作ったディレクトリを右クリックして、
New > File を選択する。


File nameに「border.xml」と入力して「Finishi」を押す


<?xml version="1.0" encoding="utf-8"?>
<selector
  xmlns:android="http://schemas.android.com/apk/res/android">

    <!-- ボタンが押されたときの定義 -->
    <item android:state_pressed="true">
        <shape
            xmlns:android="http://schemas.android.com/apk/res/android"
            android:shape="rectangle" >

            <!-- 色 -->
            <solid android:color="#000000" />
            <!-- 枠線の形状 -->
            <stroke
                android:width="1px"
                android:color="#CCCCCC" />
            <!-- パディング -->
            <padding
                android:bottom="2px"
                android:left="2px"
                android:right="2px"
                android:top="2px" />
            <!-- 角の半径を -->
            <corners android:radius="2px" />
        </shape>
    </item>
    <!-- ボタンが押されていないときの定義 -->
    <item android:state_pressed="false">
        <shape
            xmlns:android="http://schemas.android.com/apk/res/android"
            android:shape="rectangle" >

            <!-- 色 -->
            <solid android:color="#FFFFFF" />
            <!-- 枠線の形状 -->
            <stroke
                android:width="1px"
                android:color="#CCCCCC" />
            <!-- パディング -->
            <padding
                android:bottom="2px"
                android:left="2px"
                android:right="2px"
                android:top="2px" />
            <!-- 角の半径を -->
            <corners android:radius="2px" />
        </shape>
    </item>

</selector>

次は、GridViewのレイアウトを作成します。 resディレクトリを右クリックして、 New > Android XML file を選択する。

New Android XML fileが表示されたら、
Resource Typeに「Layout」を選択して、
Fileにはgridと入力します。

RootElementには、GridViewを選択して、「Finish」を押してxmlを作成します。

これで、枠の準備は完了になります。
次はGridViewのレイアウトXMLを用意します
(layoutディレクトリにgrid.xmlが作成されます。)


■grid.xml
先ほど作成したgrid.xmlの中身を下記のように変更します。
(background属性に@drawable/borderを指定する)
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="50dp"
    android:background="@drawable/border"
    android:gravity="center" />
■AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.gridview4"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="8" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.gridview4.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
■activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <GridView
        android:id="@+id/gridView1"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:numColumns="auto_fit" />

</LinearLayout>


■MainActivity.java
package com.example.gridview4;

import java.util.ArrayList;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.app.Activity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.GridView;

public class MainActivity extends Activity {
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // データの初期化
        ArrayList<String> list = new ArrayList<String>();
        
        int length = 100;
        for(int i = 0; i < length; i++){
         list.add(String.valueOf(i));
        }
        
        // アダプターの作成
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.grid, list);
        
        // GridViewの取得
        GridView gridView = (GridView) findViewById(R.id.gridView1);
        
        // データをGridViewへ設定
        gridView.setAdapter(adapter);
    }
    
 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
  // Inflate the menu; this adds items to the action bar if it is present.
  getMenuInflater().inflate(R.menu.main, menu);
  return true;
 }
 
}


実行結果は次のようになります。
クリックした箇所が黒色に変わると思います(`・ω・´)シャキーン

以上です(`・ω・´)ゞビシッ!!

参考URL

GridView(リストの最後まで表示されたら追加する)

前回の「GridViewを使ってみる(SDカードの画像表示) 」で、
SDカードに保存されている画像が大量に有った場合に、
画像が表示がされるまでにだいぶ待たされる事になってしまいます。

そこで、今回はGridViewのデータを動的に追加できる方法を調べてみました!
ついでにGridViewのクリックイベントもつけてあります(ΦωΦ)フフフ…

■AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.gridview3"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="8" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.gridview3.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

■activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#000000">
    <GridView android:id="@+id/gridView1"
     android:layout_width="fill_parent"
     android:layout_height="fill_parent"
     android:columnWidth="90dp"
     android:numColumns="auto_fit"
     android:verticalSpacing="10dp"
     android:horizontalSpacing="10dp"
     android:stretchMode="columnWidth"
     android:gravity="center"
    />
</LinearLayout>

■MainActivity.java

作成中にはまった点として、スクロールの状態を検知している箇所で、
末尾まで表示したら追加する処理を行う場合に、
今、表示されているデータの末尾の内容が全体の末尾まで読み込まれているか?という判定用に、
GridViewに登録されているデータ数のトータル数を見ているのですが、
そこの値がGridViewの初期化のタイミングでは0が入ってしまっている?っぽくてはまりました。

単純に、現在表示している末尾だけの比較になると、初期化のタイミングでおかしくなってしまうので、
GridViewがスクロールをしている状態の時だけその判定を入れる事で回避してあります。
package com.example.gridview3;

import java.util.ArrayList;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.AbsListView.LayoutParams;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.ArrayAdapter;
import android.widget.GridView;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.Toast;

public class MainActivity extends Activity {

 // デフォルトで作成するリストのデータ数
 private static final int LIST_COUNT_MAX = 100;
 // GridViewを追加する際のデータ数
 private static final int LIST_COUNT_ADD_MAX = 40;

 // GirdView
 private GridView mGridView;
 private ArrayList<String> mList;
 private ArrayAdapter<String> mArrayAdapter;

 // スクロール中か
 private static Boolean sScrolling = false;

 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);

  // データの初期化
  mList = new ArrayList<String>();
  int length = LIST_COUNT_MAX;
  for (int i = 0; i < length; i++) {
   mList.add(String.valueOf(i));
  }

  // アダプターの作成
  mArrayAdapter = new ArrayAdapter<String>(getApplicationContext(),
    android.R.layout.simple_list_item_1, mList);

  // GridViewの取得
  mGridView = (GridView) findViewById(R.id.gridView1);

  // データをGridViewへ設定
  mGridView.setAdapter(mArrayAdapter);

  // スクロールのリスナーを設定
  mGridView.setOnScrollListener(new GridViewOnScrollListener());

  // クリックのリスナーを設定
  mGridView.setOnItemClickListener(new OnItemClickListener() {
   @Override
   public void onItemClick(AdapterView<?> parent, View v,
     int position, long id) {
    Toast.makeText(getApplicationContext(),
      "onItemClick : " + position, Toast.LENGTH_SHORT).show();
   }
  });

  // 長押しのリスナーを設定
  mGridView.setOnItemLongClickListener(new OnItemLongClickListener() {

   @Override
   public boolean onItemLongClick(AdapterView<?> parent, View v,
     int position, long id) {
    Toast.makeText(getApplicationContext(),
      "onItemLongClick : " + position, Toast.LENGTH_SHORT)
      .show();
    // 長押しのイベント発生後にクリックイベントを発生させない為にfalseで返す
    return false;
   }

  });

 }

 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
  // Inflate the menu; this adds items to the action bar if it is present.
  getMenuInflater().inflate(R.menu.main, menu);
  return true;
 }

 /*
  * スクローラーの状態検知
  */
 public class GridViewOnScrollListener implements OnScrollListener {

  /*
   * ステータスが変わった時
   * 
   * @see
   * android.widget.AbsListView.OnScrollListener#onScrollStateChanged(
   * android.widget.AbsListView, int)
   */
  @Override
  public void onScrollStateChanged(AbsListView paramAbsListView,
    int scrollState) {
   switch (scrollState) {

   // スクロール停止
   case OnScrollListener.SCROLL_STATE_IDLE:

    // decode処理をqueueに登録して開始する記述
    sScrolling = false;

    // アダプターにデータ変更の通知
    mArrayAdapter.notifyDataSetChanged();
    // GridViewの再描画
    mGridView.invalidateViews();

    break;

   // スクロール
   case OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:
    // decodeのqueueをキャンセルする処理を記述
    sScrolling = true;
    break;

   // フリック
   case OnScrollListener.SCROLL_STATE_FLING:
    // decodeのqueueをキャンセルする処理を記述
    sScrolling = true;
    break;

   default:
    break;
   }
  }

  /*
   * スクロール中
   * 
   * @see
   * android.widget.AbsListView.OnScrollListener#onScroll(android.widget
   * .AbsListView, int, int, int)
   */
  @Override
  public void onScroll(AbsListView view, int firstVisibleItem,
    int visibleItemCount, int totalItemCount) {

   // 現在表示されているリストの末尾番号
   int displayCount = firstVisibleItem + visibleItemCount;

   /*
    * 
    * 初期でdisplayCountに数値が入ってるのに、totalItemCountが0の場合があるためスクロール中のみ判定するようにする
    * 。
    */
   if (displayCount < totalItemCount || !sScrolling) {
    return;
   }

   // リストの最大値を取得する
   int start = mList.size();
   // リストの最大値+追加する数
   int length = start + LIST_COUNT_ADD_MAX;

   // リストにデータ追加
   for (int i = start; i < length; i++) {
    mList.add(String.valueOf(i));
   }

   // アダプターにリストデータ変更の通知
   mArrayAdapter.notifyDataSetChanged();

   // GridViewの再描画
   mGridView.invalidateViews();

  }

 }

}
実行結果は次のようになります。

以上です(`・ω・´)ゞビシッ!!

参考URL

2013年9月18日水曜日

GridViewを使ってみる(SDカードの画像表示)

前回の「GridViewを使ってみる(Adapterのカスタマイズ) 」では、
AdapterをカスタマイズしたCustomAdapterを利用して文字列をセットして扱いました。

今回は、文字列ではなくBitmapを扱い、画像を表示させたいと思います( ̄ー ̄)ニヤリ
画像はAVDのSDカードに画像を追加してその画像を利用したいと思います。

AVDのSDカードに画像を追加する方法はこちらに記載してあります
AVDのSDカードにデータを登録する

■AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.gridview2"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="8" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.gridview2.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>


■activity_main.xml

    
    


■grid.xml
GridView用のレイアウトファイルになります。
<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

</ImageView>

■MainActivity.java

BitmapFactory.Optionsについて次の記事が参考になりました。
Android 大きい画像を効果的に読み込む
デコーダーに画像をサブサンプルさせる(縮小して読み込む、低解像度で読み込む)には、
BitmapFactory.Options の inSampleSize パラメータに 1 より大きい整数値を指定します。
(原文ではなぜか true をセットと書いてありますが間違いです)

inSampleSize に 1 より大きい整数値を指定すると、縦横それぞれが約 1 / inSampleSize になって読み込まれます。
例えば

元 : 2048 x 1536
|
inSampleSize = 4

Bitmap : 512 x 384

縦横がそれぞれ 1 / inSampleSize になるので、サイズは 1 / inSampleSize^2 になります。

表示するサイズから inSampleSize を求めるにはこうします。

には、BitmapFactory.Options の inSampleSize パラメータに 1 より大きい整数値を指定します。
package com.example.gridview2;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Environment;
import android.widget.GridView;

public class MainActivity extends Activity {

 // ディレクトリ格納用
 private List<String> directory = new ArrayList<String>(); 

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);

  // SDカードから画像を取り出す。
  ArrayList<Bitmap> list = getImages();
  // カスタムアダプターの生成
  CustomAdapter adapter = new CustomAdapter(getApplicationContext(),
    R.layout.grid, list);
  // GridViewを取得する
  GridView gridView = (GridView) findViewById(R.id.gridView1);
  // GridViewにAdapterを設定する
  gridView.setAdapter(adapter);

 }

 /*
  * SDカードから画像を取り出す。
  */
 private ArrayList<Bitmap> getImages() {

  //
  ArrayList<Bitmap> list = new ArrayList<Bitmap>();

  // 外部ストレージ(SDカード)のデレクトリPATHを取得
  File file = Environment.getExternalStorageDirectory();

  // 参照ベースディレクトリ
  directory.add(file.getPath());

  // 指定ディレクトリ内のファイル検索
  int lengthSubDirectory = 0;
  int lengthDirectory = directory.size();
  String filePathImage = "";
  for (int i = 0; i < lengthDirectory; i++) {

   // 指定されたディレクトリ情報を取得する
   File directorySub = new File((String) directory.get(i));

   // ファイル/ディレクトリ一覧を取得する
   String[] subFileName = directorySub.list();

   // ファイル/ディレクトリが無かった場合
   if (subFileName == null) {
    continue;
   }

   // 件数を取得する
   lengthSubDirectory = subFileName.length;
   for (int j = 0; j < lengthSubDirectory; j++) {

    // ディレクトリの中身のファイル(ディレクトリも含まれる)を取得する
    File subFile = new File(directorySub.getPath() + "/"
      + subFileName[j]);

    if (subFile.isDirectory()) {

     // サブディレクトリならループ末尾に追加して検索する
     directory.add(directorySub.getPath() + "/"
       + subFileName[j]);

    } else if (isImage(subFile)) {

     // 画像ファイルの場合には表示対象に追加

     // ビットマップ変換
     filePathImage = directorySub.getPath() + "/"
       + subFileName[j];

     File fileImage = new File(filePathImage);
     // オプション設定
     BitmapFactory.Options bmpOp = new BitmapFactory.Options();
     // 低解像度で読み込む。値が大きいほど低画像(サイズ、解像度が低く)になる。
     bmpOp.inSampleSize = 5;
     //
     list.add(BitmapFactory.decodeFile(fileImage.getPath(),
       bmpOp));

    }

   }
  }
  //
  return list;
 }

 /*
  * 画像の拡張子かチェックする
  * 
  * @return Boolean
  */
 protected boolean isImage(File checkedFile) {

  // チェック結果
  boolean checkResultFlag = false;

  // 画像拡張子リスト
  final String[] IMAGE_EXTENSION_ARRAY = { ".bmp", ".gif", ".jpg",
    ".jpeg", ".png" };

  // nullチェック
  if (checkedFile == null) {
   return checkResultFlag;
  }

  // isFileチェック
  if (!checkedFile.isFile()) {
   return checkResultFlag;
  }

  // ファイル名取得チェック
  if (checkedFile.getName() == null
    || checkedFile.getName().length() == 0) {
   return checkResultFlag;
  }

  // ファイルの末尾が画像拡張子リストの中にあるかチェック
  for (int i = 0; i < IMAGE_EXTENSION_ARRAY.length; i++) {
   if (checkedFile.getName().endsWith(
     IMAGE_EXTENSION_ARRAY[i].toLowerCase())
     || checkedFile.getName().endsWith(
       IMAGE_EXTENSION_ARRAY[i].toUpperCase())) {
    checkResultFlag = true;
    break;
   }
  }

  return checkResultFlag;
 }

}

■CustomAdapter.java
package com.example.gridview2;

import java.util.ArrayList;

import android.content.Context;
import android.graphics.Bitmap;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;

public class CustomAdapter extends ArrayAdapter<Bitmap> {

 //
 private Context context = null;
 // アダプターに渡したリスト
 private ArrayList<Bitmap> data = null;
 //
 private int resource = 0;

 public CustomAdapter(Context context, int resource, ArrayList<Bitmap> data) {
  super(context, resource, data);
  //
  this.context = context;
  this.resource = resource;
  this.data = data;
 }

 /*
  * 指定された項目を識別するためのIDを取得する
  */
 @Override
 public long getItemId(int position) {
  return position;
 }

 /*
  * 指定された項目を取得する
  */
 @Override
 public Bitmap getItem(int position) {
  return data.get(position);
 }

 /*
  * データの項目数を取得する
  */
 @Override
 public int getCount() {
  return data.size();
 }

 /*
  * 1アイテム分のビューを取得.
  * @param Integer
  *   アイテムのポジション番号
  * @param View
  *    可能な場合不要なビューを再利用する。膨大な量の情報を出力する場合にオブジェクトを可能な限り再利用する。
  *    nullの場合には再利用できるオブジェクトがないためオブジェクトを生成する。
  * 
  * @param ViewGroup
  *    選択されたAdapterのビューとなる。GridViewになる。
  * 
  */
 @Override
 public View getView(int position, View convertView, ViewGroup parent) {

  // Viewが無かった場合
  if (convertView == null) {
   // コンストラクタで渡されたレイアウトのリソースIDからViewを取得するため、LayoutInflaterを取得する
   LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
   // レイアウトファイルをViewに変換する(レイアウトに記述されているルートのViewになる)
   convertView = inflater.inflate(resource, null);
  }
  // 取得したビューのキャスト
  ImageView view = (ImageView) convertView;
  // ImageViewに画像を設定する
  view.setImageBitmap(getItem(position));

  return view;
 }

}
実行結果は次のようになります。

以上です(`・ω・´)ゞビシッ!!

参考URL

jQuery Migrate

jQueryもメジャーバージョンアップ2.0β版が出てきて
いよいよそれに合わせて過去の産物も準拠しなければならない時が来ました。

そういえば、jQuery1.9で動かなくなるケースもありました。
当時は、jQuery1.7を読み込んで放置しちゃいましたけど。

jQuery1.9では利用されなくなった機能、重複したAPIが
整理されちゃったりしているらしいです。

そこで、 登場するのが『jQuery Migrate』です。

これを読み込むと、お手軽にjQuery1.9に対応していただけるみたいです。

参考URL

2013年9月13日金曜日

GridViewを使ってみる(Adapterのカスタマイズ)

前回の「GridViewを使ってみる 」では、
AdapterにArrayAdapterを利用して文字列をセットして扱いました。

今回は、AdapterをカスタマイズできるようにArrayAdapterクラスを継承させて
Adapterを作成したものを使ってみたいと思います。

■AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.gridview2"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="8" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.gridview2.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>


■activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#000000">
    <GridView android:id="@+id/gridView1"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:numColumns="4"
        android:verticalSpacing="10dp"
        android:horizontalSpacing="10dp">
    </GridView>
</LinearLayout>

■MainActivity.java
package com.example.gridview2;

import java.util.ArrayList;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.widget.GridView;

public class MainActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        //GridViewに表示するデータを作成する
        ArrayList<String> list = new ArrayList<String>();
 
        int length = 100;
        for(int i = 0; i < length; i++){
         list.add(String.valueOf(i));
        }
        
        //カスタムアダプターを生成
        CustomAdapter adapter = new CustomAdapter(getApplicationContext(), R.layout.grid, list);
 
        //GridViewを取得する
        GridView gridView = (GridView) findViewById(R.id.gridView1);
        
        //GridViewにカスタムアダプターを設定する
        gridView.setAdapter(adapter);
    }

 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
  // Inflate the menu; this adds items to the action bar if it is present.
  getMenuInflater().inflate(R.menu.main, menu);
  return true;
 }

}

■CustomAdapter.java

Adapterの作成する際の注意点として、
次の点に気をつけるようにした方が良いそうです。
Adapterの高速化
このgetViewメソッドは、新しいデータが表示されるタイミングで呼び出されます。
ListViewなら、スクロールして、画面外から新しいデータが表示されるタイミングです。
こういった性質上、スクロールの度に何度も何度も呼び出されるため、
getViewメソッドで無駄な処理があると、スクロールにひっかかりが出来るなど、
パフォーマンスに直結した悪影響を及ぼします。
package com.example.gridview2;

import java.util.ArrayList;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;

public class CustomAdapter extends ArrayAdapter<String> {

 //
 private Context context = null;
 // アダプターに渡したリスト
 private ArrayList<String> data = null;
 //
 private int resource = 0;

 public CustomAdapter(Context context, int resource, ArrayList<String> data) {
  super(context, resource, data);
  //
  this.context = context;
  this.resource = resource;
  this.data = data;
 }

 /*
  * 指定された項目を識別するためのIDを取得する
  * 
  * @see android.widget.ArrayAdapter#getItemId(int)
  */
 @Override
 public long getItemId(int position) {
  return position;
 }

 /*
  * 指定された項目を取得する
  * 
  * @see android.widget.ArrayAdapter#getItem(int)
  */
 @Override
 public String getItem(int position) {
  return data.get(position);
 }

 /*
  * データの項目数を取得する
  * 
  * @see android.widget.ArrayAdapter#getCount()
  */
 @Override
 public int getCount() {
  return data.size();
 }

 /*
  * 1アイテム分のビューを取得.
  * 
  * @param Integer ビューの何番目が必要になったか。
  * 
  * @param View
  * 可能な場合不要なビューを再利用する。膨大な量の情報を出力する場合にオブジェクトを可能な限り再利用する。nullの場合には再利用できるオブジェクトがないため
  * 、オブジェクトを生成する。
  * 
  * @param ViewGroup 選択されたAdapterのビューとなる。GridViewになる。
  * 
  * @see android.widget.ArrayAdapter#getView(int, android.view.View,
  * android.view.ViewGroup)
  */
 @Override
 public View getView(int position, View convertView, ViewGroup parent) {

  // Viewが無かった場合
  if (convertView == null) {
   // コンストラクタで渡されたレイアウトのリソースIDからViewを取得するため、LayoutInflaterを取得する
   LayoutInflater inflater = (LayoutInflater) getContext()
     .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
   // レイアウトファイルをViewに変換する(レイアウトに記述されているルートのViewになる)
   convertView = inflater.inflate(resource, null);
  }

  // 取得したビューのキャスト
  TextView view = (TextView) convertView;

  // 対象のアイテムを取得する
  String text = getItem(position);

  // TextViewに文字列を設定する
  view.setText(text);

  return view;
 }
}
実行結果は次のようになります。


以上です(`・ω・´)ゞビシッ!!

参考URL

android ListView 複数リスト 選択した値を取得する

使用するパッケージ
android.widget.ListView


1. [ xmlファイルを修正 ]パレットのCompositeからListViewを選択し配置する。
  android:choiceMode="multipleChoice"を追記する

2. 表示するデータを作成し、表示する。


  2-1.静的なリストの場合

   ・ strings.xml を修正しリストを作成する。

     追加[add]を押し[String Array]を選択する。
           [String Array]を選択したまま、右の名前[Name]を変更する。
     内容を追加する。
     [String Array]を選択したまま、追加[add]を押し、Itemを選択し完了[finish]を押す。
      先ほどと、同様右の名前に値をセットする。

   ・ リスト表示する        
           OutlineのListViewを選択し、PropertiesのListView直下のEntriesをクリックし用意した配列を選択する。




  2-2.動的なリストの場合(カスタマイズする際は別途記入)
   ・  Activityファイルを修正する( MainActivity.java )
   
          使用するパッケージ
          java.util.ArrayList
          android.widget.ArrayAdapter
          android.widget.AdapterView
          android.widget.Toast (表示用に使用しているだけ)
  public class MainActivity extends Activity{

    private ListView list;
   private ArrayAdapter<String> adapter;
    private ArrayList<String> data;

   public void onCreate(){
    super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_listview);

    //リストを動的に作成
    data = new ArrayList<String>();
       for( int i=0; i < 30; i++ ){
         
            String columns_name = "select_" + i;
          data.add( columns_name );

      //アダプターを用意する
//第一引数 コンテキスト(アクティビティ), 第二引数 リストの種類, 第三引数 リストデータ
      adapter = new ArrayAdapter<String>( MainActivity.this, android.R.layout.simple_list_item_multiple_choice, data  );
    
            ListView list = (ListView)findViewById( R.id.listView1 );
            
            //リストビューにアダプターをセット
      list.setAdapter( adapter );
      
      //リスト項目がクリックされたときの処理
      //何かしらのアクションでリスト項目を追加したい時は、adapter.add("new_item!");のようにアダプターに追加する
      list.setOnItemClickListener( new AdapterView.OnItemClickListener() {

        public void onItemClick( AdapterView<?> av, View view, int position, long id ){
   
          //一度でもチェックされた項目の配列を取得する
          //名前的にチェックしている項目の配列を取得してくれそうだけど、そうではない事に注意
                SparseBooleanArray checked = list.getCheckedItemPositions();
          StringBuilder sb = new StringBuilder();
          
          //★配列の個数分ループ
          for( int index = 0; index < checked.size(); index++ ){
            //valueAtでチェックされていればtrueが返ってくる
            if( checked.valueAt(index) ){
             int key = checked.keyAt(index);//チェックされている配列のキーを取得
             sb.append( data.get(key) + "," );//用意した配列から値を取得する
            }
                    }

                    Toast.makeText( MainActivity.this , sb.substring( 0, sb.length() -1  ) , Toast.LENGTH_SHORT ).show();
               }
           });
        }
    }

■以下に別の方法がありますが、OSのバージョンによってisCheckedの戻り値が変わるそうなので上記の方法をおススメします。
   for( int index = 0; index < list.getChildCount(); index++ ){
       CheckedTextView check = (CheckedTextView)list.getChildAt(index);
       if( check.isChecked() ){
//チェックされている時の処理
       }
   }

2013年9月12日木曜日

GridViewを使ってみる

今回はGridViewを使ってみたいと思います(`・ω・´)シャキーン

見た目がグリッド状になっているViewらしく、画像が多いアプリを作りたいとは思っているのでこれは使えるかも(・∀・)イイ!!

AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.gridview1"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="8" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.gridview1.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#000000">
    <GridView android:id="@+id/gridView1"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:numColumns="4"
        android:verticalSpacing="10dp"
        android:horizontalSpacing="10dp">
    </GridView>
</LinearLayout>
MainActivity.java

ArrayAdapterで指定しているandroid.R.layout.simple_list_item_1は、
あらかじめAndroid側で用意されているレイアウトリソース名。
Android標準で用意されているレイアウトについてはこちらにあるみたいです
R.layout

AdapterにはArrayAdapterを利用しています。
Adapterクラスは、データソースとビューのつなぎ役を果たすもので、
Viewで表示すべきデータはAdapterクラスを利用するようになります。

Adapterクラスが内部のデータの違いを吸収してくれるので、
View側は型の違いなどを意識せずに処理を行えるそうです。
package com.example.gridview1;

import java.util.ArrayList;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.widget.ArrayAdapter;
import android.widget.GridView;

public class MainActivity extends Activity {

 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);

  // GridViewに表示するデータを作成する
  ArrayList<String> list = new ArrayList<String>();

  int length = 100;
  for (int i = 0; i < length; i++) {
   list.add(String.valueOf(i));
  }

  // ArrayAdapterを生成する
  ArrayAdapter<String> adapter = new ArrayAdapter<String>(
    getApplicationContext(), android.R.layout.simple_list_item_1,
    list);

  // GridViewを取得する
  GridView gridView = (GridView) findViewById(R.id.gridView1);

  // GridViewにカスタムアダプターを設定する
  gridView.setAdapter(adapter);
 }

 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
  // Inflate the menu; this adds items to the action bar if it is present.
  getMenuInflater().inflate(R.menu.main, menu);
  return true;
 }

}

実行結果は次のようになります。

以上です(`・ω・´)ゞビシッ!!

参考URL

2013年9月11日水曜日

AVDのSDカードにデータを登録する

SDカードの情報を利用した処理を作ろうと思ったらなぜかエラーになってしまってたので、
ふと、AVDのSDカードにデータが入ってないのでは!?と思ったら案の定そうでした(´;ω;`)ウッ…

なので、SDカードにデータを追加する方法になります(`・ω・´)シャキーン

■手順1.AVDのSDカードを有効にする。
Window > Android Virtual Device ManagerでAVDの作成・編集画面を開き、
既にAVDがある場合には「Edit」で編集画面を開き、
新規で作成する場合に「New」を押してください。

開いたら基本的な情報を入力して、SDカード項目にも適当な値を入力してAVDを作成してください。
※AVD作成手順の詳細はこちらの記事に書いてあります。「Android開発環境を整える(AVDの作成)


AVDのSDカードの設定が終わったらAVDを起動します。
起動が完了したら、DDMSを開きます。




DDMSが開いたら右上の方にある「File Explorer」を押してAVDのディレクトリ構成を表示させます。

次に、「File Explorer」の一覧の中からmnt > sdcardを選択してから、
右上▽みたいなボタンを押すと「Pull File...」と「Push File...」が表示されますので、
AVDのSDカードに追加を行いたい場合には、「Push File...」を押してパソコンのディレクトリやファイルを選択します。
取り出したい場合には、「Pull File...」を押してパソコンのディレクトリやファイルを選択します。


以上で、AVDのSDカードデータを追加が行えます( ´∀`)bグッ!

もし、何らかしらエラーが出る場合には、コマンドプロンプトから手動で行う方法もあるそうです。
adbコマンドの形式は次のようになります。
#SDカードに追加の場合
adb push SDカードに追加するファイル名(パソコンにあるもの) SDカードの場所

#SDカードから取り出し
adb pull SDカードの場所 SDカードに追加するファイル名(パソコンにあるもの)
たとえば次のようにコマンドを実行すればデータが追加されます。
#1ファイルを追加する場合
C:\Users\ユーザー名>adb push C:\Temp\test.jpg /sdcard/
71 KB/s (1118821 bytes in 15.228s)

#ディレクトリの中身を追加する場合
C:\Users\ユーザー名>adb push C:\Temp /sdcard/
※adbコマンドのパスを通していない場合には上記のコマンドを実行する前に、
adbがインストールされているディレクトリまで移動してから実行してください(´;ω;`)ウッ…
以上です(`・ω・´)ゞビシッ!!

参考URL

2013年9月10日火曜日

Volleyを使ってみる(JsonArrayRequest、JsonObjectRequest編)

今回は、Volleyを使ってJSON形式のデータを取得したいと思います(`・ω・´)シャキーン
JSONデータを扱うようとして次の3種類があるみたいです。

・JsonRequest(抽象クラス)
・JsonArrayRequest
・JsonObjectRequest

JsonRequestは抽象クラスみたいなので、とりあえずおいておいてJsonArrayRequestを試してみたいと思います。

■JsonArrayRequestの利用方法

JsonArrayRequestはレスポンス結果がJSON形式の配列の場合に利用します。

まずはレスポンス側のPHPプログラムとして次のようなものを利用します(`・ω・´)シャキーン
<?
header("Content-Type: text/javascript; charset=utf-8");
echo( "[1,2,3,4,5,6,7,8,9,0]" );
exit(0);
?>
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.volleyexample3"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="8" />

    <!-- インターネットへのアクセスを許可 -->
    <uses-permission android:name="android.permission.INTERNET"/>    
    
    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.volleyexample3.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

</RelativeLayout>
MainActivity.java
package com.example.volleyexample3;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.Menu;
import android.widget.Toast;

import com.android.volley.Request.Method;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.Response.Listener;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonArrayRequest;
import com.android.volley.toolbox.JsonObjectRequest;
import com.android.volley.toolbox.Volley;

public class MainActivity extends Activity {

 //ログ出力時のタグ名
 private static final String TAG_LOG = "Log";
 //Volleyでリクエスト時に設定するタグ名。キャンセル時に利用する。
 private static final Object TAG_REQUEST_QUEUE = new Object();
 //画像のURL
 private static final String REQUEST_URL_REQUEST_JSON_ARRAY = "HTTPリクエストURL";
 //RequestQueueのインスタンス用
 private RequestQueue mRequestQueue;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  
  //RequestQueueのインスタンス用を取得
  mRequestQueue = Volley.newRequestQueue(getApplicationContext());

 }
 /*
  * onCreateの後に呼び出される。
  */
 @Override
 public void onStart(){
  super.onStart();
  //
  requestJsonArray();
 }
 
 /*
  * アプリが見えなくなったときに呼び出される。
  * (他のアプリを立ち上げたりした時など)
  */
 @Override
 public void onStop(){
  super.onStop();
  mRequestQueue.cancelAll(TAG_REQUEST_QUEUE);
 }
 
 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
  // Inflate the menu; this adds items to the action bar if it is present.
  getMenuInflater().inflate(R.menu.main, menu);
  return true;
 }
 /*
  * HTTPリクエストを投げる(JSONArray)
  */
 private void requestJsonArray(){
  
  // リクエストを投げる
  JsonArrayRequest request = new JsonArrayRequest(
   REQUEST_URL_REQUEST_JSON_ARRAY,
   new Response.Listener<JSONArray>(){
    @Override 
    public void onResponse(JSONArray response) {
     
     int length = response.length();
     
     //レスポンス受け取り時の処理
     if (length <= 0){
      //空の場合
      return;
     }
     
     for(int i = 0; i < length; i++){
      try {
       Integer value = (Integer)response.get(i);
       Log.d(TAG_LOG, value.toString());
      } catch (JSONException e) {
       // TODO Auto-generated catch block
       e.printStackTrace();
      }
     }
     
     //
     Toast.makeText(getApplicationContext(), response.toString(), Toast.LENGTH_LONG).show();
     
    }
   },
   new Response.ErrorListener() {
    @Override 
    public void onErrorResponse(VolleyError error) {
     
     //エラー時の処理
     Toast.makeText(getApplicationContext(), "onErrorResponse", Toast.LENGTH_LONG).show();
     
    }
   }
  );
  //タグを設定する
  request.setTag(TAG_REQUEST_QUEUE);
  
  //リクエスト&レスポンス情報の設定を追加
  mRequestQueue.add(request);

  //リクエスト開始
  mRequestQueue.start(); 
  
 }

}
次のように表示されれば問題ありません( ´∀`)bグッ!

■JsonObjectRequestの利用方法

JsonObjectRequestはレスポンス結果がJSON形式のオブジェクトの場合に利用します。
(PHPなどでは連想配列などのことを指す)

レスポンス側のPHPプログラムとして次のようなものを利用します(`・ω・´)シャキーン
<?
header("Content-Type: text/javascript; charset=utf-8");
echo( '{"test1":1,"test2":2,"test3":3}{"test1":1,"test2":2,"test3":3}' );
exit(0);
?>
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.volleyexample3"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="8" />

    <!-- インターネットへのアクセスを許可 -->
    <uses-permission android:name="android.permission.INTERNET"/>    
    
    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.volleyexample3.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

</RelativeLayout>
MainActivity.java
package com.example.volleyexample3;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.Menu;
import android.widget.Toast;

import com.android.volley.Request.Method;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.Response.Listener;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonArrayRequest;
import com.android.volley.toolbox.JsonObjectRequest;
import com.android.volley.toolbox.Volley;

public class MainActivity extends Activity {

 //ログ出力時のタグ名
 private static final String TAG_LOG = "Log";
 //Volleyでリクエスト時に設定するタグ名。キャンセル時に利用する。
 private static final Object TAG_REQUEST_QUEUE = new Object();
 //画像のURL
 private static final String REQUEST_URL_REQUEST_JSON_OBJECT = "HTTPリクエストURL";
 //RequestQueueのインスタンス用
 private RequestQueue mRequestQueue;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  
  //RequestQueueのインスタンス用を取得
  mRequestQueue = Volley.newRequestQueue(getApplicationContext());

 }
 /*
  * onCreateの後に呼び出される。
  */
 @Override
 public void onStart(){
  super.onStart();
  //
  requestJsonObject();
 }
 
 /*
  * アプリが見えなくなったときに呼び出される。
  * (他のアプリを立ち上げたりした時など)
  */
 @Override
 public void onStop(){
  super.onStop();
  mRequestQueue.cancelAll(TAG_REQUEST_QUEUE);
 }
 
 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
  // Inflate the menu; this adds items to the action bar if it is present.
  getMenuInflater().inflate(R.menu.main, menu);
  return true;
 }
 /*
  * HTTPリクエストを投げる(JSONObject)
  */
 private void requestJsonObject(){
  
  // リクエストを投げる
  JsonObjectRequest request = new JsonObjectRequest(
   //GETのみ?
   Method.GET,
   //リクエスト先
   REQUEST_URL_REQUEST_JSON_OBJECT,
   //リクエストパラメータ
   null,
   //レスポンス時のリスナー
   new Listener<JSONObject>() {
    @Override 
    public void onResponse(JSONObject response) {
     
     //レスポンス受け取り時の処理
     if (response.toString() == ""){
      //空の場合
      return;
     }
     
     String message = null;
     
     try {
      message = (String) response.getString("test1");
     } catch (JSONException e1) {
      // TODO Auto-generated catch block
      e1.printStackTrace();
     }
     //
     Log.d(TAG_LOG, "response : " + message);
     
     //
     Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show();

    }
   },
   //エラー時のリスナー
   new Response.ErrorListener() {
    @Override 
    public void onErrorResponse(VolleyError error) {
     
     //エラー時の処理
     Toast.makeText(getApplicationContext(), "onErrorResponse", Toast.LENGTH_LONG).show();
     
    }
   }
  );
  //タグを設定する
  request.setTag(TAG_REQUEST_QUEUE);
  
  //リクエスト&レスポンス情報の設定を追加
  mRequestQueue.add(request);

  //リクエスト開始
  mRequestQueue.start(); 
  
 }

}
次のように表示されれば問題ありません( ´∀`)bグッ!

以上です(`・ω・´)ゞビシッ!!

2013年9月9日月曜日

オブジェクト指向基礎

Java初心者  オブジェクト指向基礎 No.1

参考書籍 : わかりやすいJava オブジェクト指向編[川場 隆]

1. クラスには2つの機能
  • プログラムを実行する
  • オブジェクトを定義するだけ
2. オブジェクト
  • 値とメソッドをひとつにまとめたもの
3. 継承
  • 既存のクラス定義を利用して新しいクラスを定義する
4. カプセル化
  • オブジェクトの独立性・安全性を高める機能
5. ポリモーフィズム
  • 同じメソッドでもオブジェクトの種類により違う動作をする

クラス作成 == 型を新しく作るって事

お弁当をクラス化してみる…
中身は主食2品、副菜3品の枠があるとしよう(・ω・)うちのお弁当と一緒!
   public class BoxLunch(){
    String main_1;
    String main_2;
    String sub_1;
    String sub_2;
    String sub_3;
   }
  
この定義した変数達それぞれをフィールド変数というみたい。 ( =インスタンス変数、メンバ変数とも言う ) 基本定義には具体的な値はいれない。初期値を指定したい場合はコンストラクタを使用して行う。
コンストラクタ(構築者という意味)
new演算子がオブジェクトを作成した直後、コンストラクタが起動してオブジェクトに具体的な値をセットする
コンストラクタで初期値を指定してみる
    • public → どこからでも使用できる
    • protected → 継承先でも使用できる
    • private → そのクラス内で使用できる
   public class BoxLunch(){
    
    String main_1;
    String main_2;
    String sub_1;
    String sub_2;
    String sub_3;
    
    //コンストラクタ *****************
    public BoxLunch( 引数なくてもOK ){
     main_1 = "米";
     main_1 = "ハンバーグ";
     sub_1 = "卵焼き";
     sub_2 = "切干大根の煮付け";
     sub_3 = "ひじきの煮物";
    }
    // *************************
   }
  
今回は、リテラル(定数)で初期化しました。
引数を渡してあげてもOK。
また、コンストラクタは複数書けるんだって。へぇ (コンストラクタのオーバーロード)
   public class BoxLunch(){
    
    String main_1;
    String main_2;
    String sub_1;
    String sub_2;
    String sub_3;
    
    //コンストラクタ 1 これデフォルト*****************
    public BoxLunch(){
     main_1 = "米";
     main_1 = "ハンバーグ";
     sub_1 = "卵焼き";
     sub_2 = "切干大根の煮付け";
     sub_3 = "ひじきの煮物";
    }
    // ************************************
    
    
    //コンストラクタ 2*****************
    public BoxLunch( String main, String sub2, String sub3 ){
     main_1 = "米";
     main_1 = main;
     sub_1 = "卵焼き";
     sub_2 = sub2;
     sub_3 = sub3;
    }
    // ************************************
   }
  
米と卵焼き以外のものを突っ込みたい時はコンストラクタ2を使って初期化しちゃう。みたいな。
作ったクラスのインスタンスを作る
弁当つくる為に弁当箱を用意しよう(^3^)
   
   ( BoxLunch ) box = new BoxLunch();//弁当箱を用意(インスタンス)
   //米を炊き忘れていたので中身を急遽変更することに…
   box.main1 = "パン";
   box.main2 = "ハム";
   box.sub_1 = "バナナ";
   box.sub_2 = "ヨーグルト";
   box.sub_3 = "ジャム(?)";
  
  
インスタンスメソッド
値とメソッドをひとつにまとめたものとあったように、関数も書ける
   
   public class BoxLunch(){
    
    String main_1;
    String main_2;
    String sub_1;
    String sub_2;
    String sub_3;
    
    //コンストラクタ 1 これデフォルト*****************
    public BoxLunch(){
     main_1 = "米";
     main_1 = "ハンバーグ";
     sub_1 = "卵焼き";
     sub_2 = "切干大根の煮付け";
     sub_3 = "ひじきの煮物";
    }
    // ************************************
    
    //弁当を食べる為にはあけないといけないので
    public void openBox(){
     System.out.println( box.main1 );
     System.out.println( box.main2 );
     System.out.println( box.sub_1 );
     System.out.println( box.sub_2 );
     System.out.println( box.sub_3 );
    }
    
   }
   
  
   
   BoxLunch box = new BoxLunch();//弁当箱を用意(インスタンス)
   //米を炊き忘れていたので中身を急遽変更することに…
   box.main1 = "パン";
   box.main2 = "ハム";
   box.sub_1 = "バナナ";
   box.sub_2 = "ヨーグルト";
   box.sub_3 = "ジャム(?)";
   
   box.openBox();//オブジェクトの中にある関数を参照演算子(.)で呼び出す。
   //わーぃご飯の時間だね\(^O^)/
  
  
クラスメソッドとインスタンスメソッドの違いは、staticキーワードをつけるかどうかだけのようです。
   
   public class BoxLunch(){
    
    String main_1;
    String main_2;
    String sub_1;
    String sub_2;
    String sub_3;
    
    //コンストラクタ 1 これデフォルト*****************
    public BoxLunch(){
     main_1 = "米";
     main_1 = "ハンバーグ";
     sub_1 = "卵焼き";
     sub_2 = "切干大根の煮付け";
     sub_3 = "ひじきの煮物";
    }
    // ************************************
    
    //弁当を食べる為にはあけないといけないので
    public void openBox(){
     System.out.println( box.main1 );
     System.out.println( box.main2 );
     System.out.println( box.sub_1 );
     System.out.println( box.sub_2 );
     System.out.println( box.sub_3 );
    }
    
    //弁当を奈良の鹿に取られた、…あげた。
    public static void presentBoxLunch(){
     main_1 = "";
     main_1 = "";
     sub_1 = "";
     sub_2 = "";
     sub_3 = "";
    }
    
   }
   
  
newしたインスタンスにはpresentBoxLunchは含まれず、box.presentBoxLunch();感じには使用できません。 staticの時はnewせずに使用できます。
 BoxLunch.presentBoxLunch();
 いきなり鹿に取られては、newしてる暇もないですもんね(;_;)

Volleyを使ってみる(NetworkImageView編)

Volleyを使って画像を表示する場合のNetworkImageView版になります。

ImageRequestを使った方法はこちらの記事になります
Volleyを使ってみる。(ImageRequest編)
NetworkImageViewはImageViewの拡張クラスになっています。
利用時には引数にImageCacheを実装したクラスが必要になるので指定してあげる必要がある。

今回はキャッシュを利用しない方法にするので、
ImageCacheのgetBitmapメソッド内でnullを返しています。
画像の読み込みには、setImageUrlを使うだけで(・∀・)イイ!!ので楽チンです
AsyncTaskを利用しなくても非同期で処理を行ってくれる。

AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.volleyexample2"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="8" />

    <!-- インターネットへのアクセスを許可 -->
    <uses-permission android:name="android.permission.INTERNET"/>    
    
    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.volleyexample2.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >
  
    <com.android.volley.toolbox.NetworkImageView
        android:id="@+id/image"
  android:layout_width="wrap_content"   
  android:layout_height="wrap_content"/>

</RelativeLayout>
MainActivity.java
package com.example.volleyexample2;

import android.os.Bundle;
import android.app.Activity;
import android.graphics.Bitmap;
import android.view.Menu;

import com.android.volley.RequestQueue;
import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.Volley;
import com.android.volley.toolbox.NetworkImageView;
import com.android.volley.toolbox.ImageLoader.ImageCache;

public class MainActivity extends Activity {

 //ログ出力時のタグ名
 private static final String TAG_LOG = "Log";
 //Volleyでリクエスト時に設定するタグ名。キャンセル時に利用する。
 private static final Object TAG_REQUEST_QUEUE = new Object();
 //画像のURL
 private static final String REQUEST_URL_IMAGE = "画像URL";
 //RequestQueueのインスタンス用
 private RequestQueue mRequestQueue;
 //ImageLoader
 private ImageLoader mImageLoader;
 //ImageLoaderのキャッシュ
 private ImageCache mCache;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);

  //キャッシュの情報を取得する
  mCache = getCacheNone();
  //RequestQueueのインスタンス用を取得
  mRequestQueue = Volley.newRequestQueue(getApplicationContext());
  //
  mImageLoader = new ImageLoader(mRequestQueue, mCache);
  
  //NetworkImageViewを取得する
  NetworkImageView image = (NetworkImageView)findViewById(R.id.image);
  //画像の読み込み
  image.setImageUrl(REQUEST_URL_IMAGE, mImageLoader);

 }
 /*
  * onCreateの後に呼び出される。
  */
 @Override
 public void onStart(){
  super.onStart();
 }
 
 /*
  * アプリが見えなくなったときに呼び出される。
  * (他のアプリを立ち上げたりした時など)
  */
 @Override
 public void onStop(){
  super.onStop();
  mRequestQueue.cancelAll(TAG_REQUEST_QUEUE);
 }
 
 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
  // Inflate the menu; this adds items to the action bar if it is present.
  getMenuInflater().inflate(R.menu.main, menu);
  return true;
 }
 /*
  * キャッシュを利用しないためnullにする
  */
 private ImageCache getCacheNone(){
  
  return new ImageCache(){
   @Override
   public Bitmap getBitmap(String url) {
    return null;
   }
   @Override
   public void putBitmap(String url, Bitmap bitmap) {
   }   
  };
  
 }

}

次のように指定した画像が表示されたらOKです( ´∀`)bグッ!


以上です(`・ω・´)ゞビシッ!!

参考URL

Volleyを使ってみる(ImageRequest編)

今回は、Volleyを使って画像を取得したいと思います(`・ω・´)シャキーン
画像を扱う方法として次の2種類があるみたいです。

・ImageViewを利用する方法
・ImageViewの拡張のNetworkImageViewを利用する方法

まずImageViewを利用した方法で行いたいと思います。
基本的には、前回のImageStringと殆ど同じ流れになります

AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.volleyexample2"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="8" />

    <!-- インターネットへのアクセスを許可 -->
    <uses-permission android:name="android.permission.INTERNET"/>    
    
    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.volleyexample2.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >
    
 <ImageView  
  android:id="@+id/image"
  android:layout_width="wrap_content"   
  android:layout_height="wrap_content">
 </ImageView>

</RelativeLayout>
MainActivity.java
package com.example.volleyexample2;

import android.os.Bundle;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.view.Menu;
import android.widget.ImageView;

import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.Response.ErrorListener;
import com.android.volley.Response.Listener;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.ImageRequest;
import com.android.volley.toolbox.Volley;

public class MainActivity extends Activity {

 //ログ出力時のタグ名
 private static final String TAG_LOG = "Log";
 //Volleyでリクエスト時に設定するタグ名。キャンセル時に利用する。
 private static final Object TAG_REQUEST_QUEUE = new Object();
 //画像のURL
 private static final String REQUEST_URL_IMAGE = "画像URL";
 //RequestQueueのインスタンス用
 private RequestQueue mRequestQueue;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  
  //RequestQueueのインスタンス用を取得
  mRequestQueue = Volley.newRequestQueue(getApplicationContext());  

 }
 /*
  * onCreateの後に呼び出される。
  */
 @Override
 public void onStart(){
  super.onStart();
  //
  requestImage();
 }
 
 /*
  * アプリが見えなくなったときに呼び出される。
  * (他のアプリを立ち上げたりした時など)
  */
 @Override
 public void onStop(){
  super.onStop();
  mRequestQueue.cancelAll(TAG_REQUEST_QUEUE);
 }
 
 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
  // Inflate the menu; this adds items to the action bar if it is present.
  getMenuInflater().inflate(R.menu.main, menu);
  return true;
 }
 /*
  * HTTPリクエストを投げる(画像を取得する)
  */
 private void requestImage(){
  
  //ImageView を取得する
  final ImageView image = (ImageView)findViewById(R.id.image);

  //
  ImageRequest request = new ImageRequest(
   //URL
   REQUEST_URL_IMAGE,
   //レスポンス結果リスナー
   new Listener<Bitmap>() {
    @Override
    public void onResponse(Bitmap bm) {
     image.setImageBitmap(bm);
    }
   },
   //最大の幅。指定無しは0
   0, 
   //最大の高さ。指定無しは0
   0, 
   //デコードするフォーマット
   Config.ARGB_8888,
   //エラー時のリスナー(無視する場合にはnull)
   new ErrorListener() {
    public void onErrorResponse(VolleyError e) {
     e.printStackTrace();
    }
   }
  );
  
  //タグを設定する
  request.setTag(TAG_REQUEST_QUEUE);
  
  //リクエスト&レスポンス情報の設定を追加
  mRequestQueue.add(request);

  //リクエスト開始
  mRequestQueue.start(); 
  
 }

}

実行結果は次のようになります。指定した画像が表示されたらOK( ´∀`)bグッ!


以上です(`・ω・´)ゞビシッ!!

参考URL

2013年9月6日金曜日

Volleyを使ってみる(StringRequest編)

前回の記事「Volleyを使ってみる。(ダウンロード&設定) 」からの続きになります。
前回の記事でVolleyを使うための設定が終わったので、今度は実際に使ってみたいと思います+(0゚・∀・) + ワクテカ +

Volleyで実際にリクエストを投げるには、
リクエスト情報とレスポンス情報を前もって作っておき、
それをVolleyに渡してあげる事で実際にリクエストされるみたいです。

リクエスト情報とレスポンス情報を扱うのに、次のクラスが用意されているそうです。
Volley 基礎 (Android アプリ用ネットワークライブラリ)
・StringRequest クラス
・ImageRequest クラス
・JsonRequest クラス (抽象クラス)
・JsonArrayRequest クラス
・JsonObjectRequest クラス
・ClearCacheRequest クラス

受け取りたいレスポンス結果ごとにクラスが分かれているみたいです。

今回はこの中のStringRequestクラスを利用して、文字列のレスポンス結果を受け取りたいと思います(`・ω・´)シャキーン

その前に、リクエスト先のURL側で実行されるものを用意したいと思います
リクエストのプログラムはPHPで記述します。
今回は文字列を返すだけなので2行だけで楽チンワーイヽ(゚∀゚)メ(゚∀゚)メ(゚∀゚)ノワーイ
<?php
header("Content-Type: text/plain; charset=utf-8");
echo "hogehoge";
?>
次は、AndroidManifest.xmlの編集になります。 今回はインターネットへのアクセスが含まれるので許可してあげる必要があります。 この許可がされていない場合だと、次のようなエラーが発生してしまいます。
onErrorResponsejava.net.UnknownHostException: ホスト名
AndroidManifest.xmlのソース
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.volleyexample"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="8" />

    <!-- インターネットへのアクセスを許可 -->
    <uses-permission android:name="android.permission.INTERNET"/>
 
    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.volleyexample.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
次は、実際のAndroid側のMainActivityのコードになります。
package com.example.volleyexample;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.widget.Toast;

import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;


public class MainActivity extends Activity {

 //ログ出力時のタグ名
 private static final String TAG_LOG = "Log";
 //Volleyでリクエスト時に設定するタグ名。キャンセル時に利用する。
 private static final Object TAG_REQUEST_QUEUE = new Object();
 //リクエスト先
 private static final String REQUEST_URL_RESEPONSE_STRING = "リクエスト先のURL";
 //RequestQueueのインスタンス用
 private RequestQueue mRequestQueue;
 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  
  //RequestQueueのインスタンス用を取得
  mRequestQueue = Volley.newRequestQueue(getApplicationContext());
  
 }

 /*
  * onCreateの後に呼び出される。
  */
 @Override
 public void onStart(){
  super.onStart();
  //HTTPリクエストを行う
  requestString();
 }
 
 /*
  * アプリが見えなくなったときに呼び出される。
  * (他のアプリを立ち上げたりした時など)
  */
 @Override
    public void onStop(){
        super.onStop();
        mRequestQueue.cancelAll(TAG_REQUEST_QUEUE);
    }
 /*
  * 
  */
 private void requestString(){
  
  //リクエスト&レスポンス情報の設定
  //StringRequestの場合
  StringRequest request = new StringRequest(
   //送信方法 GET/POST
   Request.Method.GET, 
   //送信先
   REQUEST_URL_RESEPONSE_STRING,
   //レスポンス成功時のリスナー
   new Response.Listener<String>() {
    @Override 
    public void onResponse(String response) {
     
     //レスポンス受け取り時の処理
     if (response == null){
      //空の場合
      return;
     }
     //
     Toast.makeText(getApplicationContext(), response, Toast.LENGTH_LONG).show();
    }
   },
   //レスポンス失敗時のリスナー
   new Response.ErrorListener() {
    @Override 
    public void onErrorResponse(VolleyError error) {
     
     //エラー時の処理
     Toast.makeText(getApplicationContext(), "onErrorResponse", Toast.LENGTH_LONG).show();

    }
   }
  );

  //タグを設定する
  request.setTag(TAG_REQUEST_QUEUE);
  
  //リクエスト&レスポンス情報の設定を追加
  mRequestQueue.add(request);

  //リクエスト開始
  mRequestQueue.start();  
 }
 
 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
  // Inflate the menu; this adds items to the action bar if it is present.
  getMenuInflater().inflate(R.menu.main, menu);
  return true;
 }

}

次の画像のように、「hogehoge」が表示された成功です( ´∀`)bグッ!

次は、POST送信を行いたいと思います
今回はPOSTされてきた値を元に表示を変えるプログラムに変更しました(ΦωΦ)フフフ…
<?php

$nMode = isset( $_POST[ "mode" ] ) ? (int)$_POST[ "mode" ] : 0;
header("Content-Type: text/plain; charset=utf-8");
echo "{$nMode} ほげほげ";

exit(0);

?>
次は、実際のAndroid側のMainActivityのコードになります。
requestStringPostメソッドが追加されています( ̄ー ̄)ニヤリ
送信するパラメーターは次の箇所の中に書く必要があります。
protected Map<String, String> getParams() throws AuthFailureError {
//POSTするデータ
}
ソースコードは次のようになりました。
package com.example.volleyexample;

import java.util.HashMap;
import java.util.Map;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.widget.Toast;

import com.android.volley.AuthFailureError;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;


public class MainActivity extends Activity {

 //ログ出力時のタグ名
 private static final String TAG_LOG = "Log";
 //Volleyでリクエスト時に設定するタグ名。キャンセル時に利用する。
 private static final Object TAG_REQUEST_QUEUE = new Object();
 //リクエスト先
 private static final String REQUEST_URL_RESEPONSE_STRING = "リクエスト先のURL";
 //RequestQueueのインスタンス用
 private RequestQueue mRequestQueue;
 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  
  //RequestQueueのインスタンス用を取得
  mRequestQueue = Volley.newRequestQueue(getApplicationContext());
  
 }

 /*
  * onCreateの後に呼び出される。
  */
 @Override
 public void onStart(){
  super.onStart();
  //HTTPリクエストを行う
  //requestString();
  //
  requestStringPost(99);
 }
 
 /*
  * アプリが見えなくなったときに呼び出される。
  * (他のアプリを立ち上げたりした時など)
  */
 @Override
    public void onStop(){
        super.onStop();
        mRequestQueue.cancelAll(TAG_REQUEST_QUEUE);
    }
 /*
  * 
  */
 private void requestString(){
  
  //リクエスト&レスポンス情報の設定
  //StringRequestの場合
  StringRequest request = new StringRequest(
   //送信方法 GET/POST
   Request.Method.GET, 
   //送信先
   REQUEST_URL_RESEPONSE_STRING,
   //レスポンス成功時のリスナー
   new Response.Listener<String>() {
    @Override 
    public void onResponse(String response) {
     
     //レスポンス受け取り時の処理
     if (response == null){
      //空の場合
      return;
     }
     //
     Toast.makeText(getApplicationContext(), response, Toast.LENGTH_LONG).show();
    }
   },
   //レスポンス失敗時のリスナー
   new Response.ErrorListener() {
    @Override 
    public void onErrorResponse(VolleyError error) {
     
     //エラー時の処理
     Toast.makeText(getApplicationContext(), "onErrorResponse", Toast.LENGTH_LONG).show();

    }
   }
  );

  //タグを設定する
  request.setTag(TAG_REQUEST_QUEUE);
  
  //リクエスト&レスポンス情報の設定を追加
  mRequestQueue.add(request);

  //リクエスト開始
  mRequestQueue.start();  
 }
 /*
  * POST送信用
  */
 private void requestStringPost(final Integer mode){
  
  //リクエスト&レスポンス情報の設定
  //StringRequestの場合
  StringRequest request = new StringRequest(
   //送信方法 GET/POST
   Request.Method.POST, 
   //送信先
   REQUEST_URL_RESEPONSE_STRING,
   //レスポンス成功時のリスナー
   new Response.Listener<String>() {
    @Override 
    public void onResponse(String response) {
     
     //レスポンス受け取り時の処理
     if (response == null){
      //空の場合
      return;
     }
     //
     Toast.makeText(getApplicationContext(), response, Toast.LENGTH_LONG).show();
    }
   },
   //レスポンス失敗時のリスナー
   new Response.ErrorListener() {
    @Override 
    public void onErrorResponse(VolleyError error) {
     
     //エラー時の処理
     Toast.makeText(getApplicationContext(), "onErrorResponse", Toast.LENGTH_LONG).show();

    }
   }
  ){
   protected Map<String, String> getParams() throws AuthFailureError {
    //POSTで送信したい値を設定する
    Map<String, String> obj = new HashMap<String, String>();
    obj.put("mode", mode.toString());
    return obj;
   }
  };

  //タグを設定する
  request.setTag(TAG_REQUEST_QUEUE);
  
  //リクエスト&レスポンス情報の設定を追加
  mRequestQueue.add(request);

  //リクエスト開始
  mRequestQueue.start();  
 }
 
 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
  // Inflate the menu; this adds items to the action bar if it is present.
  getMenuInflater().inflate(R.menu.main, menu);
  return true;
 }

}


以上です(`・ω・´)ゞビシッ!!

参考URL

Volleyを使ってみる(ダウンロード&設定など)

AndroidでHTTPリクエストを行う手段としてはいくつかあるそうです(´・∀・`)ヘー
自分が見つけたの下記の3つになります!

・org.apache.http.impl.client.DefaultHttpClient
Apacheが提供していてバグも少なく安定しているが容量が大きい。
Android 2.1以前でも利用可能。
ネット上で見かけるのはこれが多いかも?

・android.net.http.AndroidHttpClient
DefaultHttpClientをAndroid向けに最適化したもの。
AndroidHttpClientはLevel 8 (Android 2.2 Froyo)から利用可能。

・java.net.HttpURLConnection
Froyo以前の実装にはバグがあるそうです。

最初は、勉強も兼ねてDefaultHttpClientを使っていましたが、
その情報を集めている途中で、つい最近出てきたVolleyというものを見つけましたφ(゚Д゚ )フムフム…

何が良いかはこちらのサイトに箇条書きで載っていたので抜粋させて頂きました( ̄ー ̄)ニヤリ
Volley とは
・JSON や画像ファイルなどのダウンロード非同期処理の簡素化
・リクエストのスケジューリング
・リクエストの優先順位付け
・メモリキャッシュ・ディスクキャッシュ
・強力で簡単なリクエストキャンセル
・Activity が存在しないときの自動キャンセル

VolleyはAndroid 2.2 (APIレベル8) から使えるみたいです。
Android3.0(HoneyComb)から使える、非同期にデータをロードする仕組みのAsyncTaskLoaderもある

ということなので、今回はVolleyを使ってみたいと思います。

■手順1.Volleyをダウンロードする

volleyのダウンロードページ

Branches > master

[tgz]をクリックしてダウンロードを行う。

ダウンロードをしたものを解凍しておく。

gitからダウンロードをすることも可能です。
git clone https://android.googlesource.com/platform/frameworks/volley
Initialized empty Git repository in /home/K1-admin/volley/.git/
remote: Counting objects: 7, done
remote: Finding sources: 100% (7/7)
remote: Total 1992 (delta 114), reused 1992 (delta 114)
Receiving objects: 100% (1992/1992), 822.05 KiB, done.
Resolving deltas: 100% (114/114), done.

■手順2.Volleyをインポートする
File > Import

Android > Existing Android Code Into Workspace
「Next」を押す。

Root Directoryに先ほどダウンロードしたVolleyディレクトリを指定して、
New Project Nameが「Volley」、「Volley Tests」を選択して「Finish」を押す。


インポートが完了すると、「Package Explorer」に
新しいプロジェクトとして「Volley」、「VolleyTests」が作成されています。

「Volley」、「VolleyTests」の各プロジェクトを右クリックして、
Androidを選択して、右下にある「Is Library」にチェックが入ってる事を確認する。
チェックが入っていない場合にはチェックを行う。

次に、Volleyを利用するプロジェクトを作成し、
そのプロジェクトに先ほどライブラリー化したプロジェクトを関連付けします。
Library枠の「Add」を押す。

Volleyを選択して「OK」を押す

そうすると、プロジェクトの中に「Android Dependencies」というディレクトリが作られて、
その中にあ「volley.jar」が追加されます。

これで設定が完了です。

以上です(`・ω・´)ゞビシッ!!

参考URL

2013年9月5日木曜日

Google Maps Android API V2を使ってみる(AndroidManifest.xmlの設定と実行)

前回の「 Google Maps Android API V2を使ってみる(Google Play Services API のインストール&設定)」からの続きになります(`・ω・´)シャキーン

今回は、AndroidManifest.xml設定を行いますφ(`д´)メモメモ...

関連記事一覧です(`・ω・´)シャキーン
1.Google Maps Android API V2を使ってみる(API キーの取得)
2.Google Maps Android API V2を使ってみる(Google Play Services API のインストール&設定)
3.Google Maps Android API V2を使ってみる(AndroidManifest.xmlの設定と実行)


■手順1.AndroidManifest.xmlの編集 Google Maps API V2を使えるようにすためにはAndroidManifest.xmlに、
以前の記事「Google Maps Android API V2を使ってみる(API キーの取得)」で取得したAPIキーを設定したり、 ネットワーク通信を許可したりなどを記述してあげる必要があります。

AndroidManifest.xmlの修正後
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.maptest"
    android:versionCode="1"
    android:versionName="1.0" >
    
     <!-- 
      minSdkVersion 
          アプリケーションが実行するために必要な最小の API レベルを指定する数値。
          API レベルがこの属性で特定された値より低い場合に、ユーザがこのアプリケーションをインストールしないよう保護する。
      maxSdkVersion
          アプリケーションが実行するために必要な最大の API レベルを指定する数値。
          API レベルがこの属性で特定された値より高い場合に、ユーザがこのアプリケーションをインストールしないよう保護する。
      targetSdkVersion
        アプリケーションがこれより低いバージョン ( 最低 minSdkVersion の指定まで ) で実行可能ですが、ここで指定されたバージョンでの動作はをテスト済みであるということを明示する。
          プラットフォームがこのターゲットバージョンの上位互換を守るためになにか余分な処理を実行する必要はないということをプラットフォームに知らせるためのもの。
    -->
    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="18" />

    <!-- アプリケーションが要求しているGoogle Maps APIの許可を付与する -->
    <permission
          android:name="com.example.maptest.permission.MAPS_RECEIVE"
          android:protectionLevel="signature"/>
    <!-- アプリケーションが要求しているGoogle Maps APIの許可を付与する -->
    <uses-permission android:name="com.example.maptest.permission.MAPS_RECEIVE"/>        
    
    <!-- インターネットへのアクセスを許可 -->
    <uses-permission android:name="android.permission.INTERNET"/>
    <!-- ネットワーク状態を取得 -->
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <!-- 外部SDカードへの書き込み -->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <!-- Google API へのアクセス -->
    <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/>
    <!-- 位置情報の取得 (Wi-Fi経由) -->
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    <!-- 位置情報の取得 (GPS経由) -->
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <!-- OpenGL ES version 2 -->
    <uses-feature android:glEsVersion="0x00020000" android:required="true"/>
    
    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        
    <!-- Google API の認証キー -->
     <meta-data
       android:name="com.google.android.maps.v2.API_KEY"
       android:value="Google APIコンソールで生成したAPIキーを設定する"/>
 
     <uses-library
       android:name="com.google.android.maps" />
            
        <activity
            android:name="com.example.maptest.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
■手順2.レイアウトファイルの作成(activity_main.xml)
API Levelが12未満も対象にする場合。(12以上でも問題ない)
<?xml version="1.0" encoding="utf-8"?>
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
  android:id="@+id/map"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  class="com.google.android.gms.maps.SupportMapFragment"/>
API Levelが12以上を対象にする場合。
<?xml version="1.0" encoding="utf-8"?>
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
  android:id="@+id/map"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  class="com.google.android.gms.maps.MapFragment"/>

■手順3.MainActivityの作成

こちらは、API Levelが12未満用の場合になります。(12以上でも動作する)
package com.example.maptest;

import android.os.Bundle;
import android.support.v4.app.FragmentActivity;

public class MainActivity extends FragmentActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

}
こちらは、API Levelが12以上の場合になります。
package com.example.maptest;

import android.app.Activity;
import android.os.Bundle;

public class SampleMapActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_sample_map);
    }

}

■手順3.実行

実行する前に、プロジェクトに設定されているProject Build Targetの確認をしておきます。
activity_main.xmlとMainActivityで記述した内容と一致するAPIバージョンが指定されているか確認する。
(プロジェクトを右クリックしてプロパティを開き、Androidを選択すると確認ができます。)

確認が終わったら実際に実行してみると・・・背景がグレーで何も表示されない( ´゚д゚`)エー

表示されないせいでAPIの設定やAndroidManifest.xmlが間違っているのかなど
色々調べたりしてだいぶここではまっていましたが、
こちらのブログに書かれてる内容が原因っぽい感じでした。
エミュレータでGoogle Maps for Android V2を動かす方法

ブログに書かれている内容を読むと、
原因はGoogle Maps APIを利用するにはGoogle Play Servicesがインストールされている事と、
その最新版が必要?みたいで、現状エミュレーターでインストールできるものでは対応されていない?みたいな感じでした。

そこでどうしてもエミュレーターでやりたい場合には、
手動でGoogle Play Servicesのapkファイルをインストールするれば出来るとのことです。(´・∀・`)ヘー
仕方ないので、実機で確認してみたら普通に表示されました( ゚д゚)ポカーン



どうしてもエミュレーターで動作確認したって言う方は、
次のサイトに書かれているような手順で手動でGoogle Play Servicesの最新版などをインストールすると実行できるかもしれません。
エミュレータでGoogle Maps for Android V2を動かす方法

実際にここのサイトの手順と同じようにやったらエミュレーターでも動くようになりました!
ただ、現在やると動作しません・・・1ヶ月前までは動いてたのに(´;ω;`)ウッ…

エミュレーターで動かすと激重だったので、大人しく実機で確認した方が良いかもしれません・・・orz

念のため手動でやる場合の手順を書いておきます。

エミュレーター起動後に、コマンドプロンプトで「adb devices」を実行する。
C:\Users\ユーザー名>adb devices
List of devices attached
emulator-5554   device
※adbコマンドのパスが通っていないと正しく実行できません。 出力された結果の「emulator-5554」がエミュレーターの名前になります。
ここは実行している環境などで変わる?

次に、必要なapkファイルをダウンロードしてきます。
こちらのサイトに最新のGoogle Play Servicesのapkファイルがアップされているみたいでした。

com.android.vending-4.2.9.apk
com.google.android.gms.apk

ダウンロードが終わったら、エミュレーターにインストールを行います。
#vending.apkのインストール。パスはダウンロードした場所を正しく指定してください
adb -s emulator-5554 install C:\app\android-apk\com.android.vending-4.2.9.apk
71 KB/s (6129144 bytes in 83.657s)
        pkg: /data/local/tmp/com.android.vending-4.2.9.apk
Success

#gms.apkのインストール。パスはダウンロードした場所を正しく指定してください
adb -s emulator-5554 installC:\app\android-apk\com.google.android.gms.apk
64 KB/s (6064733 bytes in 91.883s)
        pkg: /data/local/tmp/com.google.android.gms.apk
Success
とうまくインストールが出来れば正しくエミュレーターで動くようになるかもしれません!?((((;゚Д゚))))ガクガクブルブル

現状だと、インストールしようとすると、
Failure [INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES]
Failure [INSTALL_PARSE_FAILED_NO_CERTIFICATES]
などが出てしまいうまく行きませんでした・・・。

この辺を解決すればもしかたらできるかもです!

以上です(`・ω・´)ゞビシッ!!
参考URL