iOS開発者の為のAndroid開発 思い出しメモ[随時更新中]


## 環境
>開発環境 Android Studio 0.3.2
Androidのバージョン 4.0

## 基礎
###Activityとは？
iOSでいうとViewController。画面。

### Fragmentとは？
簡単に言うとActivity内に入れられるActivityがFragment。
タブやタブレット用のレイアウトで使用する。
※Android3.0で導入されたがプラグインを入れることで2系でも使えるらしい

Activityと違いContextは継承してない。Contextを使いたい場合はgetActivity()する。ただ、onCreateViewした段階ではActivityが生成されておらずgetActivity()すると落ちるので注意。onActivityCreated()で行うといい。
また、findViewById()も実装されていないのでinflaterで取得したviewまたはgetView()を使うと良い。
同一クラスのFragmentをActivityに複数追加した場合、getActivity()からfindViewById()すると常に最初にセットしたFragmentのViewが返されてしまうのでinflaterで取得したviewまたはgetView()を使ってfindViewById()したほうがいい。

```java:

    // メモ FragmentがViewに関連付けされた時に呼ばれる
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.figure_list_fragment, container, false);
        return view;
    }

    @Override
    public void onActivityCreated (Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        ListView listView = (ListView) getView().findViewById(R.id.listView);
        listView.setAdapter(new FigureListAdapter(getActivity()));
    }
```

iOSでは、ViewControllerのviewに別のViewControllerのviewをaddSubViewすることで実現できる

### Fragmentにレイアウトを設定する

onCreateViewで返すViewのレイアウトが設定されます。

```java:
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        View view = inflater.inflate(R.layout.fragment_music_list, container, false);

        return view;
    }
```

###Activityのライフサイクル
こちらを参考にさせていただきました。

 -アクティビティのライフサイクル
http://www.javadrive.jp/android/activity/index2.html

また、Activity、Fragmentのライフサイクル、復元の仕組みについてよくまとめられている以下のサイトはオススメです。
- 知らずに作って大丈夫？Androidの基本的なライフサイクルイベント31選
http://www.atmarkit.co.jp/ait/articles/1604/04/news011.html

### Intent(インテント)とは
Activityを起動する仕組みです。(アクティビティアクション)
クラスを指定してインテントを送ったり(明示的インテント)機能を指定してインテントを送る(暗黙的インテント)

画面が戻った時にインテントで値を受け取ることもできます。

参考
[Androidで、起動させるActivityに値を渡す方法 - mucchinのAndroid戦記](http://android.roof-balcony.com/intent/putextra/)

また、電池容量が少なくなったなどを伝えるためにも使われます。(ブロードキャストアクション)

#### Activityへ画面遷移 (アクティビティアクションで明示的インテントの例)

Intentを送る側

~~~java:HoveActivity
Intent intent = new Intent(this, MyWebActivity.class);

intent.putExtra(MyWebActivity.EXTRA_URL, "https://www.google.co.jp/");
startActivity(intent);
~~~

Intentを受け取る側

~~~java:MyWebActivity
// インテント用
public static final String EXTRA_URL = "EXTRA_URL";

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

        Intent intent = getIntent();
        String url = intent.getStringExtra(EXTRA_URL);
}

~~~

TwitterやFacebook、Google+に共有する場合(暗黙的インテント)
http://qiita.com/ux_design_tokyo/items/96774c11026e8a321f84

### タスクとは
Activityを管理するスタック構造のことです。

HTMLに例えるとリンク先に移動する時に新しいウィンドウで開くのか、このウィンドウに開くのかといった制御です。これにより戻るボタンを押した時の挙動などがが変わります。

タスクはインテントに渡すフラグやマニュフェストファイルのlaunchModeで指定できます。

結構複雑なのでここで全て説明するのは難しいです。
詳しくは以下の本にかかれています。

[Google Androidプログラミング入門 ](http://www.amazon.co.jp/Google-Android%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E5%85%A5%E9%96%80-%E6%94%B9%E8%A8%822%E7%89%88-%E6%B1%9F%E5%B7%9D%E5%B4%87/dp/4048860682/ref=dp_ob_image_bk
) 
 第２章 アプリケーションの基礎 2.1アプリケーションとタスク 

## 実装系

### JSONを取得する

こちらを参考にさせていただきました。

-JSONをパース（解析）する - TechBooster 
http://techbooster.org/android/application/1645/

※上記で実装するよりも以下のAndroidアプリのアーキテクチャに習ってRetrofitなどを使ったほうがよさそうです
https://developer.android.com/topic/libraries/architecture/guide.html


#### 注意点として

- ネット接続する場合はパーミッションを追加する必要がある
AndroidManifest.xmlに以下を追加する

```xml:AndroidManifest.xml
  <uses-permission android:name="android.permission.INTERNET"/>
```

- メインスレッドで通信処理をするとエラーになってしまう
別スレッドで実行

```java:
        // スレッド起動
        (new Thread(new Runnable() {
            @Override
            public void run() {
		// ここで処理
        })).start();
```

- 自己証明書(オレオレ証明書)を利用する場合は割りと面倒な処理が必要そう

### ActionBarに戻るボタン(Up)を表示する方法

> 2016年2月11日追記
> **そもそもモダンなアプリを作る場合はActionBarではなくAndroid5.0で導入されたToolBarを使ったほうがいいです。**
> 
> AppCompat v21を使って5.0より前の端末にも取り入れることができます。
> http://googledevjp.blogspot.jp/2014/11/appcompat-v21-lollipop.html
> 
> 参考
> http://qiita.com/kobakei/items/f17019f8b0a88c8e57f4
> http://qiita.com/suzukihr/items/96b62d7ae758b09bcabc


AndroidManufestで親のActivityを指定する必要があります。
以下の公式ドキュメントが参考になりました。

- Providing Up Navigation
http://developer.android.com/training/implementing-navigation/ancestral.html

### Getter、Setterについて
Getter、Setterを使うメリットよりソースコードが増えるデメリットが多く感じたので必要ない場合は書かないことにしました。
publicの変数にしています。


※Getter、Setterをメリットについて参考

- オブジェクト指向プログラムで
getter/setterメソッドを使わなければならない
10の理由
http://fukumori.org/oo/why_use_getters_and_setters_j.html

### リストを表示する
長くなりそうなので別にまとめました
[Androidでリストを表示する](http://qiita.com/ux_design_tokyo/items/5dfd3ddd49dedbb2b1dd)

### ダイアログを表示する
長くなりそうなので別にまとめました
[DialogFragmentを使ってダイアログを表示する](http://qiita.com/ux_design_tokyo/items/61ca074566d1570b37d3)

### 汎用的な通信クラスを作る
長くなりそうなので別にまとめました
[[Android]AsyncTaskLoaderを使い複数通信を実装する](http://qiita.com/ux_design_tokyo/items/d07bc5953b7611ce7523)

※上記で実装するよりも以下のAndroidアプリのアーキテクチャに習ってRetrofitなどを使ったほうがよさそうです
https://developer.android.com/topic/libraries/architecture/guide.html

### ファイル操作
こちらを参考にさせていただきました
ファイルの作成・削除・移動 - http://javatechnology.net/java/file-create-delete-move/

### Activityをfinish()した時に２つ前のActivityまで戻りたい

TopActivity → MusicActivity → MusicDoneActivity
と画面遷移してMusicDoneActivityからTopActivityまで戻りたい場合

#### 方法1 ※なぜかこの方法はうまくいきませんでした

AndroidManufest.xmlのMusicActivityに「finishOnTaskLaunch」
を指定するとMusicActivityを離れた時にMusicActivityがfinishされるようになります。ただ、どんな画面遷移でもMusicActivityはfinishするようになるので注意

~~~xml:AndroidManifest.xml
        <activity
            android:name="MusicActivity"
            android:finishOnTaskLaunch="true"
            android:screenOrientation="portrait"/>
~~~

#### 方法2
MusicDoneActivityへ遷移する時に自信(MusicActivity)をfinish()する

~~~java:MusicActivity.java
Intent intent = new Intent(this, MusicDoneActivity.class);
startActivity(intent);
finish();
~~~


#### 方法3

TopActivityへのintentを作ってフラグに「FLAG_ACTIVITY_CLEAR_TOP」を設定する。

~~~java:MusicDoneActivity.java
Intent intent = new Intent(getApplication(), TopActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
~~~

参考

- AndroidでActivityのスタックを削除する方法

http://9ensan.com/blog/smartphone/android/android-activity-stack-delete/

## レイアウト

Androidのレイアウトで１番使うのはRelativeLayoutだと思います。


参考

- LinearLayoutとRelativeLayoutの使い方をまとめてみた

http://d.hatena.ne.jp/Korsakov/20110131/1296504108

- レイアウト（９）-RelativeLayout（相対的位置にウィジェットの配置）をマスターする。 

http://ichitcltk.hustle.ne.jp/gudon/modules/pico_rd/index.php?content_id=112

### 真ん中が可変のレイアウト

RelativeLayoutにして"layout_alignParentLeft"や”layout_toRightOf”、"layout_alignParentRight"を使って実現できます

![kobito.1385980193.689455.png](https://qiita-image-store.s3.amazonaws.com/0/27793/5a213def-afe7-922c-a97d-84476c55f359.png "kobito.1385980193.689455.png")

```xml:
<?xml version="1.0" encoding="utf-8"?>

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="match_parent">

    <RelativeLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content">

        <ImageView
            android:layout_width="46dp"
            android:layout_height="77dp"
            android:id="@+id/figureImageView"
            android:layout_alignParentLeft="true"
            android:layout_centerVertical="true"
            android:background="#0a2aff" />

        <LinearLayout
            android:orientation="vertical"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginRight="140dp"
            android:layout_toRightOf="@id/figureImageView"
            android:layout_centerVertical="true">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textAppearance="?android:attr/textAppearanceMedium"
                android:ellipsize="end"
                android:maxLines="2"
                android:text="フィギュア名"
                android:id="@+id/figureNameTextView" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textAppearance="?android:attr/textAppearanceSmall"
                android:text="メーカー"
                android:id="@+id/makerTextView" />
        </LinearLayout>

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="ダウンロード"
            android:id="@+id/button"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            />

    </RelativeLayout>

</FrameLayout>

```

### dpi、dp(dip)、pxについて
dpiは1inch幅のpx数


例)


> Xperia Zは1920x1080pxで5inch(対角線)
横幅は2.4513inchになる。
1080px / 2.4513inchで 440.58dpi

> 横幅2.4513inchの計算式
1080^2 + 1920^2 = x^2
x = 2202.90717008
5:W = 2202.90717008:1080
W = 2.4513061




160dpiの時1px=1dp 
density(1dpあたりのpx数) = dpi / 160

ldpiは120dpiで1dp=0.75px
mdpiは160dpiで1dp=1px
hdpは240dpiで1dp=1.5px
xhdpiは320dpiで1dp=2px 720x1280px 5inchなど
xxhdpiは480dpiで1dp=3px 1080x1920px 5inchなど

例)
> xhdpiに60pxの画像を入れたら30dp。xxhdpiに60pxの画像を入れたら20dp。

### dpについて
1dpはiOSのコード上の1pxに似ています。
160dpiの時、1dpは1pxですが、iPhoneのdpiは163dpiで実際の1pxはコード上の1pxです。
xhdpiの320dpiの時、1dpは2pxです。iPhone5は326dpiで実際の2pxがコード上の1pxとなっています。


### ActionBarのデザインを変更する

公式ドキュメントが分かりやすかったです
https://developer.android.com/training/basics/actionbar/styling.html

アクションバーのスタイル設定 - もぐら塚から山を作ろう(・∀・)
http://molehill.mole-kingdom.com/opencms/export/sites/default/translate/Android/TrainingDoc/gettingstarted/actionbar/styling/

選択状態のタブの線の色はxmlで指定するものだと思い込んでましたが、画像でした。以下のサイトで画像を作成できます。公式サイトからリンクがあったので公式っぽいです。

http://jgilfelt.github.io/android-actionbarstylegenerator/#name=example&compat=holo&theme=light&actionbarstyle=solid&texture=0&hairline=0&neutralPressed=1&backColor=E4E4E4%2C100&secondaryColor=D6D6D6%2C100&tabColor=33B5E5%2C100&tertiaryColor=F2F2F2%2C100&accentColor=33B5E5%2C100&cabBackColor=FFFFFF%2C100&cabHighlightColor=33B5E5%2C100

## アプリの設計について
Googleがとてもいいアーキテクチャを提案しています。
2017年6月現在、これに従って設計すれば間違いなさそうです。
https://developer.android.com/topic/libraries/architecture/guide.html


## 開発環境系
### メソッドの一覧をAndroid Studioで表示する
左のツールバーでクラスを選択 > 設定アイコン > Show Membersにチェック

または

View > ToolWindows > Structue

### Android Studioが実機(端末)を認識しない
Android Studioを起動し直したら直りました

### Android Studioでメソッドの呼び出し元を表示する
メソッドを選択 > Navigate > Call Hierarchy

### Android Studioのキー配置を変更する
Android Studioのキー配置はXcodeに慣れている人にとっては分かりづらい
Android Studio > Preferences > Keymap > 
Copyを押して自分のキー配列を作りましょう
![kobito.1385427408.400310.png](https://qiita-image-store.s3.amazonaws.com/0/27793/696b1e0f-f411-5c66-d27c-87a7a52d7b36.png "kobito.1385427408.400310.png")


以下の変更だけでだいぶ使いやすくなりました

Main menu > Run => コマンド + R
Main menu > Navigate > Back => コマンド + [
> ↑日本語キーボードだからか コマンド + [を押すと コマンド + ]と表示された

Main menu > Navigate > Forward => コマンド + ]
> ↑日本語キーボードだからかコマンド + ]を押すと コマンド + バックスラッシュと表示された

 ※ 日本語キーボードが英字キーボードとして認識されてしまう場合があるAndroidStudioのバグのようです
http://youtrack.jetbrains.com/issue/IDEA-63779

このよくわからないマークはオプションだった
![kobito.1385428639.093844.png](https://qiita-image-store.s3.amazonaws.com/0/27793/fb92d680-e017-1f2d-71b3-4a6f0afc7530.png "kobito.1385428639.093844.png")

### Android Studio で全ファイルから文字列検索(grep)

プロジェクトを選択 > 右クリック > Find in Path…

参考
- [Android Studio] プロジェクトのすべてのファイルから文字列を検索する
http://rakuishi.com/androidsdk/5801/

### Android Studioの便利なショートカット
コマンド + E 最近使ったファイルへの移動
コマンド + N GetterやSetterなどの自動生成

参考
Android Studio最速入門～効率的にコーディングするための使い方
http://gihyo.jp/dev/serial/01/android_studio/0011

## アプリの登録(apk作成)

### 証明書作成
以下を参考にさせて頂きました

- AndroidMarketに公開するためにアプリに署名を行う
http://techbooster.org/android/environment/1445/

### Android StudioでApkの作成

以下を参考にさせて頂きました

- Android Studioでapkを作ってみた
http://d.hatena.ne.jp/eholic/20130529/p1

### Google Play Consoleに登録

以下を参考にさせて頂きました

- Google Play での配布
http://docs.monaca.mobi/ja/manual/deploy/google_play/google_play/

## その他

・画像のダミーデータが作れる便利なサイト

http://placehold.jp/