ラベル Android Developersサンプル の投稿を表示しています。 すべての投稿を表示
ラベル Android Developersサンプル の投稿を表示しています。 すべての投稿を表示

2015年6月15日月曜日

GoogleサンプルでAndroidアプリを学ぶ(MediaEffects)

GoogleサンプルでAndroidアプリを学ぶ(MediaEffects)

[開発環境]
 Android Studio
[使用したサンプル]
 MediaEffects
[機能]
画像の効果

※Logはなしとしました。
 よって、MainActivityのextendsはFragmentActivityとしました。

なんか1行ずつ分からないので調べていると時間がかかりますが、
意味を理解しながらでないと意味がないと思うので、少しずつ調べていきたいと思います。
Open GL関係は分からないことだらけなので次回にしたいと思います。


フォルダ構成をサンプルと合わせる

ソースが置いてあるフォルダをサンプルと同じApplicationにしたら
ビルドできなくなりました。以下の2つをすることでビルドできました。

  1. settings.gradleで
    include ‘app’ -> include ‘Application’
  2. Build -> clean Project
  3. RUN

savedInstanceState

今までonCreateにあるsavedInstanceStateをあまり気にせずにやっていました。
調べてみるとsavedInstanceStateは前回終了時の状態を保持する変数で最初は、nullが格納されているということ。
ということで以下のように最初の起動のときだけのような処理が必要っぽい。

if (savedInstanceState == null) {}

せっかくなので、もう少し調べてみるとsavedInstanceStateは、superのonCreateにも
渡している。ここでsuperはextendsした親のクラスで親のクラスのonCreateも同様に処理するというようにしている。
これがないとこのクラスのonCreateしか処理されなくなり、よくないらしい。
(具体的な理由は見つかりませんでした。)

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

onSaveInstanceState(Bundle outState)

自分のアプリに戻ったときに、前の状態には自動で戻れないので、その状態を意識的に保存する必要がある。STATE_CURRENT_EFFECTという文字列に
現在のEffectの値を入れておく。

その逆にSTATE_CURRENT_EFFECTという文字列から値を取り出すには、
getInt(STATE_CURRENT_EFFECT)。

private static final String STATE_CURRENT_EFFECT = "current_effect";
@Override
public void onSaveInstanceState(Bundle outState)
{
  outState.putInt(STATE_CURRENT_EFFECT, mCurrentEffect);
}

containsKey

特定のキーが含まれているかを確認するメソッド。
含まれていればTrue。

Fragmentのライフサイクル

何回かFragmentをやってきてましたが、少しふみこんで調べてみたところ最低でも以下3つは必要と
記載されてましたが、サンプルを見るとonCreate()とonCreateView()しかないのですが、動いてはいます。

onCreate()
onCreateView()
onPause()

参考
http://www.techdoctranslator.com/android/guide/activities/fragments

Open GLのエラー

AVD Managerのエミュレータで実行していたときに以下のようなエラーがでてハマりましたが、
実機を使うことで解決しました。
一旦、実機で試すことにします。

06-14 10:50:19.598    3848-3863/com.example.android.mediaeffects E/AndroidRuntime﹕ FATAL EXCEPTION: GLThread 167
    Process: com.example.android.mediaeffects, PID: 3848
    java.lang.IllegalArgumentException: No config chosen
            at android.opengl.GLSurfaceView$BaseConfigChooser.chooseConfig(GLSurfaceView.java:869)
            at android.opengl.GLSurfaceView$EglHelper.start(GLSurfaceView.java:1023)
            at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1400)
            at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1239)

メニューがでない

なぜかメニューがでないので調べたところ以下の2点の修正が必要でした。
1. MainActivityのextendsがFragmentになっていた。
 ActionBarActivityがdeprecatedだったのでFragmentActivityにしていたのが
 問題であり、以下にあるようにAppCompatActivityにする必要があった。

https://developer.android.com/intl/ja/reference/android/support/v7/app/ActionBarActivity.html
2. styles.xmlでThemeがAppCompatになっていなかったので以下のように修正。

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
</style>
    <!-- Activity themes -->
<!--
    <style name="Theme.Base" parent="android:Theme.Light" />
    <style name="Theme.Sample" parent="Theme.Base" />
    <style name="AppTheme" parent="Theme.Sample" />   -->

その他

setHasOptionsMenu

Fragment でメニューを追加する場合は必ず setHasOptionsMenu(true)をつける必要があるらしい。おまじない。
onCreateで定義。

@Nullable

onCreateViewをオーバーライドしたら@Overrideに加えて@Nullableもついてきた。
意味としてはNullも許されるということらしい。
サンプルでは引数のViewGroup containerとBundle savedInstanceStateに@Nullableがついていたが、メソッド自身につけられるらしい。

inflate

レイアウトXMLファイルからViewを生成するときにはinflate()を使う。
attachRootをfalseとすることでR.layout.fragment_media_effectsがルートビューとなる。
trueの場合はcontainerがルートビューとなる。

inflater.inflate(R.layout.fragment_media_effects, container, false);

enter image description here

onViewCreated(View view, @Nullable Bundle savedInstanceState)

onCrearedViewが返された事をFragmentに知らせる。
viewを引数に持っているのでfindViewByIdに割り当てる。

参考
http://qiita.com/kkkaaakkku/items/97ef17ab6a7f7b4e365d

setEGLContextClientVersion

OpenGL ESのバージョンを指定する。
サンプルでは2だが、
Android 4.3からはOpenGL ES 3.0対応したらしい。

setRenderer(@Nullable GLSurfaceView.Renderer renderer)

レンダラーをセット。このサンプルでは自分自身なのでthis

setRenderMode(int rendermode)

レンダラーモードの設定。

変数 意味
RENDERMODE_CONTINUOUSLY 連続描画モード(毎フレーム)
RENDERMODE_WHEN_DIRTY 必要な時だけ描画

2015年6月13日土曜日

GoogleサンプルでAndroidアプリを学ぶ(SlidingTabsBasic)

GoogleサンプルでAndroidアプリを学ぶ(SlidingTabsBasic)

前回、ActionBarCompat-Styledを置き換えようとしたSlidingTabsBasicをやってみました。

[開発環境]
 Android Studio
[使用したサンプル]
 SlidingTabsBasic
[機能]
 デザインのみ。

※view/SlidingTabLayout、SlidingTabLayoutはpackage名を変えてそのまま使うことにしました。
※Logとかはとりあえずそのまま使いました。
※残念ながらメニューがうまくでない。。。


Packegeを作る

このサンプルでは、Common\activiesという階層にSampleActivityBase.javaというファイルを置いていたので、
javaが選択された状態でNew->Packegeでjavaを選択し、OK。
enter image description here

common.activitiesを作成する。
enter image description here

デフォルトコンストラクタ

LogWrapperクラスには、コンストラクタが定義されていないが、コンストラクタが1つも定義されていない場合は、
デフォルトコンストラクタと呼ばれる引数無しで中身が空のコンストラクタが自動で生成されるらしいので問題ないらしい。

参考
http://www.javadrive.jp/start/constructor/index4.html

Interface

インタフェース は、ある機能を実現するクラスが必ず実装するべきメソッドの名前や型といった作法のみを定義するもの。
インタフェースで定義されるメソッド(抽象メソッド)の実体は implements を用いた側のクラスで実装する必要がある。

public interface LogNode {
    public void println(int priority, String tag, String msg, Throwable tr);

}

public class MessageOnlyLogFilter implements LogNode {
}

実際にMessageOnlyLogFilterを作ってみると以下のようにinterfaceで定義したprintlnを宣言しなければいけない
とコメントがでる。 

enter image description here

drawable/tileでエラー

サンプルを真似してstyles.xmlにコーディングしていたが、以下のところでdrawable/tileがないと怒られた。

<item name="android:background">@drawable/tile</item>

テキストエディタでdrawableを検索するとオリジナルのSlidingTabsBasic/Application/build/intermediates/symbols/debug/R.txtに以下の記載がある。
int drawable tile 0x7f020001

R.txtにこれを記載する方法がわからないので、オリジナルをAndriod Studioで開いてみたところ以下のようにdrawableの下にtile.9.pngが置いてあった。

これを同じようにすればよいと思い、
SlidingTabsBasic/Application/src/main/res/drawable-hdpiに
tile.9.pngが置いてあったのでAndroid StudioでdrawableにコピーしようとDrag & Dropしたができない。。。
enter image description here

ツリービューを以下のようにProjectに変えればdrawableにDrag & Dropでコピーすることができました。そしてdrawable/tileのエラーも消えました。
enter image description here

enter image description here

FragmentTransaction

Fragmentを切り替えて画面遷移を表現する場合には、以下のように別で作成したものを置き換える。

 FragmentTransaction transaction = 
                getSupportFragmentManager().beginTransaction();
 SlidingTabsBasicFragment fragment = new SlidingTabsBasicFragment();
 transaction.replace(R.id.sample_content_fragment, fragment);
 transaction.commit();

イメージとしては以下のような感じが気がする。
enter image description here

その他

android:textSize

単位
px pixels 画面上のPixelがそのままの単位になる
dp(dpi) Density-independent Pixels ディスプレイ解像度の物理的な密度に応じた抽象単位
sp Scale-independent Pixels ユーザーのフォントサイズの設定により伸縮される。フォントサイズの指定では推奨される単位

9 patch

drawableにtile.9.pngを追加したがそもそも9.pngという拡張子を初めて見た。

9 patchというものらしく、画像が拡大される際に拡大される領域とそうでない領域を指定するものらしいです。

参考
http://d.hatena.ne.jp/tomorrowkey/20110501/1304245217

android:shadowColor

影の色

android:shadowDy

影をY方向にどれだけずらすか。負の値も指定可能。

android:shadowRadius

影の半径。大きいほどぼやける。

Widget.SampleMessage

????

android:lineSpacingMultiplier

改行時のテキストの行間の余白の高さの指定とのこと。

<item name="android:lineSpacingMultiplier">1.1</item>

transaction.replace

以下のようにしたが、Wrong 2nd argument type.というエラーがでている。
調べてみると、android.support.v4.app.Fragmentではなく、android.app.Fragmentがimportされていたので修正したら
エラーが消えました。
//import android.app.Fragment;
import android.support.v4.app.Fragment;

 SlidingTabsBasicFragment fragment = new SlidingTabsBasicFragment();
 //activity_main.xmlで定義したFrameLayoutをSlidingTabsBasicFragmentに取り替える。
transaction.replace(R.id.sample_content_fragment,fragment);

enter image description here

android:showAsAction=”always”

menu_main.xmlにandroid:showAsActionを記載したが以下のようにエラーになった。

enter image description here

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools" tools:context=".MainActivity">
    <item android:id="@+id/menu_toggle_log"
        app:showAsAction="always"
        android:title="@string/sample_show_log" />
</menu>

instanceof

logToggle.setVisible(findViewById(R.id.sample_output)instanceof ViewAnimator);

の意味が分からないので調べたところ、

findViewById(R.id.sample_output)がViewAnimatorだったら、
Trueということになります。

activity_main.xmlで以下のように宣言しているので当然Trueですが。

    <ViewAnimator
          android:id="@+id/sample_output"

setDisplayedChild

表示するためのChild viewを設定する。
以下のようになってるけど、どれが1?

if (mLogShown) {
    output.setDisplayedChild(1);
} else {
    output.setDisplayedChild(0);
}

2015年6月8日月曜日

GoogleサンプルでAndroidアプリを学ぶ(ActionBarCompat-Styled)

GoogleサンプルでAndroidアプリを学ぶ(ActionBarCompat-Styled)

[開発環境]
 Android Studio
[使用したサンプル]
 ActionBarCompat-Styled
[機能]
デザインのみ。


途中までやったが、以下理由によりこのサンプルは中断。

・deprecatedなクラスがあり、調べたがすんなりと置き換えがうまくいかない。
・SlidingTabLayoutに置き換えようとしたがそれ自身はSlidingTabsBasicのサンプルにあるので、
それをベースに考えたほうが無駄がない。


ActionBarActivityが取り消し線に

ActionBarActivityが以下のように取り消し線になってました。
enter image description here

調べてみるとAndroid Support Libraryの22.1から以下のようにdeprecatedなので、AppCompatActivityを代わりに使えとのこと。
enter image description here

AppCompatActivityに書き換えたら今度は赤くなっている。
enter image description here

Alt+Enterを押すことでimportにandroid.support.v7.app.AppCompatActivityが追加されて解決。

setNavigationModeが取り消し線に

setNavigationModeが取り消し線になっていたので、Google Developersで調べたところ以下のようにdeprecatedになってました。
enter image description here

置き換えの例がないのでどうしたらいいのか悩んでいたところ
SlidingTabsで置き換えるとが近いらしく、Android Developerのサンプルにもあるようなのでこれを参考にしてみました。

Step1. Google DeveloperのSlidengTabsBasicの
/SlidingTabsBasic/Application/src/main/java/com/example/android/common/viewにある以下の2つのファイルを新しいプロジェクトにコピー。

SlidingTabLayout.java
SlidingTabStrip.java

※packageはコピー先のMainActivityと同じpacakgeに修正する。
//package com.example.android.common.view;
package com.example.xxx.yyyyy;

以下を参考にしたがタブの画面がでてこないので中断。

参考:
http://qiita.com/nein37/items/b869193ee583a96f86a8

2015年6月7日日曜日

GoogleサンプルでAndroidアプリを学ぶ(ActionBarCompat-ShareActionProvider)

GoogleサンプルでAndroidアプリを学ぶ(ActionBarCompat-ShareActionProvider)

しばらくぶりにAndroidの勉強をしようと思い、Googleのサンプルから始めることにしました。
勉強の仕方としては、サンプルを参考に、1からプロジェクトを作ってサンプルを移植していきます。
いつまで続くかわかりませんが。。

[開発環境]
 Android Studio
[使用したサンプル]
 ActionBarCompat-ShareActionProvider
[機能]
 ・ページを切り替えるとテキストとassetsに格納された画像の表示を切り替える。
 ・表示されているコンテンツを他のアプリとShareする。

学んだことを記載します。

Assets

Assetsフォルダの追加

このサンプルではassetsフォルダにある画像を表示しておりますが、Android Studioにはassetsフォルダ自身が作成されてません。なので以下の手順でassetsフォルダを作成しました。

Step1. 表示を「Android」から「Project」へ変更
enter image description here

Step2. app\mainで右クリックし、「New」→「Directory」でassetsを作成
enter image description here

Step3. ファイルブラウザで作成したassetsフォルダに画像をコピー

Assetsフォルダのファイルへのアクセス

少しハマったので記載しておきます。
このサンプルはコンテンツを他のアプリとのShareすることを目的としているため、以下のようにContentProviderを拡張したクラスを作ってます。

public class AssetProvider extends ContentProvider

本来ならば以下のようにAssetManagerを使えば取得できるらしいのだが、できなかった。

AssetManager am = getContext().getAssets();

調べてみるとContentProviderを拡張したクラスを使っているため、AndroidManifest.xmlに
providerを追加する必要があった。

<application
  <activity
  </activity>
  <provider  
   android:authorities="com.example.android.actionbarcompat_shareactionprovider"
   android:name=".content.AssetProvider"/>
</application>

他のアプリとのShare(Intent)

enter image description here
のアイコンを出すために以下が必要。

Step1. menu_main.xmlに以下を追加する。

<menu 
    xmlns:support="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/menu_share"
        android:title="@string/menu_share"
        support:actionProviderClass="android.support.v7.widget.ShareActionProvider"
        support:showAsAction="always" />
</menu>

Step2. onCreateOptionsMenuの修正
ShareActionProviderはv7.widegetのほうをimportする必要があるので注意が必要。

イメージとしては以下のような感じな気がする。

enter image description here

//import android.widget.ShareActionProvider;
import android.support.v7.widget.ShareActionProvider;

private ShareActionProvider mShareActionProvider;

    @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);
        MenuItem shareItem = menu.findItem(R.id.menu_share);
        mShareActionProvider = (ShareActionProvider) MenuItemCompat.getActionProvider(shareItem);

    // 今、Viewpagerに表示されているものをIntentする。
        int currentViewpagerItem = ((ViewPager)findViewById(R.id.viewpager)).getCurrentItem();
        setShareIntent(currentViewpagerItem);

        return super.onCreateOptionsMenu(menu);
    }

    private void setShareIntent(int position) {
        if (mShareActionProvider != null) {
            ContentItem item = mItems.get(position);
            Intent shareIntent = item.getShareIntent(MainActivity.this);

            mShareActionProvider.setShareIntent(shareIntent);
        }
    }
[ContentItem.java]
  public Intent getShareIntent(Context context) {
        Intent intent = new Intent(Intent.ACTION_SEND);

        switch (contentType) {
            case CONTENT_TYPE_IMAGE:
                intent.setType("image/jpg");
                intent.putExtra(Intent.EXTRA_STREAM,getContentUri());
                break;
        }

        return intent;
    }

PagerAdapter

ViewPagerに表示するための仕組みがよくわからなかったので、簡単な図にしてみました。
ViewPagerで表示する中身を生成するためのAdapter(PagerAdapter)を使ってます。

enter image description here

暗黙的Intent

今回使用したのは暗黙的Intentであり、他のアプリと連携するために使用する。
宛先となるオブジェクトを明示的に指定せずに所定の動作、データのみを指定する。
これによりAndroidシステムが該当するオブジェクトをシステム全体から検索し、起動するしくみ。

それと対象に明示的Intentは画面遷移などアクティビティーから他の指定したアクティビティーへ送るIntent。

今回の場合は以下。
・Intentのコンストラクタでアクション(Intent.ACTION_SEND)を
指定してインスタンスを生成。

・setTypeでインテントにカテゴリを付加し、
 putExtraでデータの種類とデータを渡している。
 

[参考]
http://www.sakc.jp/blog/archives/24833

その他

No files are open

Android Studioでプロジェクトを開いたら以下のようにNo files are openとでてファイルが開かなくなっていたが、左側の1: Projectを押せば復活しました。
enter image description here

getCurrentItem

Viewpagerで現在のページ位置を取得する場合には以下で取得可能。

int currentViewpagerItem = ((ViewPager)findViewById(R.id.viewpager)).getCurrentItem();

android:textAppearance

xmlでテキストのスタイル定義の設定を指定する。

要素 説明
?android:textAppearanceSmall 小さいサイズ
?android:textAppearanceMedium 普通のサイズ
?android:textAppearanceLarge 大きいサイズ

[参考]
http://androidguide.nomaki.jp/html/widget/textview/fontsize.html

setOnPageChangeListenerが取り消し線になっている

ViewPagerでsetOnPageChangeListenerを使おうとしたら以下のように取り消し線になってました。
enter image description here

Google Developerで調べてみると以下のように別のを使えということなので、addOnPageChangeListenerを使いました。

enter image description here

android:scaleType

画像サイズの設定を指定する。

ScaleType 画像サイズ 表示位置
CENTER サイズ変更なし 中央
CENTER_TOP ボタンの横幅いっぱいに拡大 中央
FIT_CENTER ボタンの縦幅いっぱいに拡大 中央
FIT_END ボタンの横幅いっぱいに拡大 右寄せ
FIT_START ボタンの縦幅いっぱいに拡大 左寄せ
FIT_XY ボタンの横幅いっぱいに拡大

android:lineSpacingMultiplier

改行時のテキストの行間の余白の高さを指定します。
android:lineSpacingMultiplier = “0.8”

ViewPagerのレイアウト

ViewPagerは全画面で設置することが想定されているのか、wrap_contentをサポートしておらず、 android:layout_height=”wrap_content”とすると、高さが0になってしまうとのこと。

高さが設定できないので、layout_weightを使う。

LayoutInflater

以下とのことです。

Androidのプログラミングでは、画面のViewを構成する場合、layout用xmlファイルを用いて、レイアウトを作成することが推奨されている。
しかし、xmlファイルを用いた場合、それは、静的にレイアウトが決定付けられてしまい、プログラムの実行時にレイアウトを変形することはできない。
この不都合を回避するため、LayoutInflater Classが用意されており、このクラスを活用することにより、実行時にお好みのレイアウトに変形できる。

[参考]
https://sites.google.com/site/androyerjapan/home/layoutinflater

Error:Execution failed for task ‘:app:compileDebugAidl’. > aidl is missing

Runしたら以下のようなエラーがでた。

#!

Information:Gradle tasks [:app:assembleDebug]
:app:preBuild UP-TO-DATE
:app:preDebugBuild UP-TO-DATE
:app:checkDebugManifest
:app:preReleaseBuild UP-TO-DATE
:app:prepareComAndroidSupportAppcompatV72220Library UP-TO-DATE
:app:prepareComAndroidSupportSupportV42220Library UP-TO-DATE
:app:prepareDebugDependencies
:app:compileDebugAidl FAILED
Error:Execution failed for task ':app:compileDebugAidl'.
> aidl is missing
Information:BUILD FAILED

ビルドツールがあっていないのではということでapp\build.gradleを確認すると
以下のようにbuildToolsVersion “23.0.0 rc1”となっていた。

#!java

apply plugin: 'com.android.application'

android {
    compileSdkVersion 22
    buildToolsVersion "23.0.0 rc1"
    defaultConfig {
        applicationId "com.example.takashin10.actionbarcompat_shareactionprovider"
        minSdkVersion 15
        targetSdkVersion 22
        versionCode 1
        versionName "1.0"
    }

[対策]
1. [Tools] -> [Android] -> [SDK Manager]
2. Tools (Preview Channel)を見るとbuildToolsVersionで指定している23rc1がNot installed
 になっているので、チェックし、Install
範囲を選択_120.png
3. Android Studioを再起動

しかし、以下のようなエラーがまだでている。
Failed to find Build Tools revision 23.0.0 rc1

[SDK Manger]で確認するとAndroid SDK Build-toolsは23.0.0 rc2になっていた。
範囲を選択_122.png

app\build.gradleをbuildToolsVersion “23.0.0 rc2” に変えることでエラー回避できた。