package jp.ac.uu.is.degas.android.wifi;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.FontMetrics;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class WifiViewActicvity extends Activity {
private static final int MENU_START = 0;
private static final int MENU_PAUSE = 1;
private static final int MENU_QUIT = 2;
private MySurfaceView mySurfaceView;
private WifiManager mWifiManager;
private boolean run;
private static final float MIN_LEVEL = -120;
private static final float MAX_LEVEL = 0;
private static final int TIME_BUFFDER_SIZE = 50;
private HashMap
private long cnt;
private int[] lineColor = { Color.BLUE, Color.CYAN, Color.GREEN,
Color.MAGENTA, Color.RED, Color.YELLOW, Color.WHITE };
private int indexOfColor;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mySurfaceView = new MySurfaceView(getApplication(), 0,
TIME_BUFFDER_SIZE, MIN_LEVEL, MAX_LEVEL, TIME_BUFFDER_SIZE,
(int) ((MAX_LEVEL - MIN_LEVEL) / 10));
setContentView(mySurfaceView);
apMap = new HashMap
run = false;
cnt = 0;
indexOfColor = 0;
}
private void startScan() {
run = true;
mWifiManager = (WifiManager) getSystemService(WIFI_SERVICE);
registerReceiver(mBroadcastReceiver, new IntentFilter(
WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
mWifiManager.startScan();
}
private void pauseScan() {
run = false;
}
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
List
for (ScanResult result : scanResults) {
String bssid = result.BSSID;
int level = result.level;
AccessPoint ap = apMap.get(bssid);
if (ap == null) {
ap = new AccessPoint(TIME_BUFFDER_SIZE + 1);
ap.setColor(lineColor[indexOfColor]);
indexOfColor++;
indexOfColor %= lineColor.length;
}
ap.setLevel(cnt, Float.valueOf(level));
ap.setUpdate(true);
apMap.put(bssid, ap);
}
for (Map.Entry
AccessPoint ap = e.getValue();
if (!ap.isUpdate()) {
ap.setLevel(cnt, null);
}
ap.setUpdate(false);
apMap.put(e.getKey(), ap);
}
if (run) {
mySurfaceView.setData(cnt, apMap);
cnt++;
startScan();
}
}
};
@Override
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(0, MENU_START, 0, "START").setIcon(
android.R.drawable.ic_media_play);
menu.add(0, MENU_PAUSE, 0, "PAUSE").setIcon(
android.R.drawable.ic_media_pause);
menu.add(0, MENU_QUIT, 0, "QUIT").setIcon(
android.R.drawable.ic_menu_close_clear_cancel);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case MENU_START:
startScan();
break;
case MENU_PAUSE:
pauseScan();
break;
case MENU_QUIT:
finish();
break;
}
return super.onContextItemSelected(item);
}
}
class AccessPoint {
private Float[] data;
private boolean update;
private int color;
AccessPoint(int size) {
data = new Float[size];
}
void setLevel(long cnt, Float level) {
data[(int) (cnt % data.length)] = level;
}
void setUpdate(boolean update) {
this.update = update;
}
boolean isUpdate() {
return update;
}
void setColor(int color) {
this.color = color;
}
int getColor() {
return color;
}
Float[] getData() {
return data;
}
}
class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback,
Runnable {
private SurfaceHolder mSurfaceHolder;
private Thread thread;
private Canvas canvas;
private MyGraph myGraph;
private float minX, maxX, minY, maxY;
private int numDivX, numDivY;
private long cnt;
private HashMap
MySurfaceView(Context context, float minX, float maxX, float minY,
float maxY, int numDivX, int numDivY) {
super(context);
mSurfaceHolder = getHolder();
mSurfaceHolder.addCallback(this);
myGraph = new MyGraph();
this.minX = minX;
this.maxX = maxX;
this.minY = minY;
this.maxY = maxY;
this.numDivX = numDivX;
this.numDivY = numDivY;
}
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
public void surfaceCreated(SurfaceHolder holder) {
thread = new Thread(this);
thread.start();
}
public void surfaceDestroyed(SurfaceHolder holder) {
thread = null;
}
public void run() {
while (thread != null) {
canvas = mSurfaceHolder.lockCanvas();
myGraph.drawRule(canvas);
String[] bssidName = new String[apMap.size()];
int[] bssidColor = new int[apMap.size()];
int num = 0;
for (Map.Entry
AccessPoint ap = e.getValue();
Float[] originalData = ap.getData();
int size = originalData.length;
Float[] data = new Float[2 * size];
for (int i = 0; i < size; i++) {
data[2 * i] = Float.valueOf(i);
data[2 * i + 1] = (cnt < size) ? originalData[i]
: originalData[(int) ((i + cnt + 1) % size)];
}
myGraph.drawLines(canvas, data, ap.getColor());
bssidName[num] = e.getKey();
bssidColor[num] = ap.getColor();
num++;
}
if (apMap.size() > 0) {
myGraph.drawLegend(canvas, bssidName, bssidColor);
}
mSurfaceHolder.unlockCanvasAndPost(canvas);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
}
}
}
@Override
protected void onSizeChanged(int width, int heigh, int old_w, int old_h) {
int size = (width < heigh) ? width : heigh;
myGraph.setDarwArea(size, size, minX, maxX, minY, maxY, numDivX,
numDivY, false, true);
}
void setData(long cnt, HashMap
this.cnt = cnt;
this.apMap = apMap;
}
}
class MyGraph {
private static final float TOP_MARGIN_RATIO = 0.05f; // 描画エリアサイズに対する上マージンの比
private static final float BOTTOM_MARGIN_RATIO = 0.05f; // 描画エリアサイズに対する下マージンの比
private static final float LEFT_MARGIN_RATIO = 0.05f; // 描画エリアサイズに対する左マージンの比
private static final float RIGHT_MARGIN_RATIO = 0.05f; // 描画エリアサイズに対する右マージンの比
private boolean labelFlagX; // X軸ラベル表示フラグ
private boolean labelFlagY; // Y軸ラベル表示フラグ
private Paint paintLabel = new Paint();
private float bodyW; // ラベルを含むグラフエリア
private float bodyH; // ラベルを含むグラフエリア
private float graphW; // ラベルを含まないグラフエリア
private float graphH; // ラベルを含まないグラフエリア
private float graphOriginX; // ラベルを含まないグラフエリアの原点
private float graphOriginY; // ラベルを含まないグラフエリアの原点
private float minX, maxX, minY, maxY;
private int numDivX, numDivY;
private float legendOriginX; // 凡例原点
private float legendOriginY; // 凡例原点
private Paint legendLabel = new Paint();
void setDarwArea(float drawW, float drawH, float xMin, float xMax,
float yMin, float yMax, int xDivNum, int yDivNum,
boolean labelXFlag, boolean labelYFlag) {
this.minX = xMin;
this.maxX = xMax;
this.minY = yMin;
this.maxY = yMax;
this.numDivX = xDivNum;
this.numDivY = yDivNum;
this.labelFlagX = labelXFlag;
this.labelFlagY = labelYFlag;
// ラベルを含むグラフエリア
bodyW = (1 - LEFT_MARGIN_RATIO - RIGHT_MARGIN_RATIO) * drawW;
bodyH = (1 - TOP_MARGIN_RATIO - BOTTOM_MARGIN_RATIO) * drawH;
// ラベルを含まないグラフエリア
FontMetrics fontMetrics = paintLabel.getFontMetrics();
graphH = bodyH;
if (labelXFlag) {
graphH += (fontMetrics.top + fontMetrics.bottom);
}
graphW = bodyW;
if (labelYFlag) {
float maxTextWidth = 0;
for (int i = 0; i < yDivNum + 1; i++) {
String text = String
.valueOf(yMin + i * (yMax - yMin) / yDivNum);
float baseX = paintLabel.measureText(text); // テキスト幅
maxTextWidth = (baseX > maxTextWidth) ? baseX : maxTextWidth;
}
graphW -= maxTextWidth;
}
// ラベルを含まないグラフエリアの原点
graphOriginX = LEFT_MARGIN_RATIO * drawW + (bodyW - graphW);
graphOriginY = TOP_MARGIN_RATIO * drawH;
// 凡例原点
legendOriginX = graphOriginX + 0.05f * graphW;
legendOriginY = graphOriginY + 0.05f * graphH;
}
/* グラフの罫線、軸描画 */
void drawRule(Canvas canvas) {
// 背景色
canvas.drawColor(Color.WHITE);
// 罫線
Paint paintRule = new Paint();
paintRule.setStyle(Paint.Style.FILL);
paintRule.setColor(Color.BLACK);
for (int i = 0; i < numDivX + 1; i++) {
canvas.drawLine(graphOriginX + i * (graphW / numDivX),
graphOriginY, graphOriginX + i * (graphW / numDivX),
graphOriginY + graphH, paintRule);
}
for (int i = 0; i < numDivY + 1; i++) {
canvas.drawLine(graphOriginX,
graphOriginY + i * (graphH / numDivY), graphOriginX
+ graphW, graphOriginY + i * (graphH / numDivY),
paintRule);
}
// 軸ラベル
paintLabel.setColor(Color.GRAY);
FontMetrics fontMetrics = paintLabel.getFontMetrics();
if (labelFlagX) {
for (int i = 0; i < numDivX + 1; i++) {
String text = String
.valueOf(minX + i * (maxX - minX) / numDivX);
float baseX = paintRule.measureText(text) / 2; // テキスト幅の半分
float baseY = -fontMetrics.top; // baselineからtopまでの高さ
canvas.drawText(text, graphOriginX + i * (graphW / numDivX)
- baseX, graphOriginY + graphH + baseY, paintLabel);
}
}
if (labelFlagY) {
for (int i = 0; i < numDivY + 1; i++) {
String text = String
.valueOf(minY + i * (maxY - minY) / numDivY);
float baseX = paintLabel.measureText(text); // テキスト幅
float baseY = -fontMetrics.top / 2; // baselineからtopまでの高さの半分
canvas.drawText(text, graphOriginX - baseX, graphOriginY
+ graphH - i * (graphH / numDivY) + baseY, paintLabel);
}
}
}
void drawLines(Canvas canvas, Float[] data, int color) {
// 境界チェック
for (int i = 0; i < data.length / 2; i++) {
if (data[2 * i] != null && data[2 * i + 1] != null) {
data[2 * i] = (data[2 * i] < minX) ? minX : data[2 * i];
data[2 * i] = (data[2 * i] > maxX) ? maxX : data[2 * i];
data[2 * i + 1] = (data[2 * i + 1] < minY) ? minY
: data[2 * i + 1];
data[2 * i + 1] = (data[2 * i + 1] > maxY) ? maxY
: data[2 * i + 1];
}
}
float[] pts = new float[4 * (data.length / 2 - 1)];
// 描画座標へ変換
float pxlParUnitX = graphW / (maxX - minX); // X軸の単位辺りの画素値数
float pxlParUnitY = graphH / (maxY - minY); // Y軸の単位辺りの画素値数
for (int i = 0; i < data.length / 2 - 1; i++) {
if (data[2 * i] != null && data[2 * i + 1] != null
&& data[2 * i + 2] != null && data[2 * i + 3] != null) {
float x1 = data[2 * i];
float y1 = data[2 * i + 1];
float x2 = data[2 * i + 2];
float y2 = data[2 * i + 3];
pts[4 * i] = (x1 - minX) * pxlParUnitX + graphOriginX;
pts[4 * i + 1] = graphH - (y1 - minY) * pxlParUnitY
+ graphOriginY;
pts[4 * i + 2] = (x2 - minX) * pxlParUnitX + graphOriginX;
pts[4 * i + 3] = graphH - (y2 - minY) * pxlParUnitY
+ graphOriginY;
}
}
Paint paint = new Paint();
paint.setColor(color); // 線の色
paint.setStrokeWidth(2); // 線の太さ
canvas.drawLines(pts, paint);
}
void drawLegend(Canvas canvas, String[] name, int[] color) {
Paint paint = new Paint();
float lineLength = 0.05f * graphW;
FontMetrics fontMetrics = legendLabel.getFontMetrics();
float width;
float textW = 0;
for (int i = 0; i < name.length; i++) {
width = legendLabel.measureText(name[i]);
textW = (width > textW) ? width : textW;
}
float textH = -fontMetrics.top + fontMetrics.bottom;
float legendH = name.length * textH + fontMetrics.bottom;
float legendW = textW + lineLength;
paint.setColor(Color.WHITE);
paint.setStyle(Paint.Style.FILL);
canvas.drawRect(legendOriginX, legendOriginY, legendOriginX + legendW,
legendOriginY + legendH, paint);
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.STROKE);
canvas.drawRect(legendOriginX, legendOriginY, legendOriginX + legendW,
legendOriginY + legendH, paint);
float x, y;
x = legendOriginX;
y = legendOriginY + textH;
for (int i = 0; i < name.length; i++) {
paint.setColor(color[i]);
paint.setStrokeWidth(2);
canvas.drawLine(x, y + fontMetrics.top / 2, x + lineLength, y
+ fontMetrics.top / 2, paint);
paint.setColor(Color.BLACK);
canvas.drawText(name[i], x + lineLength, y, legendLabel);
y += textH;
}
}
}
0 件のコメント:
コメントを投稿