2009年1月アーカイブ

Bitmapのピクセル操作をするには、
android.graphicsパッケージBitmapクラスのgetPixel() / setPixel()を呼び出します。
また、getPixels() / setPixels()を呼び出すことで、複数のピクセルを操作することもできます。

具体的なサンプルコードは、以下のとおりです。

// Bitmap bitmap; // ビットマップがARGB32bitの場合
int width = bitmap.getWidth();
int height = bitmap.getHeight();
int pixels[] = new int[width * height];

bitmap.getPixels(pixels, 0, width, 0, 0, width, height);

for (int y = 0; y < height; y++) {
    for (int x = 0; x < width; x++) {
        int pixel = pixels[x + y * width];

        pixels[x + y * width] = Color.argb(
                Color.alpha(pixel),
                0xFF - Color.red(pixel),
                0xFF - Color.green(pixel),
                0xFF - Color.blue(pixel));
    }
}

bitmap.setPixels(pixels, 0, width, 0, 0, width, height);

この例では、ARGB32bit形式のBitmapに対して、
getPixels()を呼び出し、全ピクセルを(pixels)配列へ取得後、
forループ内で、各ピクセル(32bit値)のRGBを反転したピクセルを配列へ戻し、
最後に、setPixels()を呼び出し、変更した配列をBitmapへ反映させています。

上記では、全ピクセルを一括で配列へ取得していますが、
全ピクセルが必要でなければ、以下のように1行毎にget/setしてもよいでしょう。
このあたりは、画像処理のアルゴリズムとか、使用メモリ容量、速度などを考慮して書いてみてください。

int pixels[] = new int[width];

for (int y = 0; y < height; y++) {
    bitmap.getPixels(pixels, 0, width, 0, y, width, 1);

    for (int x = 0; x < width; x++) {
        int pixel = pixels[x];
        // ...
    }

    bitmap.setPixels(pixels, 0, width, 0, y, width, 1);
}

最後になりますが、
setPixels()は、Bitmapが編集不可(つまり、Bitmap.isMutable()がfalse)の場合、
IllegalStateExceptionの例外がスローされます。

ちなみに、編集不可のBitmapから、編集可能なBitmapを得るには、
copy(Bitmap.Config config, boolean isMutable)
を呼び出します。

第1引数が、Bitmapピクセルの並びで、32bitARGBを得るには、Bitmap.Config.ARGB_8888を指定します。
また、第2引数が編集可能かどうかですので、trueを設定することで、編集可能なBitmapのコピー(複製)を得ることができます。

XMLを解析するには、org.xmlpull.v1パッケージのXmlPullParserクラスを使用します。

 

XmlPullParserのインスタンスを得るには?

android.utilパッケージのXmlクラスのstaticメソッドであるnewPullParser()を呼び出します。

final XmlPullParser xmlPullParser = Xml.newPullParser();

または、

og.xmlpull.v1パッケージのXmlPullParserFactoryクラスのstaticメソッドである
XmlPullParserFactory.newInstance()を呼び出し、
XmlPullParserFactoryのインスタンスを取得後、同インスタンスのnewPullParser()を呼び出します。

final XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
final XmlPullParser xmlPullParser = factory.newPullParser();

※通常は、簡単な前者の方法でよいと思います。

 

XmlPullParserインスタンスに解析したいXMLをセットするには?

XmlPullParserクラスの
setInput(Reader in)、または、
setInput(InputStream inputStream, String inputEncoding)
を呼び出します。

例えば、このクラスの動作を理解するために、以下のように書いてみるのもよいでしょう(ヘルプと同じ例です)。

xmlPullParser.setInput(new StringReader("<foo>Hello World!</foo>"));

 

XmlPullParserインスタンスで解析を進めるには?

XmlPullParserクラスのnext()を呼び出します。

すると、戻り値に、EventTypeと呼ばれる下記のような定数値が得られます(以下は一部)。

  • XmlPullParser.START_DOCUMENT
  • XmlPullParser.START_TAG
  • XmlPullParser.TEXT
  • XmlPullParser.END_TAG
  • XmlPullParser.END_DOCUMENT

また、XmlPullParserクラスのgetDepth()を呼び出すと、現在解析しているdepth(階層)を得ることもできますし、
getName()を呼び出すと、エレメントのname(名前)を取得できます。

例えば、以下のようなXMLを解析すると、

<lv1>
  a
  <lv2 title="test">
    b
  </lv2>
  c
</lv1>

以下のような結果が得られます。

depth=0, eventType=START_DOCUMENT,  name=null   //
depth=1, eventType=  START_TAG,     name=lv1    // <lv1>
depth=1, eventType=    TEXT,        name=null   //   a
depth=2, eventType=      START_TAG, name=lv2    //     <lv2>
depth=2, eventType=        TEXT,    name=null   //       b
depth=2, eventType=      END_TAG,   name=lv2    //     </lv2>
depth=1, eventType=    TEXT,        name=null   //   c
depth=1, eventType=  END_TAG,       name=lv1    // </lv1>
depth=0, eventType=END_DOCUMENT,    name=null   //

まとめると、

  • START/END_DOCUMENTは、最初と最後に登場し、depthは、0
  • START/END_TAGは、<></>のたびに登場し、depthは、STARTでインクリメント、ENDの後にデクリメントされる
  • nameは、<></>でのみセットされる

のような感じになります。

最後になりますが、肝心の値の取得ですが、
TEXTの値を取得するには、getText()、
属性(先の例だとtitleの値)を取得するには、getAttributeValue()を呼び出すと取得できます。

android.osパッケージのParcelableは、
(Parcelクラスから)インスタンスを読み書きするためのインターフェースです。

例えば、アクティビティ(Activity)間で、データを渡したい場合、
Intent.putExtra()などで、ほとんどのデータ型を格納することができますが、

Parcelableインタフェースを実装しているクラスであれば、そのインスタンスも、
putExtra(String name, Parcelable value)を呼び出すことで、インスタンスごと渡すことができます。
※「Parcel」は日本語に直訳すると「小包」。なんとなくイメージできますね。

では、Parcelableインタフェースを実装するには、どうすればよいかというと、
下記のような実装を追加するだけでよいです。

※ソースコードは、公式のヘルプ(http://code.google.com/intl/ja/android/reference/android/os/Parcelable.html)を引用したものです。

 public class MyParcelable implements Parcelable {
     private int mData;
     
     public void writeToParcel(Parcel out, int flags) {
         out.writeInt(mData);
     }

     public static final Parcelable.Creator CREATOR
             = new Parcelable.Creator() {
         public MyParcelable createFromParcel(Parcel in) {
             return new MyParcelable(in);
         }

         public MyParcelable[] newArray(int size) {
             return new MyParcelable[size];
         }
     }
     
     private MyParcelable(Parcel in) {
         mData = in.readInt();
     }
 }

具体的には、

コンストラクタ(Parcel in)では、データの読み込み(復元)処理を追加します。

例えば、この例では、int型のメンバ変数を読み込みたいので、in.readInt()を呼び出します。

※ArrayList<XXX>の場合には、Parcel.createTypedArrayList(XXX.CREATOR)を呼び出す。
※メンバ変数が、独自のクラスの場合にも、同クラスでParcelalbeを実装し、
読み込みたいところで、Parcel.readParcelable(ClassLoader loader)を呼び出す。
ClassLoader loaderは、XXX.class.getClassLoader()で取得できます。

次に必要となるのが、書き込みですが、こちらはwriteToParcel()に処理を追加します。

追加する内容は、読み込みとペアで、readをwriteに書き換えていきます。

※ArrayList<XXX>の場合には、Parcel.writeTypedList()を呼び出す。
※Parcelalbeを実装したクラスを書きだすには、Parcel.writeParcelable(Parcel dest, int flags)を呼び出す。

※余談:感のよい方であれば、直列化/シリアライズ(Serialization)を想像されたと思いますが、
Parcelクラスは、あくまでもデータの永続化が(General)目的ではなく、
IPC(プロセス間通信)でハイパフォーマンスを得るためにデザインされたものだそうです。

Eclipseで、ソースコードを開いている時に、[Source]メニュー > [Organize Imports]をクリックすると、
不要なimportを削除することができます。

※Eclipse3.4 & Windowsの場合、Ctrl+Shift+Oキーでも同様。

Eclipseで、ソースコードを開いている時に、[Source]メニュー > [Format]をクリックすると、
ソースコードを整形することができます。

※Eclipse3.4 & Windowsの場合、Ctrl+Shift+Fキーでも同様。
※ソースコード整形のルールは、[Projects]メニュー > [Properties] > [Java Code Style] > [Formatter]から参照/変更できます。

  1. Windowメニュー > Preferences を選択
  2. (Preferences画面の)左側のAndroidを選択
  3. SDK LocationにSDKディレクトリを直接入力するか、Browse...をクリックしてディレクトリを選択
  4. Apply、OKをクリック

Android SDKディレクトリは、以下の(Windowsの例の)ようにSDKバージョン毎に分けて置いておくとよいでしょう。
C:\Android\android-sdk-windows-1.0_r1 ・・・ Android 1.0 SDK, Release 1
C:\Android\android-sdk-windows-1.0_r2 ・・・ Android 1.0 SDK, Release 2

[Android] Cursor.close()

| トラックバック(0) |

Thread内でSQLのquery操作をして、戻り値のCursolを参照するようなコードを書いていた際、

タイミングによっては、

Daemon System Thread [<5> HeapWorker] (Suspended (exception IllegalStateException)) 
 SQLiteCursor.finalize() line: 448 
 NativeStart.run() line: not available [native method]

のようなIllegalStateExceptionが発生しており、少しハマってしまいました。。。

解決方法は、Threadが終了するよりも前、かつ、DataBaseを閉じる前に

Cursol.close()

を挿入するだけでした。

たしかに、考えてみれば当然の流れですね。

リソースからXMLファイルを読み込むには?

android.content.resパッケージ
Resourcesクラス(※1)の
getXml()メンバ関数(※2)を呼び出します。

戻り値は、XmlResourceParserであり、
このクラスは、XmlPullParserインタフェースを実装しているので、
XMLの解析ができます。

※1
Resourcesクラスのインスタンスは、
Activity内であれば、getResources()で取得できます。
※getResources()は、 android.contentパッケージのContextクラスのメンバ関数。

※2
getXml()メンバ関数の第1引数は、リソースIDですので、
プロジェクト内のxmlリソース(/res/xml/hoge.xml)の
リソースID(R.xml.hogeなど)を指定してください。

Tips

REST系のアプリケーションを開発している際に、
デバッグのたびに動的にHTTPでXMLファイルを取得しなければならない場合、
同XMLファイルを、予めブラウザなどでアクセスしてファイル保存し、
上記のように静的にリソースに組み込んで、
XmlPullParserインスタンスが必要な個所を、
getXml()で書き換えてあげれば、(デバッグ用に固定の)XMLファイルを取得できるため、
デバッグ時間を短縮できたり、非ネットワーク環境下でも開発できます。

[Java] For-Eachループ

| トラックバック(0) |

For-Eachループ 

ArrayList<Integer> array = new ArrayList<Integer>();

のような配列の要素にアクセスする場合、

 

int length = array.size();
    
for (int i = 0; i < length; i++) {
    value = array.get(i);
}

の書き方で、配列の要素にアクセスすることができますが、

 

Java5(JDK1.5)で追加されたFor-Eachループでは、 

for (Integer value : array) {

}

と書くこともできます。

※Sunのドキュメントは、こちら(http://java.sun.com/j2se/1.5.0/ja/docs/ja/guide/language/foreach.html

 

後者の方が、読みやすく、安全ということみたいですが、処理時間はかかるみたいです。

実際に、Androidでコードを書いて計測してみると、
後者の方が、2~3倍処理時間がかかりました。

使用する場面に応じて使い分けるなど、留意した方が良さそうです。

Adobe AIRアプリケーションへのコードサイニング署名(アプリの電子署名・証明書)の記事は、
ADOBE DEVELOPER CONNECTIONにあります。
※こちら(http://www.adobe.com/jp/devnet/air/articles/globalsign_codesign.html)。

認証局

 ※Web Designing (ウェブデザイニング) 2009年 01月号 [雑誌] にも記事がありました。

123

2016年8月

  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31