1年に1度か2度程度、検証等でAndroidアプリを開発をする機会が訪れるのですが、Hello Worldレベルからすっかり忘れてしまうので、主要な要素を思い出すためのメモ。
前回(2014年中盤)の開発から変わったこと
- Lollipopが出た
- Volleyがdependenciesに書けば使えるようになっている
- JsonObjectReqestの引数の型チェックが厳しくなっている
- Android Studioのアイコンが変わった(1.3.1になった)
やりたいこと
そんなに多くない。
前提知識として
- ショートカット
- デバッグログ出力
実装としては、
- レイアウト
- ボタンクリック
- 画面遷移
- パラメーター渡し
- JSON連携
- ListView(これやると底なしですが、とりあえずjsonを表示するところまで)
くらい。
ショートカット
とりあえずはこの2つ。
- コードの形成 Option + Command + l
- ライブラリの補完 Option + enter
デバッグログ出力
とりあえず、
- Log.d(string tag,string msg)
という形式。LogCatでフィルタリングして見る。
その他、Log.v, Log.i, Log.w, Log.e などなど。
ログが出力されない時はadb serverのリスタートか、Android StudioでTools->Android->Enable ADB IntegrationをOn/Offしてみる。
レイアウト
Layoutは、LinearLayoutさえコントロールできれば何とかなります。
私は手書き派なので、とりあえず、ルート要素として下記の記述を基本とします。
- namespaceの定義
- layout_widthとlayout_heightの定義
- 必要に応じてorientation
が最小単位といったところ。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
</LinearLayout>
Command + Option + l でコード整形。
ボタンクリック
クリックイベントの実装法は皆さんお悩みのようですが、私はプログラマさんが一番嫌う?Androud Studioで、ボタンプロパティのonClickに直接イベントメソッドを記述する方法を選ぶことにします(buttonにandroid:onClick属性設定)。何しろ年に1度なので。
ViewにTextViewとボタンを設置し、それぞれ、
- txt1
- bnt1
と命名。
そして、MainActivityのどこかに、
public void changeText(View view)
{
TextView tv = (TextView)findViewById(R.id.txt1);
tv.setText("hoge");
}
などと書く。
buttonはこれでなんとかなりますが、他のオブジェクトを利用するさい、結局setOnClickListener()を使うので、全体的な一貫性としては、setOnClickListener()を利用したほうがいいのかもしれません。
setOnClickListener()も一応書きます。
Button btn = (Button)findViewById(R.id.btn1);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d("tama", "clicked");
}
});
記述量はかわらないですね。。Java8に対応するとラムダで書けるようになるのでしょうか。
Javaだとややこしそうですが、要はjQueryで、
$("#btn").click(function(){
console.log("hoge");
});
ってしてるのと同じ。無名(匿名)関数。
最近だと、Android/Annotationsとか、Butter Knifeみたいな、簡単記述用のライブラリもあるようです。
そもそもGoogleはなぜ、Android開発言語をJavaにしたのか。Swiftみたいに、新しいの出して欲しい。
画面遷移
Activityの追加
何は無くても、遷移先のActivityの追加が必要。プロジェクトを右クリックして、新規->Activity->Blank Activityとする。Manifestへの追加もやってくれる。楽ちん。
パーツの配置
- MainActivityにbtn1とtxt1を配置
- SubActivityにbtn2とtxt2を配置
btn1にSubへの遷移コードを、btn2にMainへの遷移(自分を消す)コードを書く。
btn1のonClick
public void gotoSub(View view)
{
//create intent
Intent intent = new Intent(getApplication(), SubActivity.class);
//start intent
startActivity(intent);
}
btn2のonClick
遷移というより、消しているだけ。
finish();
パラメーター渡し
次に遷移時のパラメーター渡し。
ただ渡すだけなら簡単。戻してもらうなら帰りのための準備が少々必要。
ただ渡すだけ
btn1のonClick(送り側)
public void gotoSub(View view)
{
//create intent
Intent intent = new Intent(getApplication(), SubActivity.class);
//param
intent.putExtra("name","hoge");
intent.putExtra("age",40);
//start intent
startActivity(intent);
}
btn2のonClick(受け取り側)
特に受け取るイベントがないので、とりあえずonCreate()で受け取り。
受け取るときは型を意識する必要あり。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sub);
//create intent
Intent intent = getIntent();
//受け取り
String name = intent.getStringExtra("name");
Integer age = intent.getIntExtra("age",0);
//内容出力
Log.d("tama",name);
Log.d("tama", age.toString());
}
戻してもらう
難しくはないが、
- requestCodeが必要(一意ならなんでも良い)
- startActivityForResult()を使う
- onAcitivityResult()で受け取る
という形となる。
btn1のonClick(送り側)
public void gotoSub(View view)
{
//create intent
Intent intent = new Intent(getApplication(), SubActivity.class);
//params
intent.putExtra("name","hoge");
intent.putExtra("age",40);
//+requestcode
int requestCode = 1000;
//+startactivity
startActivityForResult(intent,requestCode);
}
//+受け取り
protected void onActivityResult(int requestCode, int resultCode, Intent intent)
{
//もろもろ初期化・受け取り
super.onActivityResult(requestCode, resultCode, intent);
//受け取り
String str = intent.getStringExtra("back");
//出力
Log.d("tama",str);
}
btn2のonClick(受け取り側)
fisnish()の前に、Intentの処理をするが、一部、普通のパラメーター送りと形式が違う。
- setResult()で戻し値をセットする。
public void gotoMain(View view)
{
//create intent
Intent intent = new Intent();
intent.putExtra("back","back data");
setResult(RESULT_OK,intent);
finish();
}
JSON連携
今の時代、何はなくてもJSON(API)連携です。通信はOkHttpとかでもいいのですが、結局複雑なことをやろうとするとVolleyになるのでVolley使います。
準備:Volleyの読み込み
以前は何かと大変だったのですが、今は、build.grandelのdependenciesに追加すればいいみたいです。
追加するのは(Module:app)の方。
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:22.2.1'
compile 'com.mcxiaoke.volley:library:1.0.18'
}
Sync Nowをお忘れなく。
バージョンは変わるのでここを参照。
準備:internet使用許可
AndroidManifest.xmlに
<uses-permission android:name="android.permission.INTERNET"/>
を追加。<application>と同じ階層。
Android StudioでGUI使って追加する方法は無いのかな?
Volleyの利用
btn1のコード(メソッド名がgotoSubなのは上からの流れでお許しを)。
最もシンプルなパターンを書く。btn1をクリックしたら、サーバからjson取得して、Log.d()で表示。
ちなみに、APIから帰ってくるJSONは、
{"status":"OK","msg":"This is a message."}
こんなん。
では、Volleyのコード。
以前書いたコードでは、「JsonObjectRequestがあいまいです」的なエラーが出てコンパイル出来なくなってしまっていまいた。第三引数のnullに(String)nullと型指定することで、回避しました。
public void gotoSub(View view)
{
//url
String url = "http://www.bluecode.jp/test/json.php";
//queue生成
RequestQueue queue = Volley.newRequestQueue(this);
//jsonRequest生成
JsonObjectRequest jsonRequest = new JsonObjectRequest(Request.Method.GET,url,(String)null,
new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject jsonObject) {
//JSONの処理
try{
//1階層目は普通に
String status = jsonObject.getString("status");
//出力
Log.d("tama", "status=" + status);
}catch(Exception e){
e.printStackTrace();
}
}
},
new Response.ErrorListener(){
@Override
public void onErrorResponse(VolleyError error){
//
}
}
);
//Queueに追加
queue.add(jsonRequest);
}
配列を受け取る方法はこちらもしくは、下記サンプルをどうぞ。
ListView
感覚を思い出すための最小限のListView表示。
最低限のListView
- ListViewを配置。lv1という名前にする。
- とりあえずgotoSub()にデータ読み込み・表示実装。
public void gotoSub(View view)
{
//表示用データ
String[] strList = {"hoge","foo","shoo"};
//ListView
ListView lv = (ListView)findViewById(R.id.lv1);
//Adapter
ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,strList);
//set adapter
lv.setAdapter(arrayAdapter);
}
手順としては、
- データ生成(後でも良い)
- ListView生成
- Adapter生成(ListViewのテンプレートやバインドするデータはここで選ぶ)
- ListViewにAdapterをセット
という流れ。
Volleyで取得した内容をListViewで表示
このへんから雲行きが怪しくなる。が、とりあえず動くコードを載せておきます。
事務用にJSONも変えました。
{"status":"OK","msg":"This is a message.","members":["tanaka","suzuki","yamamoto","sato"]}
ListView取得はこんな感じ。配列はJSONArrayで受ける。
public void goAction(View view)
{
//url
String url = "http://www.bluecode.jp/test/json.php";
//queue生成
RequestQueue queue = Volley.newRequestQueue(this);
//jsonRequest生成
JsonObjectRequest jsonRequest = new JsonObjectRequest(Request.Method.GET,url,(String)null,
new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject jsonObject) {
//JSONの処理
try{
//配列の入れ物
ArrayList<String> arrayStr = new ArrayList<>();
//listview
ListView lv = (ListView)findViewById(R.id.lv1);
//ステータス取得
Log.d("tama","sattus="+jsonObject.getString("status"));
//members取得(配列)
JSONArray members = jsonObject.getJSONArray("members");
//ループしてArrayListへ
for(int i = 0; i < members.length(); i++){
arrayStr.add(members.getString(i));
}
//adapter
ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(getApplication(),android.R.layout.simple_list_item_1,arrayStr);
//set adapter
lv.setAdapter(arrayAdapter);
Log.d("tama","success");
}catch(Exception e){
e.printStackTrace();
}
}
},
new Response.ErrorListener(){
@Override
public void onErrorResponse(VolleyError error){
//
Log.d("tama","error");
}
}
);
//Queueに追加
queue.add(jsonRequest);
}
ここでは、一度ArrayListに入れていますが、JSONObjectを直接扱うカスタムクラス等を作ったほうがいいでしょう。
ListViewの基本はドットインストールでおさらいする。