speg03の雑記帳

主に未来の自分のために試したことなどを記録しています

UbuntuでKVMの作業メモ

環境

やったこと

# kvmインストール
$ sudo apt-get install kvm
$ sudo apt-get install virt-manager

# Ubuntu再起動が必要らしい(必要だったか確認してない)

# /dev/kvm がkvmグループになっていることを確認
$ ls -l /dev/kvm
crw-rw----+ 1 root kvm 10, 232 Jan 29 19:33 /dev/kvm

# KVMを使うユーザをkvmグループに追加
$ sudo adduser speg03 kvm
ユーザ `speg03' をグループ `kvm' に追加しています...
ユーザ speg03 をグループ kvm に追加
終了。

# KVMが有効かどうか確認
$ lsmod | grep kvm
kvm_intel              56851  0 
kvm                   367707  1 kvm_intel

# 実行してみる
$ kvm -monitor stdio
kvm: pci_add_option_rom: failed to find romfile "pxe-rtl8139.bin"
QEMU 0.14.0 monitor - type 'help' for more information
(qemu) info kvm
kvm support: enabled
(qemu) quit

# libvirtdデーモンの起動確認
$ pgrep -lf libvirtd
2920 /usr/sbin/libvirtd -d

# GUIで仮想マシンを作る
$ sudo virt-manager

# CUIで仮想マシンを作る
$ sudo virt-install --connect qemu:///system \
  --name testvm1 \
  --ram 512 \
  --disk path=/media/ext/kvm/testvm1/testvm.img,size=2 \
  --network network=default,model=virtio \
  --vnc \
  --cdrom /media/ext/isos/CentOS-6.0-x86_64-minimal.iso

# こんなん出た
WARNING  Unable to connect to graphical console: virt-viewer not installed. Please install the 'virt-viewer' package.

# 言われるとおりにインストールする
$ sudo apt-get install virt-viewer

TextViewのテキストサイズ指定

TextViewなどのテキストサイズをJavaのコードから動的に変更しようとして、はまりそうだったのでメモ。

ちなみに今回の実行環境はAndroid 2.2 (API Level 8)を使った。この環境だとデフォルトで以下のようなAndroidManifest.xmlの設定が有効になっていることになる。

<supports-screens android:anyDensity="true" />

Android 1.6 (API Level 4)よりも低い場合はanyDensityのデフォルト値がfalseになる。anyDensityの値がfalseの場合はまた話が変わってくるので注意が必要。

このあたりの話は以下を参考に。

テキストサイズの定義と取得方法

このページのDimensionの項を見るとテキストサイズの定義とXMLファイルでの取得方法、Javaコードでの取得方法がわかる。以下のような感じ。

テキストサイズの定義
<resources>
  <dimen name="font_size">16sp</dimen>
<resources>
XMLファイルでのテキストサイズの取得方法
@dimen/font_size
Javaコードでのテキストサイズの取得方法
Resources res = getResources();
float fontSize = res.getDimension(R.id.font_size);

試してみる

XMLファイルでの指定とJavaコードでの指定のそれぞれについて2種類のテキストサイズを指定してみる。

res/values/dimens.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
  <dimen name="font_size_small">16sp</dimen>
  <dimen name="font_size_large">32sp</dimen>
</resources>
res/layout/main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

  <!-- 小さいテキスト(XML指定) -->
  <TextView
      android:id="@+id/smallTextXml"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:textSize="@dimen/font_size_small"
      android:text="Small Text (XML)" />

  <!-- 小さいテキスト(コード指定) -->
  <TextView
      android:id="@+id/smallTextCode"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="Small Text (Code)" />

  <!-- 大きいテキスト(XML指定) -->
  <TextView
      android:id="@+id/largeTextXml"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:textSize="@dimen/font_size_large"
      android:text="Large Text (XML)" />

  <!-- 大きいテキスト(コード指定) -->
  <TextView
      android:id="@+id/largeTextCode"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="Large Text (Code)" />

</LinearLayout>

XML指定と書いてあるTextViewはtextSize属性に先ほど定義したテキストサイズを指定している。コード指定と書いてあるTextViewはJavaコードからテキストサイズを指定するためここでは指定していない。

TextSizeSampleActivity.java (間違ったコード)
import android.app.Activity;
import android.content.res.Resources;
import android.os.Bundle;
import android.widget.TextView;

public class TextSizeSampleActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        Resources res = getResources();
        float fontSizeSmall = res.getDimension(R.dimen.font_size_small);
        float fontSizeLarge = res.getDimension(R.dimen.font_size_large);

        // 小さいテキストのテキストサイズを指定
        TextView smallTextCode = (TextView) findViewById(R.id.smallTextCode);
        smallTextCode.setTextSize(fontSizeSmall);

        // 大きいテキストのテキストサイズを指定
        TextView largeTextCode = (TextView) findViewById(R.id.largeTextCode);
        largeTextCode.setTextSize(fontSizeLarge);
    }

}

先ほどの例にしたがってテキストサイズを取得。setTextSizeメソッドでテキストサイズを指定している。

実行結果(間違ったコード)

HVGAの場合


WVGA800の場合

HVGAの場合はXML指定とコード指定で同じ大きさになっているので問題がなさそうだけど、WVGA800の場合はXML指定とコード指定で大きさが異なっている。

修正

正しいコードは以下のようになる。

TextSizeSampleActivity.java (正しいコード)
import android.app.Activity;
import android.content.res.Resources;
import android.os.Bundle;
import android.util.TypedValue;
import android.widget.TextView;

public class TextSizeSampleActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        Resources res = getResources();
        float fontSizeSmall = res.getDimension(R.dimen.font_size_small);
        float fontSizeLarge = res.getDimension(R.dimen.font_size_large);

        // 小さいテキストのテキストサイズを設定
        TextView smallTextCode = (TextView) findViewById(R.id.smallTextCode);
        // ※ 設定値の単位を指定するようにした
        smallTextCode.setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSizeSmall);

        // 大きいテキストのテキストサイズを設定
        TextView largeTextCode = (TextView) findViewById(R.id.largeTextCode);
        // ※ 設定値の単位を指定するようにした
        largeTextCode.setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSizeLarge);
    }

}

実行結果(正しいコード)

WVGA800の場合

これでXML指定とコード指定で同じ大きさになった。

何が問題だったか

要するに

Resources res = getResources();
float fontSize = res.getDimension(R.id.font_size);

このコードで取得できるテキストサイズはpx単位なのに

TextView#setTextSize(float)

これで指定するテキストサイズがsp(scaled pixel)単位だったのが問題だった。

sp単位は160dpiを1として実際の解像度に合わせた比率で実際のpx単位を求める。なので、sp単位の値を受け取るsetTextSizeメソッドが計算済みのpx単位の値を受け取ったので大きさがずれてしまっていた。

HVGAの場合で問題がなかったのはHVGAの仮想デバイスを作成するときデフォルトで解像度が160dpiになっているためだった。

Gmailの受信通知インテントを受け取ってみた

Android端末でGmailのメール受信通知を受け取ってアレコレしたかったので調べたよ。

メール受信時のインテント

端末をPCにつないでLogCatで眺めるだけ。以下のようなインテントを見つけられる。

06-12 20:51:00.550: INFO/Gmail(10262): Sending notification intent: Intent { act=android.intent.action.PROVIDER_CHANGED dat=content://gmail-ls/unread/^iim (has extras) }
06-12 20:51:00.589: INFO/Gmail(10262): Sending notification intent: Intent { act=android.intent.action.PROVIDER_CHANGED dat=content://gmail-ls/unread/^i (has extras) }

PROVIDER_CHANGEDはandroid.content.Intentのリファレンスによるとブロードキャストなのでブロードキャストレシーバを作って受け取ってみた。

メール受信時のブロードキャストレシーバ

以下のような感じ。extrasの中身も見てみる。

AndroidManifest.xmlの一部
<receiver android:name=".Receiver" android:label="receiver">
  <intent-filter>
    <action android:name="android.intent.action.PROVIDER_CHANGED" />
    <data android:scheme="content" android:host="gmail-ls"
      android:path="/unread/^i" />
  </intent-filter>
</receiver>
Receiver.java
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

public class Receiver extends BroadcastReceiver {
    private static final String TAG = "Receiver";

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d(TAG, "You've Got Mail!!");
        for (String key : intent.getExtras().keySet()) {
            Log.d(TAG, key + ": " + intent.getExtras().get(key));
        }
    }

}

実行結果

こんな感じ。

06-12 20:51:00.550: INFO/Gmail(10262): Sending notification intent: Intent { act=android.intent.action.PROVIDER_CHANGED dat=content://gmail-ls/unread/^iim (has extras) }
06-12 20:51:00.589: INFO/Gmail(10262): Sending notification intent: Intent { act=android.intent.action.PROVIDER_CHANGED dat=content://gmail-ls/unread/^i (has extras) }
06-12 20:51:00.601: DEBUG/Receiver(10248): You've Got Mail!!
06-12 20:51:00.601: DEBUG/Receiver(10248): count: 1
06-12 20:51:00.601: DEBUG/Receiver(10248): account: speg03@gmail.com
06-12 20:51:00.601: DEBUG/Receiver(10248): tagLabel: ^^unseen-^i
06-12 20:51:00.601: DEBUG/Receiver(10248): getAttention: true

メールの件数とアカウント名は分かるようだけどタイトルや本文まで取れるのかはわからなかった。2つあるインテントの違いもよくわからない。extrasもtagLabelの末尾にimが付いているかどうかの違いしかなく、他の値は同じようだった。

あと、通知を受信したあとでPC側からそのメールを既読にすると、その変更も同じインテントで通知される。以下がそれ。

06-12 20:53:11.054: INFO/Gmail(10262): Sending notification intent: Intent { act=android.intent.action.PROVIDER_CHANGED dat=content://gmail-ls/unread/^iim (has extras) }
06-12 20:53:11.082: INFO/Gmail(10262): Sending notification intent: Intent { act=android.intent.action.PROVIDER_CHANGED dat=content://gmail-ls/unread/^i (has extras) }
06-12 20:53:11.093: DEBUG/Receiver(10248): You've Got Mail!!
06-12 20:53:11.093: DEBUG/Receiver(10248): count: 0
06-12 20:53:11.093: DEBUG/Receiver(10248): account: speg03@gmail.com
06-12 20:53:11.093: DEBUG/Receiver(10248): tagLabel: ^^unseen-^i
06-12 20:53:11.093: DEBUG/Receiver(10248): getAttention: false

countが減っているのとgetAttention(通知動作を行うかどうかかな?)が変わっている。

UnityでEclipseのメニューが表示されない

Unityのグローバルメニューが有効になっているとEclipseのメニューがほとんど表示されなかった。Fileしか表示されないと言っている人やバグレポートが上がっていたようだけど、私の環境ではWindowしか表示されなかった。

そこで以下のようなスクリプトを使ってEclipseを起動するように変更する。

#!/bin/sh
unset UBUNTU_MENUPROXY
exec /path/to/eclipse

するとグローバルメニューではなくて、通常通りウィンドウに正しいメニューが表示される。

Eclipse以外でも同様の問題があった場合は同じようにunset UBUNTU_MENUPROXYすればよさそう。

Chromiumのフォント設定

Chromiumでフォント設定が有効になっていなかったようなので。通常の設定画面からは変更が反映されないらしい。

どうするかというと適当なWebページの入力フォームを右クリックした先の言語設定から設定する。

なんともバッドノウハウ的な感じですけれども。

ホームの日本語ディレクトリを英語にする

日本語環境だとホームディレクトリにドキュメントやらダウンロードやら日本語名のフォルダが並んでいるのでこれを英語名に変えたいとき。

$ LANG=C xdg-user-dirs-gtk-update

このままだと次回ログイン時に元に戻すか聞かれてしまうので聞かれないようにする。

システムの設定 > 自動起動するアプリケーション > ユーザ・フォルダの更新

のチェックを外す。

Ubuntu 11.04でXmodmapしてるとテーマが崩れる

どうしてこうなるのか結局よくわからないのだけど、ログイン時にXmodmapでキーマップを変更しているとウィンドウテーマが崩れる。崩れるという表現も合ってるのかわからないけど、要は以下のような感じになる。

正しい表示

崩れた表示

崩れたというか古めかしい感じのスタイルになってしまう。~/.Xmodmapを消してみると正しい表示になった。

なおった、なおった。めでたし、めでたし。……というわけには当然いきませんで。Xmodmap使えないのは困るのです。

ちなみに.Xmodmapの中身は以下。

keycode 102 = Alt_L

Xmodmapをどう呼ぶか

xmodmapコマンドには直接式を指定して実行するオプションがあるので、それを実行するスクリプトを書いて自動起動するアプリケーションに追加した。

こんなやつ

#!/bin/sh
xmodmap -e 'keycode 102 = Alt_L'

自動起動するアプリケーションの登録はシステムの設定から。

なんだかちょっと気になるやり方だけどまぁうまくいっているので良いことにしてる。

追記 2011-05-12 19:54

どうにもちょくちょくうまくいってない時があるみたい。タイミングが悪いのかしら。

また調べているといろいろ見つかりました。
.Xmodmapじゃなくて.xmodmaprcだったら大丈夫とのこと。実際、大丈夫のようだったのでしばらくこれで様子見ます。

で、一度テーマが変わってしまってからだと以下のようにすれば戻るみたい。

$ sudo gnome-settings-daemon

以下を参考にしました。