Googleクラウドプリントを非対応プリンタで試してみた
Android端末から直接印刷を使いたい!ということでGoogleクラウドプリントを試してみました。
GoogleクラウドプリントはGoogleのアカウントを持っていれば、AndroidやChromebook、もちろんPCやMacからもGoogleのサーバを介して対応したプリンタへ印刷ができるサービスです。
ところが、Googleクラウドプリントに対応したプリンタはEpsonやCanonからも出ていますが、まだまだオフィスで置いてあるような業務プリンタは対応してない。そこで、今回はGoogleクラウドプリントに対応していない普通のページプリンタを使って検証を行っています。
非対応プリンタをGoogleクラウドプリントで使うためには、仲介となるChromeがインストールされたPCが必要になります。今回はOS X 10.8.2のMacBookAirを使いました。
このChromeの設定から、Googleアカウントとプリンタのひもづけを行います。プリンタの情報が事前にPCに設定されていればクリックだけで設定できます。
設定の詳しいやり方が日本語マニュアルで公開されていて、10分くらいでできました。
https://support.google.com/cloudprint/answer/1686197?rd=1
Android側はGalaxy S3にCloud Printを入れて試しました。
印刷の仕方も簡単で、アプリ上で印刷するファイルを指定して、Googleアカウントにひも付いたプリンタから使用するものを選びます。
この時、注意が必要なのは仲介となるChromeがインストールされたPCが起動してないといけないということ。まあ、Android端末は社外のネットワークで直接プリンタと接続できないのだから、仲介となるPCが動いていなければ無理ですね。
その場合、印刷ジョブはGoogle側でキューイングされるので、アプリ側の印刷依頼自体は完了します。こちらは印刷依頼が終わった後の画面。QUEUEDというステータスになってますね。
仲介PCが起動していないといけないのはハードルが高いので対応プリンタが増えて欲しいところですが、どんなときにこのサービスが役に立つのでしょうか。
プリンタに接続されたPCが使える環境ではあまり意味のないサービスですから、出張先の支社や客先でプリンタの設定をせずにちょっと印刷したい、逆にお客さんに一時的に使わせたい、スマホやタブレットだけ持って営業所に行って印刷したい、タブレットでお医者さんが患者さんにヒアリングして結果を印刷して渡してあげる、といった普段のオフィスとは違う環境で印刷したい時には良いのではないのでしょうか。
もちろん開発者向けにAPIがありますから、アプリに組み込むことが可能です。
https://developers.google.com/cloud-print/?hl=ja
Androidとの連携はこちら。
https://developers.google.com/cloud-print/docs/android
2013年元旦。明けましておめでとうございます。
明けましておめでとうございます。
年末年始は、ゆっくりと娘と粘土や、人生ゲームをやって平和な正月でした。
昨年は2度目の転職など、公私ともに変化が多かった年でしたが、
今年はデザイン、プログラム、新企画など集中と、継続の年。
本年もよろしくお願い致します。
自分で作って気に入った白ヘビとドロイド君。
Android エミュレータのSQLiteのデータを見るには
SQLiteを使うAndroidアプリを作って、エミュレータでデバッグしているときに、データの中身を見たくなりますよね。
2つの方法があります。
1つはdbファイルを取り出して、PC側でSQLiteのクライアントツールを使って読み込む。
もう一つはadbでエミュレータにアクセスして、直接SQLを実行する方法です。ここでは2つ目の方法を書こうと思います。理由はいつも忘れて、調べるのが面倒だからです・・・。
SQLiteのデータ・ファイルはここにあります。
/data/data/<package_name>/databases/<database_name>
adbを起動してエミュレータの中に入っていきます。
$ adb shell # cd /data/data/com.nextconceptdc.std/databases # ls sample.db # sqlite3 socialToDo.db (ここからはSQLiteの中です) SQLite version 3.7.4 Enter ".help" for instructions Enter SQL statements terminated with a ";"
上の説明の通り、".help"コマンドでヘルプが見れます
sqlite> .help .backup ?DB? FILE Backup DB (default "main") to FILE .bail ON|OFF Stop after hitting an error. Default OFF .databases List names and files of attached databases .dump ?TABLE? ... Dump the database in an SQL text format If TABLE specified, only dump tables matching LIKE pattern TABLE. .echo ON|OFF Turn command echo on or off .exit Exit this program .explain ?ON|OFF? Turn output mode suitable for EXPLAIN on or off. With no args, it turns EXPLAIN on. .header(s) ON|OFF Turn display of headers on or off .help Show this message .import FILE TABLE Import data from FILE into TABLE .indices ?TABLE? Show names of all indices If TABLE specified, only show indices for tables matching LIKE pattern TABLE. .load FILE ?ENTRY? Load an extension library .log FILE|off Turn logging on or off. FILE can be stderr/stdout .mode MODE ?TABLE? Set output mode where MODE is one of: csv Comma-separated values column Left-aligned columns. (See .width) html HTML <table> code insert SQL insert statements for TABLE line One value per line list Values delimited by .separator string tabs Tab-separated values tcl TCL list elements .nullvalue STRING Print STRING in place of NULL values .output FILENAME Send output to FILENAME .output stdout Send output to the screen .prompt MAIN CONTINUE Replace the standard prompts .quit Exit this program .read FILENAME Execute SQL in FILENAME .restore ?DB? FILE Restore content of DB (default "main") from FILE .schema ?TABLE? Show the CREATE statements If TABLE specified, only show tables matching LIKE pattern TABLE. .separator STRING Change separator used by output mode and .import .show Show the current values for various settings .stats ON|OFF Turn stats on or off .tables ?TABLE? List names of tables If TABLE specified, only list tables matching LIKE pattern TABLE. .timeout MS Try opening locked tables for MS milliseconds .width NUM1 NUM2 ... Set column widths for "column" mode .timer ON|OFF Turn the CPU timer measurement on or off
今の環境設定を見てみます。
sqlite> .show echo: off explain: off headers: off mode: list nullvalue: "" output: stdout separator: "|" stats: off width:
テーブルの一覧を見てみます
sqlite> .tables android_metadata auth task
taskテーブルをSELECTしてみます。カラム名とかが表示されないので分かりにくいですね。
sqlite> select * from task; |rr||false||||||||1||||rr||
ヘッダーが表示されるように設定します
sqlite> .headers ON
環境設定を見てみると、headersがonになっています
sqlite> .show echo: off explain: off headers: on mode: list nullvalue: "" output: stdout separator: "|" stats: off width:
もう一度、SELECTをやってみます。今度はカラム名も出てくれました。
sqlite> select * from task; startDate|detail|status|isUploaded|ownerId|finishDate|projectId|rejectDate|deleted|id|completeDate|_id|created|updated|acceptDate|name|duedate|currentUserId |rr||false||||||||1||||rr||
テーブルの定義も見たいですよね。Oracle DBでいうdescです。
sqlite> .dump task PRAGMA foreign_keys=OFF; BEGIN TRANSACTION; CREATE TABLE task(startDate datetime,detail text,status integer,isUploaded string default 'false',ownerId integer,finishDate datetime,projectId integer,rejectDate datetime,deleted datetime,id integer,completeDate datetime,_id integer primary key autoincrement,created datetime,updated datetime,acceptDate datetime,name text,duedate datetime,currentUserId integer); INSERT INTO "task" VALUES(NULL,'rr',NULL,'false',NULL,NULL,NULL,NULL,NULL,NULL,NULL,1,NULL,NULL,NULL,'rr',NULL,NULL); COMMIT;
以上です。
Mac OS X 64bitでSOAP UIを起動させるために
切っ掛けは不明ですが、数ヶ月前は普通に使えていたSOAP UIが起動できなくなってしまいました。
OSのバージョンを上げたときに、使ってるJVMが変わったかな?OSのバージョンはOS X 10.8.2。
エラー内容
こんなエラーがでます。
java.lang.Exception: Object owner or JVM pointer are not correct
$soapui.sh ================================ = = SOAPUI_HOME = /Applications/soapui-4.5.1 = ================================ Configuring log4j from [/Applications/soapui-4.5.1/bin/soapui-log4j.xml] 10:54:33,746 INFO [DefaultSoapUICore] initialized soapui-settings from [/Applications/soapui-4.5.1/soapui-settings.xml] 10:54:34,667 INFO [WorkspaceImpl] Loading workspace from [/Applications/soapui-4.5.1/bin/../../TestPBE-workspace.xml] 10:54:34,753 INFO [WsdlProject] Loaded project from [file:/Users/sogo/Documents/soapui/NewWSDLFile-soapui-project.xml] 10:54:35,229 INFO [SoapUI] Used java version: 1.6.0_37 objc[38025]: Class MessageLoopView is implemented in both /private/var/folders/xp/3j0nqcx93sbgs2zxszylhcnh0000gn/T/jxbrowser-3.0.Build.Unknown/libjniw.jnilib and /private/var/folders/xp/3j0nqcx93sbgs2zxszylhcnh0000gn/T/jxbrowser-3.0.Build.Unknown/libjniwrap.jnilib. One of the two will be used. Which one is undefined. objc[38025]: Class MessageLoopView is implemented in both /private/var/folders/xp/3j0nqcx93sbgs2zxszylhcnh0000gn/T/jxbrowser-3.0.Build.Unknown/libjniw.jnilib and /var/folders/xp/3j0nqcx93sbgs2zxszylhcnh0000gn/T/jxbrowser-3.0.Build.Unknown/libjniw.jnilib. One of the two will be used. Which one is undefined. 2012-12-14 10:54:37.717 java[38025:11703] [Java CocoaComponent compatibility mode]: Enabled 2012-12-14 10:54:37.742 java[38025:2517] java.lang.Exception: Object owner or JVM pointer are not correct
解決策
エラー内容からUIの部分が64bitがサポートされてないみたいなので、Javaの起動オプションに-d32を追加すればOKです。
soapui.shを開いて、JAVA_OPTSを探します。
JAVA_OPTS="-Xms128m -Xmx1024m -Dsoapui.properties=soapui.properties -Dsoapui.home=$SOAPUI_HOME -d32"
Android。フラグメントでアクションバーを使う。
コード側のポイントは3つだけです。
1.onCreateViewの中でsetHasOptionsMenu(true)でオプションメニューを有効にして
2.onCreateOptionsMenuでメニューの内容の指定
3.onOptionsItemSelectedでメニューを選択されたときの処理を実装
public class TaskListFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) { setHasOptionsMenu(true); return inflater.inflate(R.layout.tasklist_fragment, container, false); } @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { inflater.inflate(R.menu.activity_std_main, menu); super.onCreateOptionsMenu(menu, inflater); } @Override public boolean onOptionsItemSelected(MenuItem item) { Toast.makeText(getActivity(), "Selected Item: " + item.getTitle(), Toast.LENGTH_SHORT).show(); return super.onOptionsItemSelected(item); } }
メニューの内容はres/menu/の下にxmlで指定。
<menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/menu_refresh" android:title="@string/menu_refresh" android:icon="@drawable/std_button_24" android:showAsAction="ifRoom" /> <item android:id="@+id/menu_project" android:title="@string/menu_projectlist" android:icon="@drawable/std_button_26" android:showAsAction="ifRoom" /> <item android:id="@+id/menu_today" android:title="@string/menu_today" android:icon="@drawable/std_button_28" android:showAsAction="ifRoom" /> <item android:id="@+id/menu_new_task" android:title="@string/menu_new_task" android:icon="@drawable/std_button_30" android:showAsAction="ifRoom" /> </menu>
後はマニフェストファイルのandroid:uiOptionsで、ユーザの環境に合わせてどんな見せ方をしたいのかを指定。splitActionBarWhenNarrowを指定した場合は、アクションバーに収まりきらない場合は、スプリットアクションバー(最下部に表示されるバー)に配置するという指定。
<activity android:name="com.nextconceptdc.std.ui.TaskListFragment" android:label="@string/title_activity_std_main" android:uiOptions="splitActionBarWhenNarrow" > </activity>
splitActionBarWhenNarrowを指定した場合
splitActionBarWhenNarrowを指定しない場合。入る分は最上部のアクションバーに配置され、それ以外はメニューからドロップリストとして表示される。
アプリ内での複数テーブルへの問い合わせ
本エントリでは、Androidアプリで複数のテーブルを結合して情報を取り出すことについて書こうと思います。
AndroidではデータベースとしてSQLiteが用意されています。
業務系のアプリを作るような場合は特にデータの生成、管理がメインの処理になる傾向があるので、SQLiteを使うことも多いと思います。
そこで、テーブルの設計をやることになりますが、正規化を進めていくうちに画面に表示したい項目が複数のテーブルにまたがることも良くあります。
自分の場合、Androidアプリで曖昧な検索を複数テーブルに対して行うことはあまりありません。曖昧な検索とは、社員テーブルに佐藤さんを条件で、売上テーブルに売上100万円以上を条件で両方にヒットしたものを画面に表示するようなものです。理由はおそらく2つ。
1つは、スマホは画面が小さいのでその画面で検索結果が大量にあってページ送りを何度もしないとデータが見れないような画面設計をやらない。これはタブレットになってくるとそんな要件の画面もでてくるのかも知れません。
2つ目は、複数のテーブルの曖昧検索をしたいような場合ってほとんどが分析や一覧用途だと思います。分析したくなるほどのデータががAndroid端末のストレージに蓄積されていることって少ないんじゃないでしょうか。そのような場合、おそらくバックエンドのサービスにデータは蓄積されていて、分析したい場合はバックエンドに問い合わせるでしょう。
複数テーブルに問い合わせるケースで良くあるのが、社員マスタに社員番号と、社員名があり、売上テーブルかには社員番号と社員毎の売上があるような場合です。売上の上位5件を表示したときに社員番号だけではなく社員名も表示したいですよね。
そのような時、社員マスタと売上テーブルを結合してデータを取ってきたくなりますが、どうやってますか?
1つはSQLiteDatabase.rawQuery()を使って、自分でSELECT文を書いてしまうやり方です。これはSQLを書けるので、自由になんでも書けます。
もう一つはSQLiteDatabase.query()を使うやり方ですが、引数にテーブル名を渡す際に、カンマ区切りで複数のテーブルを指定し、Selection(SQLのWhere句に該当)の引数にテーブルを結合するための条件を書けます。すごい端折って書くとこんな感じです。
ContentProviderを呼び出してる方
String[] columns = new String[3]; columns[0] = "RevenueTable.EmpNo"; columns[1] = "EmploeeTable.EmpName"; columns[2] = "RevenueTable.Revenue"; String selection = "EmploeeTable.EmpNo=RevenueTable.EmpNo"; ContentResolver resolver = getContentResolver(); Cursor cursor = resolver.query(uri, columns, selection, null, null);
ContentProvider側
public Cursor query(Uri uri, String[] projection, String where, String[] whereArgs,String order) { Cursor cursor = db.query( "RevenueTable, EmploeeTable", projection, where, whereArgs, null, null, order); return cursor; }
参考にさせていただいた記事
Androidアプリのデータ保存方法の一つ「SQLite」の使い方 レコード検索編
Best way to join tables using sqlite in android
http://stackoverflow.com/questions/2421189/version-of-sqlite-used-in-android
スクラム道EXPO 2012に参加しました。
スクラム道EXPO 2012に参加してきました。
テーマはこの6つでした。
個人的には、今まさにコンサルで入っているプロジェクトで、初めてアジャイルに取り組むチームが半年弱試行錯誤してきて、次のステップとして自律型組織を目指すべきでは無いかと考えていましたので、ばっちりのテーマでした。
特に優秀であるほど、PM、リーダクラスは責任感が強く、いい加減な仕事はできないという気持ちが強いため、逆に彼らの確認待ち、計画待ちになることもフェーズによっては有り得ます。もっと大きなプロジェクトに、今試行している開発プロセスでチャレンジするためには一度、リーダ層のタスクを洗い出して、メンバーに任せられるもの、自動化できるものを分別しようと思います。そうしないとスケールしないですね。
Doneの定義についても、一応あるものの、これまでのやり方に従うところが多かったので、一度、振り返りをして足す物、引く物を検討すべきだと気づきがありました。
参考文献
塹壕より Scrum と XP