ラベル CPU利用率ビューアー の投稿を表示しています。 すべての投稿を表示
ラベル CPU利用率ビューアー の投稿を表示しています。 すべての投稿を表示

2011年9月5日月曜日

アプリをアップデート

CPU利用率ビューアーと滞在地カレンダーをアップデートした。
CPU利用率ビューアーはデータがない場合にグラフに何も表示されない理由を示すメッセージを出すようにした。
滞在地カレンダーは充電後GPSを使用しなくなることがあるのを修正した。致命的なバグだ。なぜ気がつかなかったのだろうか。滞在地カレンダーについてはフリーズバグが1件報告されている。駄目だ、理由がわからない。スレッドがjoinできなくなったようだが、なぜ抜けられなくなったのだろうか。

2011年9月4日日曜日

コメントがついた

CPU利用率ビューアーでコメントがついた。「グラフ出ません。」おそらくデータがないからだろう。データがない場合にメッセージを出てどうすればいいかわかるように修正する予定。ヘルプには書いていたのだが、これではわからないな。公開するもののUIの基本がなってない。他のアプリなら見ればこのUIは駄目だ、とすぐわかるのに、自分に甘い。

2011年8月31日水曜日

アプリのアップデート

CPU利用率ビューアーで一件、障害報告があがっていたので、修正してアップデートした。なるほど、どこで例外が発生したのか、確認できるんだな。便利だ。

2011年8月29日月曜日

Boot時起動方法

Android OSがブートしたとき自動でサービスを開始させたい場合がある。BroadcastReceiverを実装することでできる。
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

public class TBroadcastReceiver extends BroadcastReceiver {

 @Override
 public void onReceive(Context context, Intent intent) {
  if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
   context.startService(new Intent(context, TProcessWatcherService.class));
        }
    }
}
AndroidManifest.xmlに作成したクラスを記述する。
<service android:enabled="true" android:name=".TProcessWatcherService" />
 <receiver android:name=".TBroadcastReceiver">
  <intent-filter>
   <action android:name="android.intent.action.BOOT_COMPLETED" />
  </intent-filter>
 </receiver>

アプリ情報の取得方法

パッケージ名から、アプリ名、アプリアイコンを取得できる。CPU利用率ビューアーではグラフを表示するプロセスを選択するために、この情報を使用した。

public String appname = null;
 public Drawable icon = null;
 private void getAppInfo(Context context) {
  PackageManager pm = context.getPackageManager();
  try {
   ApplicationInfo applicationinfo = pm.getApplicationInfo(pkgname, 0);
   icon = pm.getApplicationIcon(applicationinfo);
   appname = (String)pm.getApplicationLabel(applicationinfo);
  } catch (NameNotFoundException e) {
  }
 }

タイトルバー(アプリ名)を消す方法

デフォルトでAndroidアプリはタイトルバーにアプリ名が表示される。画面が狭くなるので消したい。AndroidManifest.xmlでActivityのプロパティを設定する。

<activity android:name=".TCPUUseRateWatcherActivity"
  android:theme="@android:style/Theme.NoTitleBar" android:label="@string/app_name">
  <intent-filter>
   <action android:name="android.intent.action.MAIN" />
   <category android:name="android.intent.category.LAUNCHER" />
  </intent-filter>
 </activity>

CPU使用率の計算方法5 (計算)

CPU使用率の計算方法1-4で述べた方法で、システムの実行時間(tick単位)、プロセスの実行時間(tick単位)、プロセスIDのリスト、USER_HZを取得することができる。さらに、実行時間(tick単位)を取得するときに、合わせて時刻を取得しておく (測定時刻(秒単位)) とすると、以下になる。 CPU使用率はシステム・プロセスともに、

(今回の実行時間(tick単位) - 前回の実行時間(tick単位)) / USER_HZ / (今回の測定時刻(秒単位) - 前回の計測時刻(秒単位))

で計算できる。CPU利用率ビューアーではこの計算結果をグラフ表示している。

CPU使用率の計算方法4 (USER_HZの取得)

CPU使用率の計算方法1, 2で書いたように、/proc/[pid]/stat, /proc/statから取得できる実行時間の単位はtickである。 http://www.kernel.org/doc/man-pages/online/pages/man5/proc.5.html を参考にすると、sysconf(_SC_CLK_TCK)を使って取得したUSER_HZで実時間に変換できることがわかる。具体的には、実行時間をsysconf(_SC_CLK_TCK)で割ることで、秒単位に変換することができる。しかし、USER_HZを取得するためのJava用のAPIはないようだ。多くのAndroidシステムのUSER_HZは100のようだが、異なるものも存在する。したがって、CPU利用率ビューアーではJNI経由で値を取得した。
#include <unistd.h>
#include <jni.h>

jlong Java_com_appspot_takuyaandroid_tcpuuseratewatcher_TUserHzJni_getUserHz(JNIEnv *env, jobject obj) {
 return sysconf(_SC_CLK_TCK);
}

CPU使用率の計算方法3 (プロセスID取得)

CPU使用率の計算方法2で書いたように、CPU使用率を計算するためには/proc/[pid]/statにアクセスする。したがって、[pid]が必要である。実行中のプロセスの情報はActivityManagerを使ってアクセスできる。

static public void insert(Context context) {
  ActivityManager am = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);
  List list = am.getRunningAppProcesses();
  long now = new Date().getTime();
  for (RunningAppProcessInfo info : list) {
   long tick = getTick(info.pid);
   String name = info.processName;
   TProcess p = new TProcess(info.pkgList[0], name, tick, 0, now);
   p.insert(context);
  }
  long tick = getTick();
  TKernel k = new TKernel(tick, 0, now);
  k.insert(context);
 }
上記は、CPU利用率ビューアーのソースの一部である。上記を定期的に呼び出して、CPU使用率を計算するために使う情報を現在時刻とセットで保存している(TProcess#insert/TKernel#insert)。パッケージ名を使用してアイコン等の情報を取得できるため、CPU利用率ビューアーでは保存している。 なお、上記ソースでは、現在時刻として保存した時刻と/proc/[pid]/stat, /proc/statにアクセスした時間にわずかだが差があり、情報として正確ではない。

CPU使用率の計算方法2 (プロセス)

AndroidはLinuxをベースにしているため、Linux同様、/proc/にアクセスして、プロセスの情報を取得することができる。
http://www.kernel.org/doc/man-pages/online/pages/man5/proc.5.html で書かれているように、/proc/[pid]配下から実行中のプロセスについての情報を取得できる。 CPU利用率ビューアーでは、/proc/[pid]/statの項目にあるプロセスのtick単位の実行時間(utime/stime)を使用した。
static private long getTick(int pid) {
  try {
   String filename = "/proc/" + pid + "/stat";
   String stat = load(filename);
   String[] split = stat.split(" +");
   return Integer.parseInt(split[13]) + Long.parseLong(split[14]);
  } catch (Exception e) {
   return 0;
  }
 }

 static private String load(String filename) {
  try {
   BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(filename)));
   String str = reader.readLine();
   if (str == null) return null;
   reader.close();
   return str;
  } catch (Exception e) {
  }
  return null;
 }

CPU使用率の計算方法1 (システム)

AndroidはLinuxをベースにしているため、Linux同様、/proc/にアクセスして カーネルに関する情報などを取得することができる。
http://www.kernel.org/doc/man-pages/online/pages/man5/proc.5.html で書かれているように、/proc/statから、システムが消費した時間(tick単位)を取得することができる。 Android端末で実際に/proc/statにアクセスしてみると、 cpu 970616 85105 578431 25520823 316076 976 33674 0 0 0 のような情報が取得できる。10項目存在する。上記のサイトでは、9項目までは説明がある。CPU利用率ビューアーでは、すべての項目の和を使用した。
static private long getTick() {
  try {
   String filename = "/proc/stat";
   String stat = load(filename);
   String[] split = stat.split(" +");
   long time = 0;
   for (int i = 1; i < split.length; i++) time += Long.parseLong(split[i]);
   return time;
  } catch (Exception e) {
   return 0;
  }
 }

 static private String load(String filename) {
  try {
   BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(filename)));
   String str = reader.readLine();
   if (str == null) return null;
   reader.close();
   return str;
  } catch (Exception e) {
  }
  return null;
 }

2011年8月26日金曜日

もう一つアプリをアップロード

Androidマーケットにアプリをもう一つアップロードした。アップロード時に、何度か「アップロードで予期しないエラーが発生しました。しばらくしてからもう一度お試しください。」と表示されて失敗した。ほんとうに、しばらくしてからアップロードすると成功したが、単にサーバーの性能の問題で失敗しているだけかなのかな。