Chromium OS build memo

GoogleのChromium OSをビルドしたときのメモ

以下のページの通りにビルドする。特に問題は発生しなかった。

http://www.chromium.org/chromium-os/developer-guide

ところが、VM用のイメージ(chromiumos_qemu_image.bin)を作成し、

VM用イメージの作成(http://www.chromium.org/chromium-os/developer-guide#TOC-Building-an-image-to-run-in-a-virtu)
./image_to_vm.sh –board=x86-generic

これをWindows上のQEMUで動かそうとしたが動かなかった。

以下のコマンド

C:Program Filesqemu>qemu-system-i386 -m 1024 -hda “D:Virtual Machineschromiumos_qemu_image.bin”

そこで、イメージをVMWare用に変換して試したところ、VMWareでは開くことができた。

QEMU用イメージをVMWare用イメージ(VMDK)に変換

C:Program Filesqemu>qemu-img convert -O vmdk chromiumos_qemu_image.bin chromiumos_vmware_image.vmdk

このイメージをVMWareで開くには

まず、空のHDDでVMを作成し、空のHDDをはずして、上で作成したVMDKイメージを追加する。

VMWareでネットワークを認識できない場合は、VMのネットワーク設定で以下を試す。

1. “Bridged” を選択し、”Replicate physical connection state”のチェックははずす(http://www.petri.co.il/installing-chromium-in-vmware-player-3-0.htm
2. “NAT” を選択し、 .vmx ファイルに以下の行を追加(http://superuser.com/questions/539016/setup-chrome-os-hexxeh-in-vmware-player-without-network
ethernet0.virtualDev = “e1000″

VMで起動できたので、実際のノートPCでの起動を試すと、初期ログイン画面でWiFiのSSIDを選んでパスワードを入力しても、WiFiが「Out Of Range」とのメッセージがでて、次にすすめない。ネットで検索すると、この部分はBrowserの処理なので、browserを最新にすると解消するらしい。

https://code.google.com/p/chromium/issues/detail?id=236417

browserのソースは以下の手順でビルドできるはずだが・・・

http://www.chromium.org/chromium-os/how-tos-and-troubleshooting/building-chromium-browser

どうしても以下のエラーがでてビルドできなかった。

Fatal error: chrome/browser/chromeos/drive/drive.pb.h: No such file……

そこで、Browserだけをビルドする手順を実施

https://code.google.com/p/chromium/wiki/LinuxBuildInstructions

exit chroot
cd ~/chromium
gclient config http://git.chromium.org/chromium/src.git
gclient sync
chrome_set_ver –runhooks
cd src
build/install-build-deps.sh
GYP_GENERATORS=ninja gclient runhooks
export GYP_DEFINES=”chromeos=1 werror=”
build/gyp_chromium
ninja -C out/Release

ビルドすると、生成物の中にエラーの原因となっていた以下のファイルが含まれていたので、

/home/chromiumos/chromium/src/out/Release/gen/protoc_out/chrome/browser/chromeos/drive/drive.pb.h

以下のフォルダ以下のファイルを

/home/chromiumos/chromium/src/out/Release/gen/protoc_out/

以下のフォルダにコピー(※リンクをはるほうが良かったかもしれない)

/home/chromiumos/chromium/src/

ディスク容量が逼迫してきたので、古い生成物を削除して

enter chroot
./chromite/bin/cros_sdk
rm -rf /var/cache/chromeos-chrome/chrome-src/src/out_*

もう一度ビルドしてみた。

export CHROME_ORIGIN=LOCAL_SOURCE
cros_workon –board=x86-generic start chromeos-chrome

./build_packages –board=x86-generic

これで、前述のエラーはなくなり、ビルドできた。WiFiが「Out Of Range」になるエラーも解消されていた。

 

 

Paging(Swipe)するViewの作成

画面を指で左右にめくる操作・・・。最もスマホ的な操作かと思っていたのに、Androidでの実装には別のライブラリを追加するなど、少し面倒な作業が必要でした。(便利なテンプレートを用意してくれるAppleとの差はまだ大きい・・・ 訂正、新しいSDKではテンプレートが用意されていました。)

とはいえ、以下のページにサンプルコード付きで説明されているので、やり方は簡単。要はGallaryと同じようにAdapterを使うだけです。

http://developer.android.com/training/implementing-navigation/lateral.html#horizontal-paging
ここでは、ApiDemo のGallary を元にして、Swipeで操作できるように改造してみました。(ソース

1. FragmentActivity にする

  • Support Libraryをダウンロードする

http://developer.android.com/tools/extras/support-library.html

ここからダウンロードして、android-support-v4.jar を プロジェクトのlibフォルダにコピー。ライブラリのPathにも追加(Java build pathにAdd Jar…)します。(libにコピーじゃなくて、直接Add External Jar…でも大丈夫かもしれません。)

2. ソースに以下のimportを追加

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v4.app.FragmentActivity;

3. Activityの基本クラスをActivityからFragmentActivityに変更

public class SwipeViewActivity extends FragmentActivity {...}

4. Adapter を実装

FragmentStatePagerAdapter を継承するクラスを作成

Overrideする必要があるのは以下の2つ

Fragment getItem(int)

int getCount()

Fragmentは、めくられるページ(View)の内容を保持します。getItem(int) の引数としてページの番号が与えられるので、それをもとに、ページの内容を作成するのに必要な情報を持ったFragmentのオブジェクトを作成して返します。

例えば、現在のページ番号だけ分かればいいのであれば、引数のintを直接渡してしまえばOK

	public class CollectionPagerAdapter extends
 	FragmentStatePagerAdapter {
		public CollectionPagerAdapter(FragmentManager fm) {
			super(fm);
		}

		@Override
		public Fragment getItem(int i) {
		     Fragment fragment = new ObjectFragment();
		     Bundle args = new Bundle();
		     // Our object is just an integer :-P
		     args.putInt(ObjectFragment.ARG_OBJECT, i);
		     fragment.setArguments(args);
		     return fragment;
		}

		@Override
		public int getCount() {
		     return mImageIds.length;
		}
	}

5. Fragment を実装

Fragmentを継承するクラスを作成します

リソースにある画像のIDを配列で保持し、その画像をViewで表示する例です

画像のIDを配列はこのように定義(ApiDemoのGallaryのをコピーして使用)

    static private final Integer[] mImageIds = {
            R.drawable.gallery_photo_1,
            R.drawable.gallery_photo_2,
            R.drawable.gallery_photo_3,
            R.drawable.gallery_photo_4,
            R.drawable.gallery_photo_5,
            R.drawable.gallery_photo_6,
            R.drawable.gallery_photo_7,
            R.drawable.gallery_photo_8
    };

リソースの画像を表示するViewを作成して返します。

	public static class ObjectFragment extends Fragment {
		public static final String ARG_OBJECT = "object";
		private Bitmap mBmp = null;

		@Override
		 public View onCreateView(LayoutInflater inflater,
		         ViewGroup container, Bundle savedInstanceState) {
		     // The last two arguments ensure LayoutParams are inflated
		     // properly.
			ImageView imgView = (ImageView)inflater.inflate(
		             R.layout.imageview, container, false);
		    Bundle args = getArguments();
		    int position = (int) args.getInt(ARG_OBJECT);
		    imgView.setImageResource(mImageIds[position]);
		    imgView.setScaleType(ImageView.ScaleType.FIT_CENTER);
		    return imgView;
		 }
	}

6. 画面リソース(main.xml)を定義

android.support.v4.view.ViewPager を使います。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <android.support.v4.view.ViewPager android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_alignParentTop="true"
        android:layout_alignParentLeft="true" android:id="@+id/imageviewpager"/>

</LinearLayout>

7. Fragmentで作成するViewのxml定義。Layoutは要らない。(もちろん、XMLを使わず、動的に作成してもいいはず)

<?xml version="1.0" encoding="utf-8"?>
    <ImageView xmlns:android="http://schemas.android.com/apk/res/android" 
        android:layout_width="fill_parent" 
        android:layout_height="fill_parent" 
android:id="@+id/imageview"/>

8. ViewPagerにAdapterを設定

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        ViewPager pager = (ViewPager) findViewById(R.id.imageviewpager);
        pager.setAdapter(new CollectionPagerAdapter(getSupportFragmentManager()));
    }

動かしてみるとこんな感じです(ページをめくろうとしているところ)

swipe

ローカライゼーション(多言語対応)(Android)

res フォルダの下にある各リソースのフォルダをコピーして、フォルダ名の後ろにハイフン(”-”)に続けてロケールを指定する。例えば ”values”フォルダの日本語なら”values-ja”。このフォルダの内容を日本語のもので置き換える。リソースのIDは変更しない。

なお、リソースを編集した後は、Javaのソースに一部変更を加えて(例えばスペースや改行を追加するなど)ソースがコンパイルされるようにしないと、xml.outという拡張子のファイルが作成されてしまい、エラーになることがあるので注意。

ライブラリ参照の追加でエラー’setting build path has encountered a problem’

Eclipse でライブラリのJarを追加しようとしても、’setting build path has encountered a problem’とのエラーで追加できない場合。

⇒プロジェクトの”.classpath”ファイルのHidden属性を外すと直ります。

<参照>

http://stackoverflow.com/questions/1888075/eclipse-error-setting-build-path-has-encountered-error

GPSの位置情報を取得する (Android)

AndroidでGPSの位置情報を取得してみます。

位置情報は、主にGPSと携帯基地局の情報から取得できます。

手順としては、まずLocationManagerを取得し

LocationManager lm =

(LocationManager) getSystemService(Context.LOCATION_SERVICE);

最後に取得した情報を取得するには LocationManagerのgetLastKnownLocation()を使用します。

そして、最新の情報を取得するには、LocationManagerのrequestLocationUpdates() を呼び出します。このとき、Location Provider(GPSまたは携帯基地局)を指定します。また、位置を取得した後の動作として、 LocationListenerを定義して通知を受ける方法と、Intentを指定する方法があります。

位置情報が更新されるとLocation Listener の onLocationChanged(Location location) が呼び出されます。ここで引数として与えられる Location が位置情報です。

通知を受け取らないようにする(位置情報の取得を停止する)には removeUpdates()を呼び出します。

参考資料

バックグランドでもアプリを動かし続けるには?(iOS)

UIApplication.applicationDidEnterBackground  で beginBackgroundTaskWithExpirationHandler を呼び出すようにとの資料があったが

https://developer.apple.com/library/ios/#documentation/UIKit/Reference/UIApplicationDelegate_Protocol/Reference/Reference.html#//apple_ref/occ/intfm/UIApplicationDelegate/applicationDidEnterBackground:

beginBackgroundTaskWithExpirationHandler は”You should not use this method simply to keep your application running after it moves to the background.”と書いてあるので、これを使ってはいけない気がするが。。。では、どうしたらいいのだろう’?

しかし、とりあえず beginBackgroundTaskWithExpirationHandler を呼び出す方法を使ってみたところ、エミュレータではちゃんとバックグランドで動いたし、別に問題ないように見える。

画面の向きが変わったときにメンバ変数の値もクリアされてしまう(Android)

画面の向きが変わったときにメンバ変数の値もクリアされてしまう

なぜかAndroidでは画面の向きを変えたときに、Activity.onCreate() が呼ばれる、つまりActivityが再作成されている。このとき、クラスのメンバ変数の値もクリアされてしまう。この問題は以下の3つの方法で回避できた。

1)画面の向きを固定にする

Activity.onCreate()で setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) を呼び出す。画面の向きを変える必要がないときは、これが一番簡単で、スムーズで、安定している。

2)Activityの終了時に値を保存して、新しいActivityの開始時に再設定する

SharedPreferences を使う。面倒だが、これが一番推薦されているように思える。

3)変数を static にする

正しいやり方なのかわからないが、これで回避できた。新しいActivityも同一プロセス内にあるということらしい。

画面の向きを変える

なお、2)と3)では、画面の向きにあわせてデザインを変えた方が使いやすいはず。

これも正しいやり方なのかわからないが、Displayの縦横比で方向を判断してレイアウトを切り替える方法がある。

Activity.onCreate()内でhorizontal と landscape レイアウトを使い分けるサンプル

        int orientation = getWindowManager().getDefaultDisplay().getOrientation();
        if(orientation == 0) {
            setContentView(R.layout.main);        
        }
        else {
            setContentView(R.layout.main_l);                
        }

UIPickerViewを使う(iOS)

1.xlbファイルにPickerViewを追加

2.UIPickerViewDelegateとUIPickerViewDataSourceを実装、xlbファイルのFileOwnerであるViewControllerに実装しても可。

3.xlb上で、PickerViewのDataSourceとDelegateに関連づける

datasourceとdelegateの設定
datasourceとdelegateの設定

4.ViewControllerにPickerViewのOutletを追加。初期値の設定や選択された値の取得はこのOutletで行う。

Custom Viewを作成(iOS)

SingleView でプロジェクトを作成 xlbを開き、既存のViewの上にラベルやボタンなどのコントロールと、CustomView用のUIViewを乗っける。

新規にUIViewを継承するクラスを作成し、さっき追加したCustomView用のObjectに関連づける。

作成したクラスの drawRect に描画のコードを追加。UIBezierPathを使って円弧を塗りつぶす。

ここで、1つひっかかってしまったのは、Pathに弧の部分だけを描いても思ったように塗りつぶせないこと。AndroidのCanvas.drawArcメソッドのuseCenterパラメータがfalseと同じ状態になり、弧の始点と終点を直線で結んだ内部だけが塗りつぶされる。円の中心も含めるには、Pathに明示的に円の中心までの直線を追加する必要がある。なお、塗りつぶし(fill)の場合は、Pathの始点と終点が自動的に直線で結ばれる(closeされる)が、線を描く(stroke)場合は、明示的に始点と終点を結ぶ線を追加するか、あるいはclosePathメソッドを呼び出さないと、開放されたPathのままで描かれる。

円弧を塗りつぶすコード例

    //draw filled arc for tic
    UIBezierPath *pathTic1 = [UIBezierPath bezierPathWithArcCenter:c radius:r startAngle:st1 endAngle:en1 clockwise:true];
    //Close the path.
    [pathTic1 addLineToPoint:c]; 

    // Set the render colors
    [[UIColor redColor] setFill];

    // Fill the path
    [pathTic1 fill];