curious4dev

中国旅行、Arduinoなどを使った電子工作、その他色々。

*

上司離着席状態検知アプリ

 

お疲れ様です。高橋です。

上司離着席状態検知システムですが、

  1. 必要性を記載
  2. 回路図や必要部品を記載
  3. 応用例
  4. webによるクラウド対応

までは完了しました。次はアプリ化です。

アプリ化

離着席状態はPCからAWSにアップされ、AWS上のAPI(と呼ぶのはおこがましいが)をコールすると、最新の日時と状態を取得出来るようにしたので、それをただただ画像として表現するためだけの物です。

091601

90分で実装~アイコン作成~リリースが完了しました。90分で出来るレベルなので、大したことありません。

091602

このアプリは世界141カ国にリリースされています。141カ国のAndroidユーザが私の上長の離着席状態を知ることが出来る世界は素敵です。

作り方

アイコンは「無料 素材 シルエット 椅子」でググって来たものを使っています。既にどこから拾ってきたのかは忘れましたが、権利系は問題ないはずです。

 

MainActivity.java – アプリ起動時に呼び出されるコードです。

package jp.curious4dev.preab;

import android.app.Activity;
import android.net.Uri;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageButton;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ImageButton btn = (ImageButton) findViewById(R.id.imageButton1);
        btn.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                getCurrentStatus();
            }

        });
        getCurrentStatus();

    }

    public void getCurrentStatus() {
        Uri.Builder builder = new Uri.Builder();
        AsyncHttpRequest task = new AsyncHttpRequest(this);
        task.execute(builder);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
}

AsyncHttpRequest.java – MainActivityから呼び出される、非同期http通信と画面への画像表示を担当してます。

package jp.curious4dev.preab;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;

import android.app.Activity;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.AsyncTask;
import android.widget.ImageButton;
import android.widget.TextView;

public class AsyncHttpRequest extends AsyncTask<Uri.Builder, Void, String> {

    private Activity mainActivity;

    public AsyncHttpRequest(Activity activity) {

        this.mainActivity = activity;

    }

    @Override
    protected String doInBackground(Uri.Builder... builder) {

        StringBuffer sb = new StringBuffer();

        try {
            URL url = new URL("http://curious4dev.mydns.jp/richakuseki/now4app.php");
            Object content = url.getContent();
            if (content instanceof InputStream) {
                BufferedReader bf = new BufferedReader(new InputStreamReader((InputStream) content));
                String line;
                while ((line = bf.readLine()) != null) {
                    sb.append(line);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return sb.toString();
    }

    @Override
    protected void onPostExecute(String result) {
        String[] aryResult = result.split(",");
        String strDateTime = aryResult[0];
        String strStatus = aryResult[1];
        Resources r = mainActivity.getResources();
        ImageButton imageButton = (ImageButton) mainActivity.findViewById(R.id.imageButton1);
        TextView textView1 = (TextView) mainActivity.findViewById(R.id.textView1);
        textView1.setText(strDateTime + " JST");
        if (strStatus.equals("10") == true) {
            Bitmap bmp = BitmapFactory.decodeResource(r, R.drawable.presence);
            imageButton.setImageBitmap(bmp);
        } else {
            Bitmap bmp = BitmapFactory.decodeResource(r, R.drawable.absence);
            imageButton.setImageBitmap(bmp);
        }

    }
}

activity_main.xml – 画面レイアウトの定義です。

<LinearLayout xmlns:tools="http://schemas.android.com/tools"
 xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:layout_gravity="center"
 android:gravity="top"
 android:orientation="vertical"
 android:paddingBottom="@dimen/activity_vertical_margin"
 android:paddingLeft="@dimen/activity_horizontal_margin"
 android:paddingRight="@dimen/activity_horizontal_margin"
 android:paddingTop="@dimen/activity_vertical_margin"
 tools:context="jp.curious4dev.preab.MainActivity" >

 <TextView
 android:id="@+id/textView1"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:text="@string/strDateTime" />

 <ImageButton
 android:id="@+id/imageButton1"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_gravity="fill"
 android:contentDescription="TODO"
 android:scaleType="fitXY"
 android:src="@drawable/absence"
 tools:ignore="ContentDescription,HardcodedText" />

</LinearLayout>

AndroidManifest.xml – 設定ファイル。INTERNETのパーミッションを記載しています。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
 package="jp.curious4dev.preab"
 android:versionCode="1"
 android:versionName="1.0" >

 <uses-sdk
 android:minSdkVersion="16"
 android:targetSdkVersion="21" />
 <uses-permission android:name="android.permission.INTERNET"/>

 <application
 android:allowBackup="true"
 android:icon="@drawable/ic_launcher"
 android:label="@string/app_name"
 android:theme="@style/AppTheme" >
 <activity
 android:name=".MainActivity"
 android:label="@string/app_name" >
 <intent-filter>
 <action android:name="android.intent.action.MAIN" />

 <category android:name="android.intent.category.LAUNCHER" />
 </intent-filter>
 </activity>
 </application>

</manifest>

今回は面倒なので広告IDは取得してません。

残タスク

通知処理が必要かと思います。「着席したその瞬間」に相談に行けば、上司は打ち合わせから戻ってきて「さて自分の仕事をしようか」とエンジンが本格的にかかる前のタイミングなはずで、キリが良いと思われます。

課題

今回作った上司デバイスと部下デバイス間の通信可能距離は、意外に短い可能性が高い事が判明しました。上司デバイスから電波を受け取れる位置にあるPCに部下デバイスをセットして、そこからAWSにデータを飛ばす必要があります。部下デバイスからデータを取得してAWSに飛ばす箇所に、http-proxyの対応を仕込む必要があるかもしれません。

 

以上、よろしくお願い致します。

 - アプリ開発

  関連記事

遅刻の言い訳提案システム 稼働三日目 ~大失敗~

お疲れ様です。高橋です。 三日目を迎えた遅刻の言い訳提案システムですが、重大なバ …

西野カナ風な歌詞自動生成「カナかな?」をリリースしてみた。

お疲れ様です。高橋です。 昨日はずっと助詞に関する実装をしていたのですが、どうし …

街頭インタビュー 入力UI実装

お疲れ様です。高橋です。 今日は文字入力UI及び、背景人物の切り替え機能を実装し …

遅刻の言い訳提案システム 稼働四日目

お疲れ様です。高橋です。 本日も遅刻の言い訳提案システムのデータの分析と改善のた …

総務省統計APIで引っ張ったデータをHoloGraphLibraryで可視化してみた

お疲れ様です。高橋です。 先日の「総務省の統計APIからデータを取得する」ではデ …

「カナかな?」の2週間分のダウンロード数

お疲れ様です。高橋です。 本日の貴重な帰宅後の時間は、妻からの「なんとかっていう …

AndroidアプリでHoloGraphLibraryを使ってグラフ描画してみた

お疲れ様です。高橋です。 先日、総務省の統計APIをコールしてデータを取得してく …

DLリンク付き言い訳提案システムとDL数の関係について

お疲れ様です。高橋です。 DLリンク付きの言い訳提案システムを1週間稼働させ、そ …

SurfaceViewを使って絵を書き動かすサンプルをコピペして動かしてみた

お疲れ様です。高橋です。 本日はcocos2d-xの3.3rc0を導入しようと試 …

androidアプリの作り方

お疲れ様です。高橋です。 androidアプリの作り方は、ググったところ大体下記 …