2015/06/10

OpenLayers 3 でマーカーを表示する方法 2種

調べた限り、OpenLayers 3 でマーカーを表示する方法は2通りある様子OpenLayers 3.6.0 で確認
2015/05/02

Android Studio で Warning や Error の一覧を表示する

Android SDK を更新したら Warning が増えてしまいました。
問題になりそうなところを教えてくれるのは良いのですが、修正するには一覧で確認したいもの。
というわけで、一覧表示する方法を調べました。

Analyze → Inspect Code...

対象の範囲を選びます。

Analyze が終了すると、左下に Inspection というウィンドウが作成され、一覧が表示されます。

左のボタンで表示を切り替え可能なので、使いやすいようにカスタマイズします。
お勧めは、赤と黄色のボタン、"Group Inspections By Severity" です。
以下のように Error, Warning, Typo で分類してくれます。

2015/04/12

AndroidStudioで Java Library を追加したら UNEXPECTED TOP-LEVEL EXCEPTION でコンパイルが通らなかった場合の対処方法

現象

UNEXPECTED TOP-LEVEL EXCEPTION もいろいろなケースがあるので、一概に言えないのですが、以下のように ParseException: bad class file magic or version の場合、コンパイルに使った Java のバージョンが合っていない可能性が高いです。

...省略
:app:preDexDebug
AGPBI: {"kind":"SIMPLE","text":"UNEXPECTED TOP-LEVEL EXCEPTION:","position":{},"original":"UNEXPECTED TOP-LEVEL EXCEPTION:"}
AGPBI: {"kind":"SIMPLE","text":"com.android.dx.cf.iface.ParseException: bad class file magic (cafebabe) or version (0034.0000)","position":{},"original":"com.android.dx.cf.iface.ParseException: bad class file magic (cafebabe) or version (0034.0000)"}
AGPBI: {"kind":"SIMPLE","text":"\tat com.android.dx.cf.direct.DirectClassFile.parse0(DirectClassFile.java:472)","position":{},"original":"\tat com.android.dx.cf.direct.DirectClassFile.parse0(DirectClassFile.java:472)"}
AGPBI: {"kind":"SIMPLE","text":"\tat com.android.dx.cf.direct.DirectClassFile.parse(DirectClassFile.java:406)","position":{},"original":"\tat com.android.dx.cf.direct.DirectClassFile.parse(DirectClassFile.java:406)"}
AGPBI: {"kind":"SIMPLE","text":"\tat com.android.dx.cf.direct.DirectClassFile.parseToInterfacesIfNecessary(DirectClassFile.java:388)","position":{},"original":"\tat com.android.dx.cf.direct.DirectClassFile.parseToInterfacesIfNecessary(DirectClassFile.java:388)"}
AGPBI: {"kind":"SIMPLE","text":"\tat com.android.dx.cf.direct.DirectClassFile.getMagic(DirectClassFile.java:251)","position":{},"original":"\tat com.android.dx.cf.direct.DirectClassFile.getMagic(DirectClassFile.java:251)"}
AGPBI: {"kind":"SIMPLE","text":"\tat com.android.dx.command.dexer.Main.processClass(Main.java:704)","position":{},"original":"\tat com.android.dx.command.dexer.Main.processClass(Main.java:704)"}
AGPBI: {"kind":"SIMPLE","text":"\tat com.android.dx.command.dexer.Main.processFileBytes(Main.java:673)","position":{},"original":"\tat com.android.dx.command.dexer.Main.processFileBytes(Main.java:673)"}
AGPBI: {"kind":"SIMPLE","text":"\tat com.android.dx.command.dexer.Main.access$300(Main.java:83)","position":{},"original":"\tat com.android.dx.command.dexer.Main.access$300(Main.java:83)"}
AGPBI: {"kind":"SIMPLE","text":"\tat com.android.dx.command.dexer.Main$1.processFileBytes(Main.java:602)","position":{},"original":"\tat com.android.dx.command.dexer.Main$1.processFileBytes(Main.java:602)"}
AGPBI: {"kind":"SIMPLE","text":"\tat com.android.dx.cf.direct.ClassPathOpener.processArchive(ClassPathOpener.java:284)","position":{},"original":"\tat com.android.dx.cf.direct.ClassPathOpener.processArchive(ClassPathOpener.java:284)"}
AGPBI: {"kind":"SIMPLE","text":"\tat com.android.dx.cf.direct.ClassPathOpener.processOne(ClassPathOpener.java:166)","position":{},"original":"\tat com.android.dx.cf.direct.ClassPathOpener.processOne(ClassPathOpener.java:166)"}
AGPBI: {"kind":"SIMPLE","text":"\tat com.android.dx.cf.direct.ClassPathOpener.process(ClassPathOpener.java:144)","position":{},"original":"\tat com.android.dx.cf.direct.ClassPathOpener.process(ClassPathOpener.java:144)"}
AGPBI: {"kind":"SIMPLE","text":"\tat com.android.dx.command.dexer.Main.processOne(Main.java:632)","position":{},"original":"\tat com.android.dx.command.dexer.Main.processOne(Main.java:632)"}
AGPBI: {"kind":"SIMPLE","text":"\tat com.android.dx.command.dexer.Main.processAllFiles(Main.java:510)","position":{},"original":"\tat com.android.dx.command.dexer.Main.processAllFiles(Main.java:510)"}
AGPBI: {"kind":"SIMPLE","text":"\tat com.android.dx.command.dexer.Main.runMonoDex(Main.java:280)","position":{},"original":"\tat com.android.dx.command.dexer.Main.runMonoDex(Main.java:280)"}
AGPBI: {"kind":"SIMPLE","text":"\tat com.android.dx.command.dexer.Main.run(Main.java:246)","position":{},"original":"\tat com.android.dx.command.dexer.Main.run(Main.java:246)"}
AGPBI: {"kind":"SIMPLE","text":"\tat com.android.dx.command.dexer.Main.main(Main.java:215)","position":{},"original":"\tat com.android.dx.command.dexer.Main.main(Main.java:215)"}
AGPBI: {"kind":"SIMPLE","text":"\tat com.android.dx.command.Main.main(Main.java:106)","position":{},"original":"\tat com.android.dx.command.Main.main(Main.java:106)"}
AGPBI: {"kind":"SIMPLE","text":"...while parsing com/kokufu/lib/Test.class","position":{},"original":"...while parsing com/kokufu/lib/Test.class"}
AGPBI: {"kind":"SIMPLE","text":"1 error; aborting","position":{},"original":"1 error; aborting"}

私の環境で Java のバージョンを調べてみると、以下のように 1.8 でした。

$ java -version
java version "1.8.0_20"
Java(TM) SE Runtime Environment (build 1.8.0_20-b26)
Java HotSpot(TM) 64-Bit Server VM (build 25.20-b23, mixed mode)

解決方法

2015/4/12 現在、Android Studio は Java 1.7 系でコンパイルするようですので、以下のように Java Library のコンパイルバージョンを下げます。

lib/build.gradle
apply plugin: 'java'

sourceCompatibility = '1.7'

Android Application のコンパイルバージョンを変更する

おまけですが、Android Application の方のコンパイルバージョンも変更することが出来ます。
以下のように Source Compatibility を選択すればオーケー。
現時点では 1.8 が選択肢にないです。

File → Project Structure
2015/03/19

DialogFragment の中に Fragment を表示する方法

ちょっと複雑な Dialog を表示しようと思った場合、DialogFragment の中に Fragment を表示したいということがあるかと思います。
しかし、XML を使った静的な Fragment は入れ子構造に出来ないようです。

では、どうしたら良いのかというと、動的に Fragment を追加してやれば良いです。
以下のように、onViewCreated() で Fragment を追加します。この時、getChildFragmentManager() を使用していることに注意です。

TestDialog.java
public class TestDialog extends DialogFragment {
    public TestDialog() {
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.dialog_test, container, false);
        return v;
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        Fragment innerFragment = new InnerFragment();
        getChildFragmentManager().beginTransaction().add(R.id.fragment, innerFragment).commit();
    }
}

dialog_test.xml
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/fragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />
2015/02/09

Gradle で Configuration with name 'default' not found. が出てしまった時の対処方法

Gradle で app と lib のように 2つの依存関係のあるモジュールを開発していると、以下のようなエラーが出てしまうことがあります。

A problem occurred configuring project ':app'.
> Cannot evaluate module lib : Configuration with name 'default' not found.

解決策1: app から対象の Configuration を明示的に指定する

Configuration は plugin を適用すると大抵は自動的に設定されます。 java とか com.android.application だと default という名前の Configuration があるので問題ないのですが、その他のものの場合は default がない場合があります。その場合は、対処の Configuration を以下のように明示的に指定することで回避することができます。
project の引数に path: が追加されているのに注意してください。

app/build.gradle
dependencies {
    compile project(path: ':lib', configuration: 'compile')
}

解決策2: lib に default という名前の Configuration を作る

lib にプラグインを適用してない等、Configuration がそもそもない場合は、以下のように自分で作成してしまうのも手です。

lib/build.gradle
configurations.create('default')