2015年7月25日土曜日

Android開発 LayoutInflaterを利用してListViewをカスタマイズする

Androidのリスト表示をカスタマイズして、クリック、長押しに反応するようにします。
リスト表示の見た目を変えるために、LayoutInflaterを利用します。
http://developer.android.com/intl/ja/reference/android/view/LayoutInflater.html

とくになにもせずAndroidのListViewを表示したときは、単一のテキストまたはボタンなどが行になって表示されます。
色々な要素をリスト表示したいときには、たとえば、Webサイトの場合だとループの中にHTMLを書くだけで済むのですが、Androidの場合は、LayoutInflaterを利用してListViewの中に動的にxmlを差し込んで表示したりする必要があります。
また、リストをスクロールしたとき、リストの要素が再利用されるので、リスト番号が単純に上から順にインクリメントされているわけではなく、クリックでリスト番号を取得するための挙動を制御する必要がありました。
このように、Androidでのリストの扱いは、ひとくせある感じになっています。

目的を実現するにあたって、以下の資料を参考にしました。

androidでRSSを取得して一覧表示 - m_shige1979のささやかな抵抗と欲望の日々
http://m-shige1979.hatenablog.com/entry/2015/07/15/080000
Adapter#getViewの挙動について - hyoromoのブログ
http://hyoromo.hatenablog.com/entry/20090912/1252777077
Android -ListView(イベント処理)- <MitoRoid>
http://mitoroid.com/category/android/android_listview3.php
LayoutInflater - Androyer in Japan
https://sites.google.com/site/androyerjapan/home/layoutinflater
ListView で onItemClick() と onItemLongClick() を両立 - Unmotivated
http://blog.lciel.jp/blog/2013/11/22/onitemclick-vs-onitemlongclick/

以下、コードの解説です。

MainActivity.java

リストの要素を作ります。ArrayAdapterを継承したrowAdapaterをリストビューに渡しています。
クリック・長押しされたときにトーストを表示するようにします。
package monst.post.nine.listview1;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends ActionBarActivity {
private ListView listview;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 表示用のリストを用意
List<RowDetail> objects = new ArrayList<RowDetail>();
for (int i = 0; i < 100; i++) {
RowDetail item = new RowDetail();
StringBuilder title = new StringBuilder();
title.append("テスト");
title.append(i);
String title_message = new String(title);
StringBuilder detail = new StringBuilder();
detail.append(title_message);
detail.append("の詳細データです。");
String detail_message = new String(detail);
item.setTitle(title_message);
item.setDetail(detail_message);
// リストにアイテムを追加
objects.add(item);
}
// リストビューへ紐付け
listview = (ListView)findViewById(R.id.listView);
// ArrayAdapterを設定
RowDetailAdapter rowAdapater = new RowDetailAdapter(this, 0, objects);
// リストビューへリストを登録
listview.setAdapter(rowAdapater);
// リストビューがクリックされたときのコールバックリスナーを登録
listview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
// リストのアイテムをクリックした時の挙動
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// リストビューの項目を取得
ListView listview = (ListView) parent;
RowDetail item = (RowDetail) listview.getItemAtPosition(position);
String text = "クリックしました:" + item.getTitle() + ":" + item.getDetail();
// トースト表示
Toast.makeText(getApplicationContext(), text, Toast.LENGTH_SHORT).show();
}
});
// リストビューの項目が長押しされたときのコールバックリスナーを登録
listview.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
// リストビューの項目を取得
ListView listview = (ListView) parent;
RowDetail item = (RowDetail) listview.getItemAtPosition(position);
String text = "長押ししました:" + item.getTitle() + ":" + item.getDetail();
// トースト表示
Toast.makeText(getApplicationContext(), text, Toast.LENGTH_LONG).show();
// onItemClickを実行しない
return true;
}
});
}
}

RowDetail.java

リストの要素を保存する際に使用するクラスです。
package monst.post.nine.listview1;
public class RowDetail {
private String title;
private String detail;
public void setTitle(String title){
this.title = title;
}
public String getTitle(){
return this.title;
}
public void setDetail(String detail){
this.detail = detail;
}
public String getDetail(){
return this.detail;
}
}
view raw RowDetail.java hosted with ❤ by GitHub

RowDetailAdapter.java

リストビュー用のアダプターです。
リストをスクロールして、新しい行が表示されるタイミングでgetViewが実行されます。
レイアウトが初めて作成される場合のみLayoutInflaterを実行します。それ以外は、表示されなくなったViewが引数に渡されてくるので再利用します。
package monst.post.nine.listview1;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
import java.util.List;
public class RowDetailAdapter extends ArrayAdapter<RowDetail> {
private LayoutInflater layoutinflater;
// コンストラクタ
public RowDetailAdapter(Context context, int textViewResourceId, List<RowDetail> objects){
super(context, textViewResourceId, objects);
// xmlで定義したレイアウトを取得
layoutinflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// 指定行のデータを取得
RowDetail detail = (RowDetail)getItem(position);
// レイアウトが初めて作成される場合のみ作成
if(null == convertView){
convertView = layoutinflater.inflate(R.layout.row, null);
}
// 行のデータを項目へ設定
TextView text1 = (TextView)convertView.findViewById(R.id.textView);
text1.setText(detail.getTitle());
TextView text2 = (TextView)convertView.findViewById(R.id.textView2);
text2.setText(detail.getDetail());
// 返却
return convertView;
}
}

activity_main.xml

ListViewを表示します。
<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:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">
<ListView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/listView"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
</RelativeLayout>

row.xml

ListViewの中身になります。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:weightSum="1">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Large Text"
android:id="@+id/textView" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="Medium Text"
android:id="@+id/textView2"
android:layout_weight="0.08" />
</LinearLayout>
view raw row.xml hosted with ❤ by GitHub

2015年7月18日土曜日

Android開発 JSONをVolleyで取得して、お天気アプリを作る

JSONデータを返すAPIを叩いて、ビューに表示するだけの簡単なAndroidサンプルアプリです。
APIを叩くときには、Androidの非同期HTTP通信ライブラリである”Volley”を使います。
今回のアプリは、この、Volleyのトレーニング目的で作ってみました。
APIは、livedoor 天気情報のAPIを利用します。(http://weather.livedoor.com/weather_hacks/webservice

さて、このVolleyとはいったい何でしょうか?
こちらの記事が参考になります。

ネットワーク通信用ライブラリVolleyを使いこなす | Tech Booster
http://techbooster.org/android/hacks/16474/
Android SDKでは非同期処理(またはマルチスレッド化)のための機構が用意されています。AsyncTaskやService、それらを拡張したAsyncTaskLoader、IntentServiceが代表的です。さらに汎用的に使えるHandler、ApacheのHttpClient、JavaのExecutorService、Threadなど非同期処理のための仕組みが豊富に存在していますが非同期でのキャンセル処理や取得済みデータのキャッシュ方法など周辺技術と組み合わせて設計しないといけません。
Android SDKの標準APIは応用力が高いのですが、習得するまでの難しさ、エラー処理、各バージョンごとの実装差異が存在しています。これらの課題を解消するためにVolleyライブラリが作られました。
以前、Apache HTTP Client(DefaultHttpClient)を使ったサンプルアプリを作ったことがあるのですが、どうやら、最近のAndroidでは、メインスレッドからネットワーク処理を行うことを許していないそうで。別スレッドを立ち上げてHTTPの処理を実行したり、さらに、これが別スレッドであるがためにViewに情報を渡そうとすると、ハンドラを生成したりと案外面倒だった記憶があります。Volleyは、この複雑だった処理を簡潔に書けるようにします。
Volleyは、ネットワークリクエストとキャッシュをスレッドプールを使って、それぞれの通信処理をリクエストという単位でキューイングして処理を捌きます。そして、コールバックで処理結果がUIスレッドに渡されます。
ネットワーク経由で取得した情報をビューへ渡すための処理をVolleyに任せる感じです。

Android StudioのプロジェクトにVolleyを導入

app/build.gradleファイルを編集、compile行を追記。
dependencies {
    ...
    compile 'com.android.volley:volley:1.0.0'
}
この状態で、Android StudioのメニューからBuild -> Make Projectしてみてください。エラーが出なかったらVolleyライブラリ導入成功です。

Volleyを使ったサンプルコード

以下、サンプルコードです。
<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:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/textview_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="@dimen/abc_text_size_large_material"
android:textColor="@android:color/black"
android:background="#ffb8db83" />
<ListView
android:id="@+id/listview_forecasts"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#ffbff8ec" />
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/textview_description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#ffffffff"
android:textColor="@android:color/black" />
</ScrollView>
</LinearLayout>
</RelativeLayout>
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.yako.volleyinstalltest" >
<uses-permission android:name="android.permission.INTERNET" />
<application
android:name="AppController"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".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>
package com.example.yako.volleyinstalltest;
import android.app.Application;
import android.text.TextUtils;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.toolbox.JsonObjectRequest;
import com.android.volley.toolbox.Volley;
/**
* AppController
*/
public class AppController extends Application {
public static final String TAG = AppController.class
.getSimpleName();
private RequestQueue mRequestQueue;
private static AppController mInstance;
@Override
public void onCreate() {
super.onCreate();
mInstance = this;
}
public static synchronized AppController getInstance() {
return mInstance;
}
public RequestQueue getRequestQueue() {
if (mRequestQueue == null) {
mRequestQueue = Volley.newRequestQueue(getApplicationContext());
}
return mRequestQueue;
}
public <T> void addToRequestQueue(JsonObjectRequest req, String tag) {
// set the default tag if tag is empty
req.setTag(TextUtils.isEmpty(tag) ? TAG : tag);
getRequestQueue().add(req);
}
public <T> void addToRequestQueue(Request<T> req) {
req.setTag(TAG);
getRequestQueue().add(req);
}
public void cancelPendingRequests(Object tag) {
if (mRequestQueue != null) {
mRequestQueue.cancelAll(tag);
}
}
}
apply plugin: 'com.android.application'
android {
compileSdkVersion 22
buildToolsVersion "22.0.1"
defaultConfig {
applicationId "com.example.yako.volleyinstalltest"
minSdkVersion 15
targetSdkVersion 22
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:22.2.0'
compile 'com.android.volley:volley:1.0.0'
}
view raw build.gradle hosted with ❤ by GitHub
package com.example.yako.volleyinstalltest;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.app.Activity;
import android.app.ProgressDialog;
import android.os.Bundle;
import android.util.Log;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
import com.android.volley.AuthFailureError;
import com.android.volley.NetworkError;
import com.android.volley.NoConnectionError;
import com.android.volley.ParseError;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.ServerError;
import com.android.volley.TimeoutError;
import com.android.volley.VolleyError;
import com.android.volley.VolleyLog;
import com.android.volley.toolbox.JsonObjectRequest;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
public class MainActivity extends ActionBarActivity {
// JSONデータ取得URL
private final String URL_API = "http://weather.livedoor.com/forecast/webservice/json/v1?city=130010";
// Volleyでリクエスト時に設定するタグ名、キャンセル時に利用 クラス名をタグ指定
private static final Object TAG_REQUEST_QUEUE = MainActivity.class.getName();
// 地区名用テキストビュー
TextView textview_title;
// 地区名用テキストビュー
TextView textview_description;
// 予報表示用リストビューのアダプター
ArrayAdapter<String> adapter;
// ログ出力用のタグ
private static final String TAG = MainActivity.class.getSimpleName();
// Volleyへ渡すタグ
String tag_json_obj = "json_obj_req";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.e(TAG, "onCreate");
// ビューを設定
// 地区名
textview_title = (TextView) findViewById(R.id.textview_title);
// 予報
ListView listview_forecasts = (ListView) findViewById(R.id.listview_forecasts);
adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1);
listview_forecasts.setAdapter(adapter);
// 天気概況
textview_description = (TextView) findViewById(R.id.textview_description);
// リクエスト処理
request();
}
// リクエスト処理
private void request() {
// ロードダイアログ表示
final ProgressDialog pDialog = new ProgressDialog(this);
pDialog.setMessage("Loading...");
pDialog.show();
JsonObjectRequest jsonObjReq = new JsonObjectRequest(Request.Method.GET, URL_API, null,
new Response.Listener<JSONObject>() {
// レスポンス受信のリスナー
@Override
public void onResponse(JSONObject response) {
// ログ出力
Log.d(TAG, "onResponse: " + response.toString());
// ロードダイアログ終了
pDialog.hide();
try {
// 地区名を取得、テキストビューに登録
String title = response.getString("title");
textview_title.setText(title);
// 天気概況文を取得、テキストビューに登録
JSONObject description = response.getJSONObject("description");
String description_text = description.getString("text");
textview_description.setText(description_text);
// 天気予報の予報日毎の配列を取得
JSONArray forecasts = response.getJSONArray("forecasts");
for (int i = 0; i < forecasts.length(); i++) {
JSONObject forecast = forecasts.getJSONObject(i);
// 日付を取得
String date = forecast.getString("date");
// 予報を取得
String telop = forecast.getString("telop");
// リストビューに登録
adapter.add(date + ":" + telop);
}
} catch (JSONException e) {
Log.e(TAG, e.getMessage());
}
}
},
new Response.ErrorListener() {
// リクエストエラーのリスナー
@Override
public void onErrorResponse(VolleyError error) {
// ロードダイアログ終了
pDialog.hide();
// エラー処理
Log.d(TAG, "Error: " + error.getMessage());
if( error instanceof NetworkError) {
} else if( error instanceof ServerError) {
} else if( error instanceof AuthFailureError) {
} else if( error instanceof ParseError) {
} else if( error instanceof NoConnectionError) {
} else if( error instanceof TimeoutError) {
}
}
}
);
// シングルトンクラスで実行
AppController.getInstance().addToRequestQueue(jsonObjReq, tag_json_obj);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
include ':app'
view raw settings.gradle hosted with ❤ by GitHub

以下の資料を参考にしました。

Transmitting Network Data Using Volley | Android Developers
https://developer.android.com/training/volley/index.html
Android working with Volley Library
http://www.androidhive.info/2014/05/android-working-with-volley-library-1/
Volleyについて調べる(1) - 未処分利益
http://www.vagrantup.jp/entry/2013/12/07/164310
Volley 基礎 (Android アプリ用ネットワークライブラリ) - ひだまりソケットは壊れない
http://vividcode.hatenablog.com/entry/android-app/volley-basis
Android - Volleyの起動・停止・キャンセル - Qiita
http://qiita.com/ueno-yuhei/items/d81dc638951ce3f6988a
ケーワン・エンタープライズのエンジニアメモ(`・ω・´)ゞビシッ!!: Volleyを使ってみる(JsonArrayRequest、JsonObjectRequest編)
http://k-1-ne-jp.blogspot.jp/2013/09/volleyjsonrequestjsonarrayrequestjsonob.html
【Android】Volleyを使ってネットワーク通信 その2 実装編【ライブラリ】 | 手巻き式IT
http://temakishiki.com/?p=141

2015年7月10日金曜日

Android開発 WebViewでウェブページを読み込む


最近、趣味でAndroidアプリを作っていて、初心者レベルなのですが、若干知見が溜まってきたので、サンプルコードをブログにしてみます。

ここでは、Androidでウェブページを読み込む方法を紹介します。
いくつか方法があるのですがここではスタンダードなWebViewを利用します。
Activityは、Blank Activityを使います。

AndroidManifest.xml
まず。AndroidManifest.xmlを設定します。以下の設定を入れることによってインターネットへのアクセスを許可します。
<uses-permission android:name="android.permission.INTERNET" />

MainActivity.java
MainActivity.javaでは、onCreateにWebViewのコードを書いていきます。
古いAndroid端末では、WebViewで開いたページのリンクをタップすると、標準ブラウザが立ち上がってしまうのですが。以下のコードで抑制をしています。
mWebView.setWebViewClient(new WebViewClient());
JavaScriptを有効にします。
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
ユーザエージェントを設定します。このコードでは、標準のWebViewのユーザエージェントに追加で独自の文字列を追加しています。
String ua = mWebView.getSettings().getUserAgentString();
ua = ua + " my-android-app";
mWebView.getSettings().setUserAgentString(ua);
キャッシュと履歴をクリアします。
mWebView.clearCache(true);
mWebView.clearHistory();
指定したURLを開きます。
mWebView.loadUrl(top_url);
あとは、アプリがバックグラウンドになった時や、別のActivityが有効になったときのWebViewの処理を入れていきます。
onResume, onPause, onStop, onDestroyの処理です。
もし、この設定を入れないと、たとえばYoutubeなどを再生していて、アプリをバックグラウンドにした時などに音が再生されっぱなしになってしまったりします。必ず入れましょう。
また、WebViewを使っているActivityはできるだけ破棄しておかないと、アプリのクラッシュが発生することがあります。
「問題が発生したため〇〇を終了します」といったエラーメッセージが出て、アプリが強制終了してしまったときには、このあたりを疑ってみると良さそうです。
別のActivityを開くときには、 finish(); でアクティビティスタックを破棄しておくと安心できます。

以下の資料が参考になりました。

図で理解するActivityのスタック
http://techblog.qoncept.jp/?p=102
恵比寿のベンチャーで働くエンジニアのメモ帳|【Android】Intent発行時にActivityスタックをクリアする方法
http://6rats.blog62.fc2.com/blog-entry-107.html
1. アクティビティ - ソフトウェア技術ドキュメントを勝手に翻訳
http://www.techdoctranslator.com/android/guide/activities
Android - Activity のライフサイクル再確認 - Qiita
http://qiita.com/calciolife/items/39b2696a9a03e8591d40
Fragmentのライフサイクルメモ - Androidはワンツーパンチ 三歩進んで二歩下がる
http://sakura-bird1.hatenablog.com/entry/20111207/1323267262

activity_main.xml
activity_main.xmlでは、WebViewのレイアウトを記述します。layout_widthとlayout_heightの設定をmatch_parentとしています。WebViewを最大の幅で表示するという設定です。

dimens.xml
dimens.xmlでは、activity_horizontal_margin, activity_vertical_marginを0dpに設定しています。これでWebViewを余白なしで画面いっぱいに表示することができます。

以下、サンプルコードです。

<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:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">
<WebView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/webView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.yako.samplewebview" >
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".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>
<resources>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">0dp</dimen>
<dimen name="activity_vertical_margin">0dp</dimen>
</resources>
view raw dimens.xml hosted with ❤ by GitHub
package com.example.yako.samplewebview;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
public class MainActivity extends ActionBarActivity {
// mWebViewをprivateに
private WebView mWebView;
// WebViewで開くURLを設定
private static String top_url = "http://takeshiyako.blogspot.jp/";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// レイアウトのリソースを利用
mWebView = (WebView) findViewById(R.id.webView);
// WebViewClientを利用 標準のブラウザの起動を防ぐ
mWebView.setWebViewClient(new WebViewClient());
// JavaScriptを有効
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
// ユーザエージェント設定
String ua = mWebView.getSettings().getUserAgentString();
ua = ua + " my-android-app";
mWebView.getSettings().setUserAgentString(ua);
// キャッシュクリア
mWebView.clearCache(true);
// 履歴をクリア
mWebView.clearHistory();
// URL読み込み
mWebView.loadUrl(top_url);
}
/***
* Activityの「onResume」に基づき開始される
*/
@Override
public void onResume() {
super.onResume();
mWebView.onResume();
}
/***
* Activityが「onPause」になった場合や、Fragmentが変更更新されて操作を受け付けなくなった場合に呼び出される
*/
@Override
public void onPause() {
super.onPause();
mWebView.onPause();
}
/***
* フォアグラウンドでなくなった場合に呼び出される
*/
@Override
public void onStop() {
super.onStop();
mWebView.onPause();
}
/***
* Activityが破棄される時、最後に呼び出される
*/
@Override
public void onDestroy() {
super.onDestroy();
mWebView.destroy();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}