SlideShare une entreprise Scribd logo
1  sur  66
2017年1月21日
わんくま勉強会東京
B.G
※この発言は個人の見解であり、所属する組織
の公式見解ではありません
 HN: B.G
 TwitterID:
 @miu_hiro_(メイン, 仕事だけだったはず
が・・・。)
 @bg1_333(元メイン, 同人関係その他)
 Blog:
 車輪のx発明 ~B.G's Blog~
 (http://bg1.hatenablog.com/)
 言語・環境など:
 C++(とくにC++1x)わかりません
 C#わかりません
 Javaわかりません
 Win32マン
 Androidわかりません
 最近はAndroidも多い
Androidわからないマンが
ブラウザを作ることになった
というお話
 はじめに
 WebView
 URLバー
 ブックマーク
 履歴
 タブブラウザ
 まとめ
 WebView
 https://developer.android.com/reference/android/w
ebkit/WebView.html
 指定されたURLのWebページを読み込み、適切に
表示してくれる。
 単体でも簡易的なWebページ表示には使えるが、
本格的に使う場合は、後述するWebViewClient、
WebChromeClient、WebSettingsなどと組み合わ
せる。
 WebViewClient
 https://developer.android.com/reference/android/w
ebkit/WebViewClient.html
 WebViewのロード中のステータスに対するイベン
トハンドラを持つ。
 WebViewClientを継承した派生クラスオブジェク
トをWebViewにセットすることで、さまざまなイ
ベント処理をカスタマイズできる。
 読み込み開始時
 読み込み終了時
 読み込みURL変更時
 WebChromeClient
 https://developer.android.com/reference/android/w
ebkit/WebChromeClient.html
 これもWebViewに派生クラスをセットする形で使
う。
 こちらは比較的UIに関するイベントなどのカスタ
マイズに使う。
 プログレスバーの更新
 タイトルの取得
 faviconの取得
 WebSettings
 https://developer.android.com/reference/android/w
ebkit/WebSettings.html
 WebViewのさまざまな設定を行うクラス。
 JavaScriptの有効化/無効化
 UserAgentの設定/取得
 shouldOverrideUrlLoading
 https://developer.android.com/reference/android/w
ebkit/WebViewClient.html#shouldOverrideUrlLoadi
ng(android.webkit.WebView, java.lang.String)
 WebViewClientのハンドラメソッド
 読み込みURLが変更された時に、ここに来る。
 リダイレクトでURLが切り替わった時
 Webページ内のリンクをクリックした時
 オーバーライドしないと、Chromeを起動してし
まう問題(後述)
 Zinc #3 一部のサイトでChromeにリダイレクトする動
作を防止
 オーバーライドしないと、Chromeを起動してしまう問題
shouldOverrideUrlLoadingの戻り値
true → WebViewでは処理しない
false → WebViewで処理する
public class CustomWebViewClient extends WebViewClient{
public boolean shouldOverrideUrlLoading(WebView view, String url){
// 必ずWebViewに表示したいので, falseを返す.
return false; // falseを返す.
}
}
 こうすると、Chromeを起動せずにWebViewでロードする。
 EditText
 https://developer.android.com/reference/android/w
idget/EditText.html
 AndroidにはURLバーというViewは無いので、
EditTextを改造する。
 URLバーの更新
 URLを入力するEditTextを配置しただけでは、リ
ンクをクリックしたり、リダイレクトでURLが変
わった時にURLを更新してくれない。
 shouldOverrideUrlLoadingでURLが変わった時、
更新後のURLをsetTextでセットする。
 Zinc #8 リンク先URLをURLバーに反映
// MainActivity.java
protected void onCreate(Bundle savedInstanceState) {
//…
WebView webView = (WebView)findViewById(R.id.webview);
CustomWebViewClient cwvcl = new CustomWebViewClient(this);
// this(MainActivity自身)を渡す.
webView.setWebViewClient(cwvcl);
//…
}
// CustomWebViewClient.java
public class CustomWebViewClient extends WebViewClient{
private Context mContext;
public void CustomWebViewClient(Context context){
mContext = context;
}
public boolean shouldOverrideUrlLoading(WebView view, String url){
if (mContext != null){
EditText urlBar =
(EditText)((MainActivity)mContext).findViewById(R.id.urlBar);
urlBar.setText(url); // 更新後のurlをセット.
}
return false;
}
}
 これでURLが更新される
http://yahoo.co.jp
から
http://m.yahoo.co.jp/
に更新
 HTTPの補完と省略
 現在の一般的なブラウザは、URLバーにいちい
ち”http://”から始まるURLを入力しなくても、
HTTPリクエストとして認識する。loadUrl
は”http://”または”https://”が無いと、正しく読み込
めないので、この部分を補完する必要がある。
 一方、更新時にURLバーにURLを表示する場合
は、”http”の場合は省略する場合が比較的多
い。”http”の除去が必要。
 これらの処理もshouldOverrideUrlLoadingなどで
行う。
 Zinc #9 ロード時のhttp補完および表示時のhttp省略
 URLバーでリターンキー入力でロード
 これまではURLバーの隣にロード用のボタンを用意し、
それを押すとWebページのロードが開始されるような
形にしていた。
 しかし、たいていのWebブラウザには、ロード用ボタ
ンは無く、リターンキー(Enter, 完了)入力だけでロー
ドが開始される。
 これを実現するにはTextView.OnEditorActionListenerを
使う。
 OnEditorActionの中に書くべき処理はいくつかのパターン
があるので注意!
 TextView.OnEditorActionListener
 https://developer.android.com/reference/android/widget/Te
xtView.OnEditorActionListener.html
 Zinc #13 URLバー内でのEnterキーでWebページをロード
public class MainActivity extends Activity implements
View.OnClickListener, TextView.OnEditorActionListener {
protected void onCreate(Bundle savedInstanceState) {
//…
EditText urlBar = (EditText)findViewById(R.id.urlBar);
urlBar.setOnEditorActionListener(this); // EditorActionにthis.
}
public boolean onEditorAction(TextView v, int actionId, KeyEvent
event){
if (actionId == EditorInfo.IME_ACTION_DONE){
EditText urlBar = (EditText) findViewById(R.id.urlbar);
String url = urlBar.getText().toString();
WebView webView = (WebView)
findViewById(R.id.webview);
webView.loadUrl(load);
}
}
}
 これでロード用のボタンは不要。
(右の×ボタンはURLバーの入力文字列をクリアするボタン)
 バックキーで戻る
 バックキーで一つ前のページに戻るには、
onKeyDownのKEYCODE_BACKや
onBackPressedで、webView.canGoBackがtrueの
時に、webView.goBackすればいい。
 Zinc #10 ハードバックキーで前のページに戻る
 ブックマーク機能の大幅縮小(事実上廃止)
 Android5.1以前はBrowser.saveBookmarkで専用ダ
イアログを表示してくれたり、管理もAndroid側
でよろしくやってくれていた。
 Android6からは、これらの便利なメソッドが軒並
み廃止になり、アプリ内でブックマークデータを
管理しなければならなくなった。
 https://developer.android.com/about/versions/marshmall
ow/android-6.0-changes.html#behavior-bookmark-
browser
 Zinc #6 ブックマークDBテーブルへの登録
 AlertDialog.builder
 https://developer.android.com/reference/android/a
pp/AlertDialog.Builder.html
 ダイアログクラス。登録するURLの確認用に使う。
 SQLiteOpenHelper
 https://developer.android.com/reference/android/d
atabase/sqlite/SQLiteOpenHelper.html
 SQLiteのヘルパークラス。これをオーバーライド
して、DBの作成やアップグレードを行う。
public class DBHelper extends SQLiteOpenHelper {
private static final String DB = "zinc1.db";
private static final int DB_VERSION = 1;
private static final String TABLE_BOOKMARK = "bookmark";
private static final String CREATE_TABLE_BOOKMARK = "create table " +
TABLE_BOOKMARK + " ( _id integer primary key autoincrement, name string, url
string);";
private static final String DROP_TABLE_BOOKMARK = "drop table " +
TABLE_BOOKMARK + ";";
public DBHelper(Context context){
super(context, DB, null, DB_VERSION);
}
public void onCreate(SQLiteDatabase db){
try{
db.execSQL(CREATE_TABLE_BOOKMARK);
}
catch(Exception ex){
Log.e("Zinc", ex.toString());
}
}
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion){
db.execSQL(DROP_TABLE_BOOKMARK );
onCreate(db);
}
}
 SQLiteDatabase
 https://developer.android.com/reference/android/d
atabase/sqlite/SQLiteDatabase.html
 ヘルパーから取得したDB本体。これでinsertや
updateを行う。
DBHelper hlpr = new DBHelper(getApplicationContext());
SQLiteDatabase sqlite = hlpr.getWritableDatabase();
ContentValues values = new ContentValues();
values.put("name", strName);
values.put("url", strUrl);
long id = sqlite.insertOrThrow("bookmark", null, values);
 ListView
 https://developer.android.com/reference/android/widget
/ListView.html
 ブックマークや履歴などのURLリストはリストビュー
で表示する。
 単体では使用せず、Adapter系クラスと組み合わせて使
う。
 ArrayAdapter
 https://developer.android.com/reference/android/widget
/ArrayAdapter.html
 実際のリストデータとリストビューの橋渡しをするク
ラス。
 渡されたリストデータをアイテム一つ一つどういうレ
イアウトで表示するかを決定する。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/url_list_item_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView android:id="@+id/url_list_item_name"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<TextView android:id="@+id/url_list_item_url"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>
public class UrlListItem {
public String name; // Webページ名.
public String url; // URL
}
public class UrlListAdapter extends ArrayAdapter<UrlListItem> {
private LayoutInflater inflater;
public UrlListAdapter(Context context, int resource, List<UrlListItem>
objects){
super(context, resource, objects);
inflater =
(LayoutInflater)context.getSystemService(context.LAYOUT_INFLATER_SERVICE);
}
@Override
public View getView(int position, View convertView, ViewGroup parent){
if (convertView == null){
convertView = inflater.inflate(R.layout.url_list_item, null);
}
TextView tvName =
(TextView)convertView.findViewById(R.id.url_list_item_name);
tvName.setText(getItem(position).name);
TextView tvUrl =
(TextView)convertView.findViewById(R.id.url_list_item_url);
tvUrl.setText(getItem(position).url);
return convertView;
}
}
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:id="@+id/bookmarklist"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</ListView>
</LinearLayout>
</LinearLayout>
public class BookmarkActivity extends AppCompatActivity {
public List<UrlListItem> bookmarkList = null;
public ListView lvBookmark = null;
public UrlListAdapter adapter = null
public DBHelper hlpr = null;
public SQLiteDatabase sqlite = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bookmark);
bookmarkList = new ArrayList<UrlListItem>();
adapter = new UrlListAdapter(this, R.layout.url_list_item, bookmarkList);
lvBookmark = (ListView)findViewById(R.id.bookmarklist);
lvBookmark.setAdapter(adapter);
//…
hlpr = new DBHelper(getApplicationContext());
sqlite = hlpr.getReadableDatabase();
Cursor cursor = null;
cursor = sqlite.rawQuery("SELECT * FROM bookmark;", null);
int c = cursor.getCount();
cursor.moveToFirst();
for (int i = 0; i < c; i++){
int _id = cursor.getInt(0); // 0列目は_id.
String name = cursor.getString(1); // 1列目はname.
String url = cursor.getString(2); // 2列目はurl.
UrlListItem item = new UrlListItem();
item.name = name; // item.nameにname.
item.url = url; // item.urlにurl.
bookmarkList.add(item);
cursor.moveToNext();
}
cursor.close();
 メニュー(今回は割愛)でブックマークの登録を選択
 確認用ダイアログ表示
 ブックマークの管理を選択
 ブックマークに登録されている
 履歴も自前DBで管理
 ブックマークと同様、通算の履歴もAndroid6からは、
自前で管理しなければならない。
 WebBackForwardList は通算の履歴ではない
 WebBackForwardList
 https://developer.android.com/reference/android/webki
t/WebBackForwardList.html
 これはWebViewがページ遷移のどの位置にいるかをスタッ
ク状に蓄積しているだけ。
 ページA→ページB→ページC→戻る→戻る
 このとき、 WebBackForwardListに残っているのはページ
Aのみ
 履歴の表示
 ブックマークと同様にListViewでDBから読み込んで表
示する。
 履歴の登録
 どのタイミングで登録すべきかは、おそらく正解
がない。
 いまのところ、おそらくonPageFinishedで登録す
るのが良いと思われる。
 Chromeでは、ロードの途中のどこかで履歴に登
録されている模様だが、詳細は不明。
 onPageStarted
 https://developer.android.com/reference/android/w
ebkit/WebViewClient.html#onPageStarted(android
.webkit.WebView, java.lang.String,
android.graphics.Bitmap)
 WebViewClientのハンドラメソッド
 読み込みが開始された時に、ここに来る。
 loadUrlでロードされた時
 リダイレクトやリンクを開いた時の
shouldOverrideUrlLoadingの後
 ここで履歴DBへの登録をしてしまうと、リダイ
レクトURLをすべて登録してしまうので×
 ここでは読み込んだURLをいったんメンバに保持
しておくだけにしておくのが良いと思われる。
 onPageFinished
 https://developer.android.com/reference/android/webkit
/WebViewClient.html#onPageFinished(android.webkit.
WebView, java.lang.String)
 WebViewClientのハンドラメソッド
 読み込みが終了した時に、ここに来る。
 しかし、なぜか同じURLで2度ここに来ることがある。
 例えばYahooなど
 バグ?JavaScriptのせい?
 そのため、最後にメンバに保持していたURLと同じ
URLで、なおかつ1回目の到着時のみ、履歴DBに登録
するのがベスト(というかベター)という結論に。
public class CustomWebViewClient extends WebViewClient {
private String mStartUrl = “”;
private int count = 0;
@Override
public void onPageStarted(final WebView view, final String url, final
Bitmap favicon) {
mStartUrl = url;
count = 0;
}
@Override
public void onPageFinished(WebView view, String url) {
if (count == 0){
if (mStartUrl.equals(url)){
// 履歴DBに登録
// …
}
}
count++;
}
}
 タブブラウザにしたい
 これまで一つのActivityに一つのWebViewを置いて
ページを表示してきたが、Chromeを始め、ほと
んどのブラウザはタブブラウザが基本となってい
る。
 タブブラウザの機能も標準として用意されている
わけではなく、自前で切り替えや表示の機能を作
らなければならない。
 Chrome Custom Tabsというものも最近出てきた
が、どこまでカスタム出来るか不明なので今後調
査してみようと思う。
 https://developer.chrome.com/multidevice/android/custo
mtabs
 タブ系ビュー(1)
 TabActivity
 https://developer.android.com/reference/android/app/Ta
bActivity.html
 Android3系まで使われていた。
 1つのActivityの中に子Activityをいくつも置くような形
(現在でいうFragment)
 APIレベル13で非推奨
 TabHost
 https://developer.android.com/reference/android/widget/
TabHost.html
 Android3系まで使われていた。
 Layoutの表示/非表示を複数のタブで切り替えるような
使い方。
 Fragmentを入れることはできない?(試してないので不
明)
 主に複数の固定画面切り替えで使う
 APIレベル13(?)辺りで非推奨のはずが、後述の
ActionBar.TABがAPIレベル21で非推奨となり、こっち
は非推奨が撤回された模様(?)
 タブ系ビュー(2)
 ActionBar.Tab
 https://developer.android.com/reference/android/app/Ac
tionBar.Tab.html
 APIレベル11(Android3)から追加
 ActionBarの機能の一部としてタブの機能が追加された。
 中はFragmentなので、画面切り替えとしても使いやす
い。
 しかし、APIレベル21(Android5)から非推奨に。
 タブ系ビュー(3)
 FragmentTabHost
 https://developer.android.com/reference/android/support/v
4/app/FragmentTabHost.html
 Support.v4ライブラリにあるFragment切り替えのできる
TabHost
 使い方はTabHostをベースとしている。
 最初はこれで実装してみたが問題点がいくつも出てきた。
 TabとFragmentを一括管理しており、Fragmentだけを
差し替えることができない。(Fragmentを取得して強引
に削除したら落ちた。)
 1つのTab/Fragmentのセットを削除できない。削除する
ときはすべてのTab/Fragmentのセットを削除してから、
新たに作り直さなければならない。
 Viewが維持されない。Tabを押すたびに画面の生成が行
われ、ロード済みのWebページを表示していた
WebViewも真っ白に。onSavedInstanceで保存していて
も、復元時に再ロードが走ってしまう。
 Tabを追加するたびにTab部分が小さくなり、Tabが多い
とタイトルがほとんど表示できない。
 タブ系ビュー(4)
 PagerTabStrip
 https://developer.android.com/reference/android/support/v4/
view/PagerTabStrip.html
 Support.v4ライブラリにあったみたいだが試してない。
 『こっちの方がよかったのでは』と後悔。
 TabLayout
 https://developer.android.com/reference/android/support/des
ign/widget/TabLayout.html
 Design.Supportライブラリにあるので比較的新しいが試して
ない。
 『今だとこちらがトレンドかも』とさらに後悔。
 BottomNavigationView
 https://developer.android.com/reference/android/support/des
ign/widget/BottomNavigationView.html
 下タブなので却下。
 概念上のタブ
 FragmentTabHostまでで疲弊したので、改めてタブに
ついて考えてみた。
 そもそも、タブ系ビューでないといけないのか。
 Google Chromeは、謎の3DなUIによって切り替えられ
ている。
 サードパーティー製のブラウザやWindows10Mobileな
どはグリッドビューのようなタイル形式でサムネイル
を選択するような形が多い。
 (概念上の)タブごとにWebViewを始めとするViewがの
状態が維持されていれば、タブ系ビューにこだわる必
要は無いのでは。
(概念上の)タブの画面はそれぞれFragmentにして、
タブ切り替え用の一覧画面は専用の特殊な
Fragmentにしよう。
 Fragment
 https://developer.android.com/reference/android/a
pp/Fragment.html
 Activityの中に配置できる子Activityのようなもの
 これを複数配置して画面を切り替えるのが一般的。
 FragmentManager
 https://developer.android.com/reference/android/a
pp/FragmentManager.html
 Activity内のFragment管理。
 FragmentTransaction
 https://developer.android.com/reference/android/a
pp/FragmentTransaction.html
 Fragment操作などを行う。
 add
 https://developer.android.com/reference/android/app/Fr
agmentTransaction.html#add(int,
android.app.Fragment, java.lang.String)
 Fragmentを追加する。
 既に追加済みのFragmentはそのまま残る。
 show/hideで表示/非表示を切り替える。
 show/hideの切り替え時にFragmentライフサイクルは
発生しない
 replace
 https://developer.android.com/reference/android/app/Fr
agmentTransaction.html#replace(int,
android.app.Fragment, java.lang.String)
 Fragmentを置換する。
 既に追加済みのFragmentは消える。
 置換なのでFragmentライフサイクルが発生する。
 起動時に表示する最初のタブ
 FragmentTransaction.addで追加する。
private final String FRAGMENT_TAB_PREFIX_WEB = "web";
private int webFragmentNo = 0;
private FragmentManager fragmentManager = null;
private Map<String, Fragment> fragmentMap = null;
private String currentFragmentTag = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// fragmentMapの作成.
fragmentMap = new HashMap<String, Fragment>();
// 最初のWebフラグメントの追加.
fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction =
fragmentManager.beginTransaction();
String fragmentTag = FRAGMENT_TAB_PREFIX_WEB + webFragmentNo;
WebFragment webFragment = new WebFragment();
fragmentTransaction.add(R.id.content, webFragment, fragmentTag);
fragmentTransaction.commit();
fragmentMap.put(fragmentTag, webFragment);
currentFragmentTag = fragmentTag;
webFragmentNo++
}
 新しいタブの追加
 FragmentTransaction.addで追加する。
 Zinc #34 新しいタブの追加
// メニュー選択時
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.menu_item_add_tab) {
// 他のフラグメントを非表示にしてから, フラグメントを追加し, 表示.
FragmentTransaction fragmentTransaction =
fragmentManager.beginTransaction();
for (Map.Entry<String, Fragment> entry: fragmentMap.entrySet()){
Fragment fragment = entry.getValue();
fragmentTransaction.hide(fragment);
}
String fragmentTag = FRAGMENT_TAB_PREFIX_WEB + webFragmentNo;
WebFragment webFragment = new WebFragment();
fragmentTransaction.add(R.id.content, webFragment, fragmentTag);
fragmentTransaction.show(webFragment);
fragmentTransaction.commit();
fragmentMap.put(fragmentTag, webFragment);
currentFragmentTag = fragmentTag;
webFragmentNo++;
setMenuUrlBar("");
}
return super.onOptionsItemSelected(item);
}
 真っ白な新しいタブが追加された
 タブの切り替えボタン
 メニューにタブ切り替えボタンを用意し、それを
押すと、タブ一覧画面のFragmentを表示する。
 タブ一覧画面
 タブ一覧画面のFragmentにGridViewでタブのサム
ネイルを表示する。
// メニュー選択時
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// 選択されたメニューアイテムごとに振り分ける.
int id = item.getItemId(); // item.getItemIdでidを取得.
if (id == R.id.menu_item_show_tabs) { // タブ一覧の表示.
// 現在表示しているタブのキャプチャを撮影.
if (currentFragmentTag.contains(FRAGMENT_TAG_PREFIX_WEB))
String path = getCacheDir() + "/" + currentFragmentTag + ".jpg
WebFragment webFragment =
(WebFragment)fragmentManager.findFragmentByTag(currentFragmentTag);
View view = webFragment.getView();
captureView(path, view);
}
// tabsFragmentを作成して, タグ名を決めて追加.
TabsFragment tabsFragment = new TabsFragment();
String fragmentTag = FRAGMENT_TAG_PREFIX_TABS;
addFragment(tabsFragment, fragmentTag); // フラグメントの追加.
setMenuUrlBar(""); // setMenuUrlBarでURLバーを空に.
menuItemUrlBar.setVisible(false); // URLバーの非表示.
}
// フラグメントのビューのキャプチャを撮る.
public void captureView(String path, View view){
Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(),
Bitmap.Config.ARGB_8888); // bitmapを作成.
Canvas canvas = new Canvas(bitmap); // bitmapからCanvasオブジェクトcanvasを生成.
view.draw(canvas); // view.drawでcanvasにviewを描画.
FileOutputStream fos = null;
try {
fos = new FileOutputStream(path);
if (fos != null) {
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, fos);
fos.close();
fos = null;
}
}
catch (Exception e) {
Log.d("Zinc:e:", e.toString());
}
finally {
try {
if (fos != null) {
fos.close();
fos = null;
}
}
catch (Exception e) {
Log.d("Zinc:e:", e.toString());
}
}
}
// フラグメントの追加
public void addFragment(Fragment addFragment, String fragmentTag){
// 他のフラグメントを非表示にしてから, フラグメントを追加し, 表示.
FragmentTransaction fragmentTransaction =
fragmentManager.beginTransaction();
for (Map.Entry<String, Fragment> entry: fragmentMap.entrySet()){
Fragment fragment = entry.getValue();
fragmentTransaction.hide(fragment);
}
fragmentTransaction.add(R.id.content, addFragment, fragmentTag);
fragmentTransaction.show(addFragment);
fragmentTransaction.commit();
fragmentMap.put(fragmentTag, addFragment);
currentFragmentTag = fragmentTag;
}
public class TabsFragment extends Fragment implements AdapterView.OnItemClickListener{
// メンバフィールドの定義
private MainActivity mainActivity = null;
private View fragmentView = null;
private GridView tabsGridView = null;
private List<TabsGridItem> tabsGridItemList = null;
private TabsGridAdapter adapter = null;
private Map<String, Fragment> fragmentMap = null;
private final String FRAGMENT_TAG_PREFIX_WEB = "web";
private final String FRAGMENT_TAG_PREFIX_TABS = "tabs";
public TabsFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// タブ一覧を取得して, GridViewで表示.
mainActivity = (MainActivity)getActivity();
// Inflate the layout for this fragment
fragmentView = inflater.inflate(R.layout.fragment_tabs, container, false);
tabsGridView = (GridView)fragmentView.findViewById(R.id.tabsGridView);
tabsGridItemList = new ArrayList<TabsGridItem>();
adapter = new TabsGridAdapter(mainActivity, R.layout.grid_item_tabs, tabsGridItemList);
tabsGridView.setAdapter(adapter);
fragmentMap = mainActivity.getFragmentMap();
addTabsGridItem();
adapter.notifyDataSetChanged();
tabsGridView.setOnItemClickListener(this);
return fragmentView;
}
// グリッドアイテムが選択された時.
public void onItemClick(AdapterView<?> parent, View view, int position, long id){
// 選択されたアイテムの取得.
GridView gridView = (GridView)parent;
TabsGridItem gridItem = (TabsGridItem) gridView.getItemAtPosition(position);
mainActivity.changeFragment(gridItem.tabName);
mainActivity.changeUrl(gridItem.tabName);
mainActivity.removeFragment(FRAGMENT_TAG_PREFIX_TABS);
}
// フラグメントの切り替え
public void changeFragment(String tabName){
// 指定されたtabNameのフラグメントは表示, それ以外は非表示.
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
for (Map.Entry<String, Fragment> entry : fragmentMap.entrySet()) {
String tab = entry.getKey();
Fragment fragment = entry.getValue();
if (tab.equals(tabName)){
fragmentTransaction.show(fragment);
}
else {
fragmentTransaction.hide(fragment);
}
}
fragmentTransaction.commit();
currentFragmentTag = tabName;
}
// フラグメントの削除
public void removeFragment(String tabName){
// tabNameでfragmentを探して, 削除.
Fragment fragment = fragmentManager.findFragmentByTag(tabName);
if (fragment != null) {
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.remove(fragment);
fragmentTransaction.commit();
fragmentMap.remove(tabName);
}
 実際にWebブラウザを作ってみると、WebView以外の部分
がViewや機能として用意されていなかったので、自分で作
り込むのが大変だった。
 ただ、Androidのよく使う機能について、全体的に学べたこ
とは良かった。
 今後もWebブラウザ開発、Androidについての知見を積んで
いきたいとおもった。
 「もっと簡単にできるよ!」「楽にできるよ!」っていう
のがあったら教えていただきたい。

Contenu connexe

Tendances

SOLID principles in practice: the Clean Architecture
SOLID principles in practice: the Clean ArchitectureSOLID principles in practice: the Clean Architecture
SOLID principles in practice: the Clean ArchitectureFabio Collini
 
/etc/network/interfaces について
/etc/network/interfaces について/etc/network/interfaces について
/etc/network/interfaces についてKazuhiro Nishiyama
 
Testing RESTful Webservices using the REST-assured framework
Testing RESTful Webservices using the REST-assured frameworkTesting RESTful Webservices using the REST-assured framework
Testing RESTful Webservices using the REST-assured frameworkMicha Kops
 
Keycloakの実際・翻訳プロジェクト紹介
Keycloakの実際・翻訳プロジェクト紹介Keycloakの実際・翻訳プロジェクト紹介
Keycloakの実際・翻訳プロジェクト紹介Hiroyuki Wada
 
フリーでできるセキュリティWeb編(SQLMあpを楽しもう)
フリーでできるセキュリティWeb編(SQLMあpを楽しもう)フリーでできるセキュリティWeb編(SQLMあpを楽しもう)
フリーでできるセキュリティWeb編(SQLMあpを楽しもう)abend_cve_9999_0001
 
Android audio system(audioflinger)
Android audio system(audioflinger)Android audio system(audioflinger)
Android audio system(audioflinger)fefe7270
 
Testing RESTful web services with REST Assured
Testing RESTful web services with REST AssuredTesting RESTful web services with REST Assured
Testing RESTful web services with REST AssuredBas Dijkstra
 
Introduction to Gstreamer
Introduction to GstreamerIntroduction to Gstreamer
Introduction to GstreamerRand Graham
 
Writing a fast HTTP parser
Writing a fast HTTP parserWriting a fast HTTP parser
Writing a fast HTTP parserfukamachi
 
Keycloakの紹介と最新開発動向
Keycloakの紹介と最新開発動向Keycloakの紹介と最新開発動向
Keycloakの紹介と最新開発動向Yuichi Nakamura
 
Kamailio - SIP Firewall for Carrier Grade Traffic
Kamailio - SIP Firewall for Carrier Grade TrafficKamailio - SIP Firewall for Carrier Grade Traffic
Kamailio - SIP Firewall for Carrier Grade TrafficDaniel-Constantin Mierla
 
[若渴計畫] Challenges and Solutions of Window Remote Shellcode
[若渴計畫] Challenges and Solutions of Window Remote Shellcode[若渴計畫] Challenges and Solutions of Window Remote Shellcode
[若渴計畫] Challenges and Solutions of Window Remote ShellcodeAj MaChInE
 
第4回コンテナ型仮想化勉強会@東京 Oracle Solaris のコンテナ技術「Solaris Zones」
第4回コンテナ型仮想化勉強会@東京 Oracle Solaris のコンテナ技術「Solaris Zones」第4回コンテナ型仮想化勉強会@東京 Oracle Solaris のコンテナ技術「Solaris Zones」
第4回コンテナ型仮想化勉強会@東京 Oracle Solaris のコンテナ技術「Solaris Zones」Kazuyuki Sato
 
Web automation using selenium.ppt
Web automation using selenium.pptWeb automation using selenium.ppt
Web automation using selenium.pptAna Sarbescu
 
C/C++プログラマのための開発ツール
C/C++プログラマのための開発ツールC/C++プログラマのための開発ツール
C/C++プログラマのための開発ツールMITSUNARI Shigeo
 
Spring Security e Spring Boot Aula - 2018
Spring Security e Spring Boot Aula - 2018Spring Security e Spring Boot Aula - 2018
Spring Security e Spring Boot Aula - 2018André Luiz Forchesatto
 
Smooth scrolling in UITableView and UICollectionView
Smooth scrolling in UITableView and UICollectionViewSmooth scrolling in UITableView and UICollectionView
Smooth scrolling in UITableView and UICollectionViewAndrea Prearo
 

Tendances (20)

SOLID principles in practice: the Clean Architecture
SOLID principles in practice: the Clean ArchitectureSOLID principles in practice: the Clean Architecture
SOLID principles in practice: the Clean Architecture
 
/etc/network/interfaces について
/etc/network/interfaces について/etc/network/interfaces について
/etc/network/interfaces について
 
Unit Test
Unit TestUnit Test
Unit Test
 
Testing RESTful Webservices using the REST-assured framework
Testing RESTful Webservices using the REST-assured frameworkTesting RESTful Webservices using the REST-assured framework
Testing RESTful Webservices using the REST-assured framework
 
Keycloakの実際・翻訳プロジェクト紹介
Keycloakの実際・翻訳プロジェクト紹介Keycloakの実際・翻訳プロジェクト紹介
Keycloakの実際・翻訳プロジェクト紹介
 
フリーでできるセキュリティWeb編(SQLMあpを楽しもう)
フリーでできるセキュリティWeb編(SQLMあpを楽しもう)フリーでできるセキュリティWeb編(SQLMあpを楽しもう)
フリーでできるセキュリティWeb編(SQLMあpを楽しもう)
 
Android audio system(audioflinger)
Android audio system(audioflinger)Android audio system(audioflinger)
Android audio system(audioflinger)
 
Testing RESTful web services with REST Assured
Testing RESTful web services with REST AssuredTesting RESTful web services with REST Assured
Testing RESTful web services with REST Assured
 
Introduction to Gstreamer
Introduction to GstreamerIntroduction to Gstreamer
Introduction to Gstreamer
 
Writing a fast HTTP parser
Writing a fast HTTP parserWriting a fast HTTP parser
Writing a fast HTTP parser
 
Keycloakの紹介と最新開発動向
Keycloakの紹介と最新開発動向Keycloakの紹介と最新開発動向
Keycloakの紹介と最新開発動向
 
Kamailio - SIP Firewall for Carrier Grade Traffic
Kamailio - SIP Firewall for Carrier Grade TrafficKamailio - SIP Firewall for Carrier Grade Traffic
Kamailio - SIP Firewall for Carrier Grade Traffic
 
[若渴計畫] Challenges and Solutions of Window Remote Shellcode
[若渴計畫] Challenges and Solutions of Window Remote Shellcode[若渴計畫] Challenges and Solutions of Window Remote Shellcode
[若渴計畫] Challenges and Solutions of Window Remote Shellcode
 
第4回コンテナ型仮想化勉強会@東京 Oracle Solaris のコンテナ技術「Solaris Zones」
第4回コンテナ型仮想化勉強会@東京 Oracle Solaris のコンテナ技術「Solaris Zones」第4回コンテナ型仮想化勉強会@東京 Oracle Solaris のコンテナ技術「Solaris Zones」
第4回コンテナ型仮想化勉強会@東京 Oracle Solaris のコンテナ技術「Solaris Zones」
 
Web automation using selenium.ppt
Web automation using selenium.pptWeb automation using selenium.ppt
Web automation using selenium.ppt
 
Alfresco紹介
Alfresco紹介Alfresco紹介
Alfresco紹介
 
C/C++プログラマのための開発ツール
C/C++プログラマのための開発ツールC/C++プログラマのための開発ツール
C/C++プログラマのための開発ツール
 
Spring Security e Spring Boot Aula - 2018
Spring Security e Spring Boot Aula - 2018Spring Security e Spring Boot Aula - 2018
Spring Security e Spring Boot Aula - 2018
 
Smooth scrolling in UITableView and UICollectionView
Smooth scrolling in UITableView and UICollectionViewSmooth scrolling in UITableView and UICollectionView
Smooth scrolling in UITableView and UICollectionView
 
Lineamientos Globales de Q.A
Lineamientos Globales de Q.ALineamientos Globales de Q.A
Lineamientos Globales de Q.A
 

En vedette

ブラウザはつくるもんじゃない
ブラウザはつくるもんじゃないブラウザはつくるもんじゃない
ブラウザはつくるもんじゃないbg1 333
 
使うっきゃない!iOS9で楽になったAuto Layout!
使うっきゃない!iOS9で楽になったAuto Layout!使うっきゃない!iOS9で楽になったAuto Layout!
使うっきゃない!iOS9で楽になったAuto Layout!SatoTakeshi
 
Bottom navigation
Bottom navigationBottom navigation
Bottom navigationYuki Nanri
 
Android2でも動くMaterialデザイン実装
Android2でも動くMaterialデザイン実装Android2でも動くMaterialデザイン実装
Android2でも動くMaterialデザイン実装Yusuke Konishi
 
【 ITベンチャーを支えるテクノロジー 】チャットワークを支える技術|Chatwork株式会社
【 ITベンチャーを支えるテクノロジー 】チャットワークを支える技術|Chatwork株式会社【 ITベンチャーを支えるテクノロジー 】チャットワークを支える技術|Chatwork株式会社
【 ITベンチャーを支えるテクノロジー 】チャットワークを支える技術|Chatwork株式会社leverages_event
 
【18-C-5】C# で iOS/Androidアプリ開発 - Visual Studio 2015 + Xamarin + MVVMCross -
【18-C-5】C# で iOS/Androidアプリ開発 - Visual Studio 2015 + Xamarin + MVVMCross -【18-C-5】C# で iOS/Androidアプリ開発 - Visual Studio 2015 + Xamarin + MVVMCross -
【18-C-5】C# で iOS/Androidアプリ開発 - Visual Studio 2015 + Xamarin + MVVMCross -ShinichiAoyagi
 
Webエンジニアなら抑えておきたい最近のOSS事情
Webエンジニアなら抑えておきたい最近のOSS事情Webエンジニアなら抑えておきたい最近のOSS事情
Webエンジニアなら抑えておきたい最近のOSS事情Atsushi Nakatsugawa
 

En vedette (7)

ブラウザはつくるもんじゃない
ブラウザはつくるもんじゃないブラウザはつくるもんじゃない
ブラウザはつくるもんじゃない
 
使うっきゃない!iOS9で楽になったAuto Layout!
使うっきゃない!iOS9で楽になったAuto Layout!使うっきゃない!iOS9で楽になったAuto Layout!
使うっきゃない!iOS9で楽になったAuto Layout!
 
Bottom navigation
Bottom navigationBottom navigation
Bottom navigation
 
Android2でも動くMaterialデザイン実装
Android2でも動くMaterialデザイン実装Android2でも動くMaterialデザイン実装
Android2でも動くMaterialデザイン実装
 
【 ITベンチャーを支えるテクノロジー 】チャットワークを支える技術|Chatwork株式会社
【 ITベンチャーを支えるテクノロジー 】チャットワークを支える技術|Chatwork株式会社【 ITベンチャーを支えるテクノロジー 】チャットワークを支える技術|Chatwork株式会社
【 ITベンチャーを支えるテクノロジー 】チャットワークを支える技術|Chatwork株式会社
 
【18-C-5】C# で iOS/Androidアプリ開発 - Visual Studio 2015 + Xamarin + MVVMCross -
【18-C-5】C# で iOS/Androidアプリ開発 - Visual Studio 2015 + Xamarin + MVVMCross -【18-C-5】C# で iOS/Androidアプリ開発 - Visual Studio 2015 + Xamarin + MVVMCross -
【18-C-5】C# で iOS/Androidアプリ開発 - Visual Studio 2015 + Xamarin + MVVMCross -
 
Webエンジニアなら抑えておきたい最近のOSS事情
Webエンジニアなら抑えておきたい最近のOSS事情Webエンジニアなら抑えておきたい最近のOSS事情
Webエンジニアなら抑えておきたい最近のOSS事情
 

Similaire à Androidアプリ本格開発入門 webブラウザ編

Mongo db使ってみよう
Mongo db使ってみようMongo db使ってみよう
Mongo db使ってみようOda Shinsuke
 
データマイニング+WEB勉強会資料第6回
データマイニング+WEB勉強会資料第6回データマイニング+WEB勉強会資料第6回
データマイニング+WEB勉強会資料第6回Naoyuki Yamada
 
cocos2d-xにおけるBox2Dの利用方法および便利なツール
cocos2d-xにおけるBox2Dの利用方法および便利なツールcocos2d-xにおけるBox2Dの利用方法および便利なツール
cocos2d-xにおけるBox2Dの利用方法および便利なツールTomoaki Shimizu
 
DEV-010_エンプラ系業務 Web アプリ開発に効く! 実践的 SPA 型モダン Web アプリ開発の選択手法
DEV-010_エンプラ系業務 Web アプリ開発に効く! 実践的 SPA 型モダン Web アプリ開発の選択手法DEV-010_エンプラ系業務 Web アプリ開発に効く! 実践的 SPA 型モダン Web アプリ開発の選択手法
DEV-010_エンプラ系業務 Web アプリ開発に効く! 実践的 SPA 型モダン Web アプリ開発の選択手法decode2016
 
Android Studioの魅力
Android Studioの魅力Android Studioの魅力
Android Studioの魅力Keiji Ariyama
 
Inside mobage platform
Inside mobage platformInside mobage platform
Inside mobage platformToru Yamaguchi
 
RxDataSourceをNSDiffableDataSourceへ置き換える際のTips集紹介
RxDataSourceをNSDiffableDataSourceへ置き換える際のTips集紹介RxDataSourceをNSDiffableDataSourceへ置き換える際のTips集紹介
RxDataSourceをNSDiffableDataSourceへ置き換える際のTips集紹介Fumiya Sakai
 
WordPress3.0 新デフォルトテーマ Twenty Ten 大解剖! ~秋バージョン~
WordPress3.0 新デフォルトテーマ Twenty Ten 大解剖! ~秋バージョン~WordPress3.0 新デフォルトテーマ Twenty Ten 大解剖! ~秋バージョン~
WordPress3.0 新デフォルトテーマ Twenty Ten 大解剖! ~秋バージョン~hokori matu
 
jQuery Mobile(開発編)勉強会資料
jQuery Mobile(開発編)勉強会資料jQuery Mobile(開発編)勉強会資料
jQuery Mobile(開発編)勉強会資料Nobumasa Ura
 
D3js入門 - Code for Kobe 可視化勉強会資料
D3js入門 - Code for Kobe 可視化勉強会資料D3js入門 - Code for Kobe 可視化勉強会資料
D3js入門 - Code for Kobe 可視化勉強会資料充彦 保田
 
node+socket.io+enchant.jsでチャットゲーを作る
node+socket.io+enchant.jsでチャットゲーを作るnode+socket.io+enchant.jsでチャットゲーを作る
node+socket.io+enchant.jsでチャットゲーを作るKiyoshi SATOH
 
Webフロントエンド開発の最新トレンド - HTML5, モバイル, オフライン
Webフロントエンド開発の最新トレンド - HTML5, モバイル, オフラインWebフロントエンド開発の最新トレンド - HTML5, モバイル, オフライン
Webフロントエンド開発の最新トレンド - HTML5, モバイル, オフラインShumpei Shiraishi
 
Groovyで楽にSQLを実行してみよう
Groovyで楽にSQLを実行してみようGroovyで楽にSQLを実行してみよう
Groovyで楽にSQLを実行してみようAkira Shimosako
 
html5j.orgがHTML5+JavaScriptで Metro Style アプリを作ってみた
html5j.orgがHTML5+JavaScriptで Metro Style アプリを作ってみた html5j.orgがHTML5+JavaScriptで Metro Style アプリを作ってみた
html5j.orgがHTML5+JavaScriptで Metro Style アプリを作ってみた Shumpei Shiraishi
 
CodeIgniterによるPhwittr
CodeIgniterによるPhwittrCodeIgniterによるPhwittr
CodeIgniterによるPhwittrkenjis
 
【de:code 2020】 「あつまれ フロントエンドエンジニア」 Azure Static Web Apps がやってきた
【de:code 2020】 「あつまれ フロントエンドエンジニア」 Azure Static Web Apps がやってきた【de:code 2020】 「あつまれ フロントエンドエンジニア」 Azure Static Web Apps がやってきた
【de:code 2020】 「あつまれ フロントエンドエンジニア」 Azure Static Web Apps がやってきた日本マイクロソフト株式会社
 

Similaire à Androidアプリ本格開発入門 webブラウザ編 (20)

Mongo db使ってみよう
Mongo db使ってみようMongo db使ってみよう
Mongo db使ってみよう
 
Mongodb
MongodbMongodb
Mongodb
 
データマイニング+WEB勉強会資料第6回
データマイニング+WEB勉強会資料第6回データマイニング+WEB勉強会資料第6回
データマイニング+WEB勉強会資料第6回
 
cocos2d-xにおけるBox2Dの利用方法および便利なツール
cocos2d-xにおけるBox2Dの利用方法および便利なツールcocos2d-xにおけるBox2Dの利用方法および便利なツール
cocos2d-xにおけるBox2Dの利用方法および便利なツール
 
DEV-010_エンプラ系業務 Web アプリ開発に効く! 実践的 SPA 型モダン Web アプリ開発の選択手法
DEV-010_エンプラ系業務 Web アプリ開発に効く! 実践的 SPA 型モダン Web アプリ開発の選択手法DEV-010_エンプラ系業務 Web アプリ開発に効く! 実践的 SPA 型モダン Web アプリ開発の選択手法
DEV-010_エンプラ系業務 Web アプリ開発に効く! 実践的 SPA 型モダン Web アプリ開発の選択手法
 
Android Studioの魅力
Android Studioの魅力Android Studioの魅力
Android Studioの魅力
 
Inside mobage platform
Inside mobage platformInside mobage platform
Inside mobage platform
 
RxDataSourceをNSDiffableDataSourceへ置き換える際のTips集紹介
RxDataSourceをNSDiffableDataSourceへ置き換える際のTips集紹介RxDataSourceをNSDiffableDataSourceへ置き換える際のTips集紹介
RxDataSourceをNSDiffableDataSourceへ置き換える際のTips集紹介
 
WordPress3.0 新デフォルトテーマ Twenty Ten 大解剖! ~秋バージョン~
WordPress3.0 新デフォルトテーマ Twenty Ten 大解剖! ~秋バージョン~WordPress3.0 新デフォルトテーマ Twenty Ten 大解剖! ~秋バージョン~
WordPress3.0 新デフォルトテーマ Twenty Ten 大解剖! ~秋バージョン~
 
WordPress と Bootstrap
WordPress と BootstrapWordPress と Bootstrap
WordPress と Bootstrap
 
jQuery Mobile(開発編)勉強会資料
jQuery Mobile(開発編)勉強会資料jQuery Mobile(開発編)勉強会資料
jQuery Mobile(開発編)勉強会資料
 
D3js入門 - Code for Kobe 可視化勉強会資料
D3js入門 - Code for Kobe 可視化勉強会資料D3js入門 - Code for Kobe 可視化勉強会資料
D3js入門 - Code for Kobe 可視化勉強会資料
 
node+socket.io+enchant.jsでチャットゲーを作る
node+socket.io+enchant.jsでチャットゲーを作るnode+socket.io+enchant.jsでチャットゲーを作る
node+socket.io+enchant.jsでチャットゲーを作る
 
Webフロントエンド開発の最新トレンド - HTML5, モバイル, オフライン
Webフロントエンド開発の最新トレンド - HTML5, モバイル, オフラインWebフロントエンド開発の最新トレンド - HTML5, モバイル, オフライン
Webフロントエンド開発の最新トレンド - HTML5, モバイル, オフライン
 
Groovyで楽にSQLを実行してみよう
Groovyで楽にSQLを実行してみようGroovyで楽にSQLを実行してみよう
Groovyで楽にSQLを実行してみよう
 
JSDoc ToolKit
JSDoc ToolKitJSDoc ToolKit
JSDoc ToolKit
 
html5j.orgがHTML5+JavaScriptで Metro Style アプリを作ってみた
html5j.orgがHTML5+JavaScriptで Metro Style アプリを作ってみた html5j.orgがHTML5+JavaScriptで Metro Style アプリを作ってみた
html5j.orgがHTML5+JavaScriptで Metro Style アプリを作ってみた
 
ASP.NET MVC Part 2
ASP.NET MVC Part 2ASP.NET MVC Part 2
ASP.NET MVC Part 2
 
CodeIgniterによるPhwittr
CodeIgniterによるPhwittrCodeIgniterによるPhwittr
CodeIgniterによるPhwittr
 
【de:code 2020】 「あつまれ フロントエンドエンジニア」 Azure Static Web Apps がやってきた
【de:code 2020】 「あつまれ フロントエンドエンジニア」 Azure Static Web Apps がやってきた【de:code 2020】 「あつまれ フロントエンドエンジニア」 Azure Static Web Apps がやってきた
【de:code 2020】 「あつまれ フロントエンドエンジニア」 Azure Static Web Apps がやってきた
 

Plus de bg1 333

はじめての転職
はじめての転職はじめての転職
はじめての転職bg1 333
 
Windows 10 on ARM やるの?やらないの?どっちなんだい!
Windows 10 on ARM やるの?やらないの?どっちなんだい!Windows 10 on ARM やるの?やらないの?どっちなんだい!
Windows 10 on ARM やるの?やらないの?どっちなんだい!bg1 333
 
MADOSMAにSIMを挿してみた
MADOSMAにSIMを挿してみたMADOSMAにSIMを挿してみた
MADOSMAにSIMを挿してみたbg1 333
 
MSCCに参加してみた
MSCCに参加してみたMSCCに参加してみた
MSCCに参加してみたbg1 333
 
Azure mobileserviceを使ってみた
Azure mobileserviceを使ってみたAzure mobileserviceを使ってみた
Azure mobileserviceを使ってみたbg1 333
 
とあるMvnoキャリアを支える技術(ガラケーからスマホへの移行)
とあるMvnoキャリアを支える技術(ガラケーからスマホへの移行)とあるMvnoキャリアを支える技術(ガラケーからスマホへの移行)
とあるMvnoキャリアを支える技術(ガラケーからスマホへの移行)bg1 333
 

Plus de bg1 333 (6)

はじめての転職
はじめての転職はじめての転職
はじめての転職
 
Windows 10 on ARM やるの?やらないの?どっちなんだい!
Windows 10 on ARM やるの?やらないの?どっちなんだい!Windows 10 on ARM やるの?やらないの?どっちなんだい!
Windows 10 on ARM やるの?やらないの?どっちなんだい!
 
MADOSMAにSIMを挿してみた
MADOSMAにSIMを挿してみたMADOSMAにSIMを挿してみた
MADOSMAにSIMを挿してみた
 
MSCCに参加してみた
MSCCに参加してみたMSCCに参加してみた
MSCCに参加してみた
 
Azure mobileserviceを使ってみた
Azure mobileserviceを使ってみたAzure mobileserviceを使ってみた
Azure mobileserviceを使ってみた
 
とあるMvnoキャリアを支える技術(ガラケーからスマホへの移行)
とあるMvnoキャリアを支える技術(ガラケーからスマホへの移行)とあるMvnoキャリアを支える技術(ガラケーからスマホへの移行)
とあるMvnoキャリアを支える技術(ガラケーからスマホへの移行)
 

Androidアプリ本格開発入門 webブラウザ編