2011年2月27日日曜日

[Java]プライベートクラスをインスタンス化する

そもそもユニットテストを前提とした設計をしていないのが問題なんですが、ユニットテストで、特定のクラスの内部クラスを実行しなければいけない場合に遭遇しました。
メンバ変数に保持していれば、リフレクションで取り出すことができるので、実行も比較的楽なんですが、コレがメソッド内のみで利用されている場合、この内部クラスを外部からインスタンス化する必要があります。
ちょっと面倒ですが、外部からインスタンス化する方法を紹介します。

■インスタンス化するコード
try {
    TargetClass target = new TargetClass();

    //配列の0番目は決めうち
    Class<?> clss = TargetClass.class.getDeclaredClasses()[0];

    //コンストラクタを取り出す。引数はそのアウタークラスになる
    Constructor<?> cons = clss.getDeclaredConstructor(new Class[]{TargetClass.class});

    //コンストラクタを使ってインスタンスを生成する
    cons.setAccessible(true);
    Object inner = cons.newInstance(new Object[]{target});

    //メソッド実行
    System.out.println(inner.toString());

catch (SecurityException e) {
catch (NoSuchMethodException e) {
catch (IllegalArgumentException e) {
catch (InstantiationException e) {
catch (IllegalAccessException e) {
catch (InvocationTargetException e) {
}

第一引数が該当のクラスのアウタークラスになるのがルール。

■ターゲットのクラス(例)

public class TargetClass {

    public void doExec(){

        new TargetInnerClass().subExec();
    }

    //このクラスの単体テストが難しい...
    private class TargetInnerClass{
        public void subExec(){

        }
    }
}

2011年2月20日日曜日

[Android]ADBからintentを送信する

ADBのshellからintentを発行する方法としてamコマンドがあります。以下のような感じ。
結構便利です。

■電話をかける
am start -a android.intent.action.CALL tel:0521112222


■Androidまかせ(ブラウザ起動と地図→スキーまでよろしくやる)
am start -a android.intent.action.VIEW http://www.google.com
am start -a android.intent.action.VIEW geo:0,0?q=Tokyo


■設定
am start -a android.settings.SETTINGS


■特定のアプリケーションを起動
am start -a android.intent.action.MAIN -n com.android.settings/.Settings

2011年2月18日金曜日

[他]シート名を取得する

excelでシート名を取得したい場合があります。シート名を特定のセルに入れたい場合などですね。
で、式はこんな感じ。

=MID(CELL("filename"),FIND("]",CELL("filename"))+1,31)


2012/1/16 追記。
複数のシートがあった時、最後に編集したシート名?になってしまうようです。
とういうことで、
=MID(CELL("filename",$A$1),FIND("]",CELL("filename",$A$1))+1,31)

2011年2月16日水曜日

[Java]ファイルを簡単にコピーする

Javaにはファイルをコピーするメソッドが存在しません。そのためInputStreamとOutputStreamのread/writeで処理しますが、もっと簡単な方法がありました。コードはこんな感じ。

/**
 * ファイルコピーします。
 *
 * @param srcPath コピー元
 * @param destPath コピー先
 */

public static void copy(File srcPath, File destPath) {

    FileChannel srcChannel = null;
    FileChannel destChannel = null;

    try {
        srcChannel = new FileInputStream(srcPath).getChannel();
        destChannel = new FileOutputStream(destPath).getChannel();

        srcChannel.transferTo(0, srcChannel.size(), destChannel);

    } catch (IOException e) {
        e.printStackTrace();

    } finally {
        if (srcChannel != null) {
            try {
                srcChannel.close();
            } catch (IOException e) {
            }
        }
        if (destChannel != null) {
            try {
                destChannel.close();
            } catch (IOException e) {
            }
        }
    }
}

2011年2月12日土曜日

[Android]プロセスは終了しない(基本的に)

Androidのプロセスは基本的に終了しません。最初違和感があったんですが、最近は慣れてきました。
でも余計なリソースを残したくない。という場合、ActivityのライフサイクルのonDestroyあたりでSystem.exit()を呼び出すという方法があります。

意外とすっきりする感じがします。

2011年2月9日水曜日

[Android]ライブラリプロジェクトを使う

androidの開発で、複数のプロジェクトを開発し、なおかつ、共通部分を切り出したい。というときがあります。そういうときに、ライブラリプロジェクトを使います。
ライブラリプロジェクトを使わない方法としては、共通部分をjar化する方法がありますが、結構面倒だったり、デバッグしづらかったりします。

ライブラリプロジェクトは、以下のようにして作成します。


  1. androidプロジェクトを新規作成します

  2. プロジェクトの設定で、「android」のプロパティで「Is Library」にチェックする

ライブラリプロジェクトを使う方法は、以下のようにします。



  1. androidプロジェクトを新規作成します

  2. プロジェクトの設定で「android」のプロパティで、ライブラリの部分の「追加」ボタンでライブラリプロジェクトを選択します

以上。超簡単。でどんなメリットがあるかというと、


  • ソースを共有できる。ソースフォルダを共有します。ビルド対象になります

  • リソースを共有できる。文字列や画像。ライブラリプロジェクト側のR.javaが追加されます

  • aidlを共有できる。R.java同様に、勝手に追加されます

  • nativeライブラリが共有できる。各プロジェクトにコピーする必要がなくなった

リソースに関しては、ライブラリプロジェクトのにあるものと、同名のものを作るとなんと、オーバライドされます。


ソースのビルドは多少時間がかかりますが、反面、コンパイルされることにより、ビルド時にいろいろなことを解決できます。オーバラードされたリソースIDとか。意外と便利。

2011年2月3日木曜日

[Java]オブジェクトをディープコピーする

Object#cloneをオーバライドして実装するのはいちいち手間がかかります。
で、手っ取り早くオブジェクトをディープコピーするために、シリアライズ・デシリアライズします。コードはこんな感じ。

/**
 * ObjectOutputStreamを使ったディープイコピー
 * @param target 対象のオブジェクト
 * @return コピーしたもの
 * @throws Exception
 */

public static Object deepCopy(Object target) throws Exception {
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    ObjectOutputStream oos = new ObjectOutputStream(bos);
    oos.writeObject(target);

    ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(
            bos.toByteArray()));
    return ois.readObject();
}