初めてのRuby On Rails①(環境構築)
Webアプリケーション作成のためのフレームワークであるRuby On Rails
の勉強を始めました。
まずは、ローカルでRailsが動く環境を作ってみたいと思います。
Rubyの準備
1.rbenvのインストール
ローカルでの開発環境なので、色々と柔軟に作りたいと思い、
Rubyのバージョン管理ツールrbenv
を使ってRubyをインストールしてみました。
brew install rbenv
インストールが完了したらrbenv
の初期設定を行います。
以下の設定を.zshenv
や.bashrc
に記載します。
この設定で、[user_home]/.rbenv
ディレクトリ配下に各バージョンごとのRubyがインストールされるようになります。
# rbenvの初期設定 if which rbenv > /dev/null; then export RBENV_ROOT=${HOME}/.rbenv export PATH=${RBENV_ROOT}/shims:${PATH} eval "$(rbenv init -)"; fi
その他、必要なツールのインストールを行います。
brew install ruby-build brew install rbenv-gemset brew install rbenv-gem-rehash
2.インストールの確認
ここまでで、正しくrbenv
のインストールおよび設定ができているかを確認するために以下のコマンドを実行します。
rbenv versions
rbenv versions
コマンドは、インストール済みのRubyのバージョンを確認するコマンドです。
設定されているパスが以下のように自分のホームディレクトリを指していれば、正しく設定ができています。
* system (set by /Users/[user_home]/.rbenv/version)
3.rubyのインストール
実際にバージョンごとのRubyをインストールします。
インストール可能なバージョンの確認
rbenv install -l
目的のRubyのバージョンをインストール
rbenv install 2.0.0p451
4.インストールの確認
ruby -v
実行時にダウンロードしたRubyのバージョンが、
以下のように表示されていれば正しくインストールが完了しています。
ruby -v ruby 2.0.0p451 (2014-02-24 revision 45167) [universal.x86_64-darwin13]
インストールしたRubyの実行ファイルパスも確認してみます。
which ruby /Users/[user_home]/.rbenv/shims/ruby
.rbenv
配下にインストールされていればOKです。
※rubyのバージョンを切り替える方法
rbenv global [バージョン] rbenv rehash
rehash
コマンドを実行することで、/Users/[user_home]/.rbenv/shims/
配下のパスが指定したバージョンへ切り替わります。
Rails の準備
1.Railsのインストール
gemからRailsをインストールします。
gem install rails
インストールの確認。
rails -v
2.bundleのインストール
依存モジュールのインストールを管理するためにbundler
をインストールします。
gem install bundler
ここまでで、Railsのプロジェクトを作成する準備は完了です。
テストプロジェクトを作成してみる
1.プロジェクトの作成
テスト用のプロジェクトを作成するために、
任意のディレクトリ配下へ移動して以下のコマンドを実行します。
rails new [プロジェクトパス]
これだけで、Railsプロジェクトのひな形が作成されます。
※作成したプロジェクトで使用しているライブラリバージョンの確認
rake about
2.Railsサーバーの起動
Rubyには、標準でWEBrick
というWebサーバーが同梱されています。
以下のrails server
というコマンドを実行すると、
他にWebサーバーが使用されていない場合は、WEBrick
が自動的に立ち上がります。
rails server
以下のようにログが出力されていれば、正しく起動しています。
=> Booting WEBrick => Rails 4.1.1 application starting in development on http://0.0.0.0:3000 => Run `rails server -h` for more startup options => Notice: server is listening on all interfaces (0.0.0.0). Consider using 127.0.0.1 (--binding option) => Ctrl-C to shutdown server [2014-05-11 19:46:16] INFO WEBrick 1.3.1 [2014-05-11 19:46:16] INFO ruby 2.0.0 (2013-02-08) [x86_64-darwin13.1.0] [2014-05-11 19:46:16] INFO WEBrick::HTTPServer#start: pid=627 port=3000
試しにhttp://localhost:3000にアクセスしてみて、
以下のようなページがでれば、正しくサーバーが起動しています。
3.テストページの作成
Railsのコントローラとアクションを作成して、
アプリケーションのテストページを表示してみます。
rails generate controller [コントローラ名] [アクション名]
たとえばHoge
コントローラのpiyo
アクションのページを作成する場合は、
rails generate controller Hoge piyo
とします。
http://localhost:3000/hoge/piyoにアクセスすると、
以下のようなページが表示されると思います。
たったこれだけで、Webアプリケーションのページが作成できました。
rbenvのインストール(Mac)
Rubyのバージョン管理ツールであるrbenv
を使って、
Rubyの実行環境をつくってみました。
1.rbenvをインストール
brew install rbenv
インストールが完了したらrbenv
の初期設定を行います。
以下の設定を.zshenv
や.bashrc
に記載します。
この設定で、[user_home]/.rbenv
ディレクトリ配下に書くバージョンのrubyがインストールされるようになります。
# rbenvの初期設定 if which rbenv > /dev/null; then export RBENV_ROOT=${HOME}/.rbenv export PATH=${RBENV_ROOT}/shims:${PATH} eval "$(rbenv init -)"; fi
その他、必要なツールのインストール
brew install ruby-build brew install rbenv-gemset brew install rbenv-gem-rehash
2.インストールの確認
ここまでで、正しくrbenv
のインストールおよび設定ができているかを確認するために、
以下のコマンドを実行します。
rbenv versions
※ rbenv versions ~ インストール済みのRubyのバージョンを確認
設定されているパスが以下のように自分のホームディレクトリを指していれば、
正しく設定ができています。
* system (set by /Users/[user_home]/.rbenv/version)
3.rubyのインストール
実際に使用するRubyをインストールします。
インストール可能なバージョンの確認
rbenv install -l
Rubyのバージョンをインストール
rbenv install 2.0.0p451
4.インストールの確認
ruby -v ruby 2.0.0p451 (2014-02-24 revision 45167) [universal.x86_64-darwin13]
ダウンロードした、Rubyのバージョンを指していれば正しくインストールされています。
インストールしたRubyの実行ファイルパスも確認してみます。
which ruby /Users/[user_home]/.rbenv/shims/ruby
.rbenv配下にインストールされていれば大丈夫です。
rubyのバージョンを切り替える時
rbenv global [バージョン] rbenv rehash
rehashしてあげないと、私の環境ではPATHが切り替わりませんでした。
【Android】youtubeの動画を再生する
Androidで、youtubeの動画を再生するには大きく分けて2つの方法があります。
1つは、youtubeアプリに対してIntentを飛ばす方法で、
例えば下記のように記載することで直接youtubeアプリを起動することができます。
Intent intent = new Intent(Intent.ACTION_SEARCH); intent.setPackage("com.google.android.youtube"); intent.putExtra("query", "Android"); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent);
もう一つは、YouTube Android Player API
を使用する方法です。
これは、googleが提供しているAPIで、自分のアプリ内でyoutubeの再生機能を利用することができます。
(youtubeを起動はしない)
今回は、YouTube Android Player API
を使用して、
アプリ内で動画を再生する方法を試してみました。
API Keyを作成する
まずは、Google APIをアプリ上で実行するために、
Google Developlers Consoleにて、
APIKeyを取得します。
1.新規プロジェクトを作成
2.Youtube APIを有効にする
APIs & auth
を選択し、 YouTube Data API v3
をONにします。
3.API Keyを作成する
APIs & auth
>Credentials
を選択、 Public API access
にあるCREATE NEW KEY
ボタンを押下します。
キー種別の選択ダイアログが表示されるため、 Android key
を選択します。
続いて、表示されるテキストボックスにAndroidに組み込むkeystoreのSHA1のフィンガープリントおよび、
API実行を許可するアプリケーションのパッケージ名を入力します。
入力フォーマットは、[フィンガープリント];(セミコロン)[パッケージ名]となっています。
CREATE
ボタンを押下すれば、API key
の作成は完了です。
完了後に画面に表示されているAPI key
をAndroidアプリケーションに組み込んで使用します。
例: 9F:DA:1F:03:71:4B:1E:BD:90:76:51:AB:26:0C:B7:41:2F:94:AB:C6;com.sample.gcmtest
※ keystoreのフィンガープリントを確認するには
■ 使用するコマンド
keytool -exportcert -alias androiddebugkey -keystore [署名するkeystoreのパス] -list -v
今回は、Android ADTで用意されているデバッグ用のkeystoreで確認します。
デバッグ用のkeystoreは、[ユーザーHOME]/.android/debug.keystore
にデフォルトkeyが配置されていて、
パスワードは、android
です。
keytool -exportcert -alias androiddebugkey -keystore ~/.android/debug.keystore -list -v
上記のコマンド実行結果から、表示されるフィンガープリントのSHA1
の文字列をコピーすればOKです。
Androidアプリの実装
今回は、youtubeのプレーヤーをFragmentとして使用するサンプルアプリを実装します。
1.YouTube Android Player API
の最新バージョンをダウンロード
YouTube Android Player APIの最新版をダウンロードし、libs/
にあるYouTubeAndroidPlayerApi.jar
をプロジェクトへインポートします。
2.AndroidManifestの実装
下記、パーミッションを追加します。
<uses-permission android:name="android.permission.INTERNET"/>
3.layout.xmlにYouTubePlayerFragment
を定義
今回は、動画の再生に使用するYouTubePlayerFragment
をlayout.xmlに定義して使用します。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <fragment android:name="com.google.android.youtube.player.YouTubePlayerFragment" android:id="@+id/youtube_fragment" android:layout_width="match_parent" android:layout_height="wrap_content"/> </LinearLayout>
4.Activityの実装
下記サンプルでは、Activityに登録されたYouTubePlayerFragment
インスタンスを、
上記で取得したAPI Key
で初期化しています。
また、初期化のコールバックを取得するために、YouTubePlayer.OnInitializedListener
を実装し、
初期化が成功したタイミングでプレーヤーの実行準備を行っています。
APIの詳細については、YouTube Android Player API - リファレンス ガイドを参照してください。
public class MainActivity extends Activity implements YouTubePlayer.OnInitializedListener { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // フラグメントインスタンスを取得 YouTubePlayerFragment youTubePlayerFragment = (YouTubePlayerFragment) getFragmentManager().findFragmentById(R.id.youtube_fragment); // フラグメントのプレーヤーを初期化する youTubePlayerFragment.initialize("[API Key]", this); } @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 void onInitializationFailure(Provider provider, YouTubeInitializationResult error) { // プレーヤーの初期化失敗時に呼ばれる } @Override public void onInitializationSuccess(Provider provider, YouTubePlayer player, boolean wasRestored) { // プレーヤーの初期化成功時に呼ばれる if (!wasRestored) { // 指定された動画のサムネイルを読み込み、プレーヤーがその動画を再生する準備を行う player.cueVideo("nCgQDjiotG0"); } } }
これだけで、アプリ内でyoutubeの動画を再生することができます。
他にも、ウィジェットなどのAPIも用意されているようなので、
色々試して見たいと思います。
参考リンク
https://developers.google.com/youtube/android/player/ https://developers.google.com/youtube/android/player/setup
Appiumを使ってRubyでAndroidアプリのテストを行う①
Appiumをインストール
sudo npm install -g appium npm install wd appium &
Appiumリポジトリをクローン
git clone https://github.com/appium/appium.git
テスト実行環境を確認
以下のスクリプトを実行して、テストに必要な環境の構築を行います。
ビルドパスやコマンドが不足している場合は、必要に応じてインストールします。
cd appium ./reset.sh --verbose
参考までに私の環境でエラーになった内容について記載しておきます。
[mavenがインストールされていなかった]
Homebrewでインストール。
brew install maven
[androidSDKのAPI Level16がインストールされていなかった]
Android SDK Managerから指定のAPIをインストール。
android
テスト実行環境をインストール
今回は、Rubyでテストを行うつもりなので以下を実行します。
cd appium/sample-code/examples/ruby bundle install
ここでハマったのが、bundle install
時に以下のエラーでて、ビルドが失敗していました。
An error occurred while installing ffi (1.9.3), and Bundler cannot continue. Make sure that `gem install ffi -v '1.9.3'` succeeds before bundling.
原因は、Xcode 5.1 へのアップデートによってclangが更新されたためとのことです。
下記のサイトを参考にさせていただき、
ARCHFLAGS=-Wno-error=unused-command-line-argument-hard-error-in-future bundle install
とすることで、成功しました。
参考サイト:
【Mac】clang によるビルドエラー【Xcode 5.1】
rspecのインストール
Appiumの実行には、Rspec
を使用するため、gemでインストールしておきます。
gem install rspec
ここまでで、テストを実行する準備が整いました。
次回は、具体的にどうやってテストを書けばいいかを書いていきたいと思います。
参考サイト
http://qiita.com/2or3/items/261862eebbccc436265b
http://iti.hatenablog.jp/entry/2013/12/25/085726
【Android】NFCを使ってみる① (読み込み処理)
NFC(Near Field Communication)は、近距離無線のテクノロジーで、
Android 2.3からサポートされている技術です。
また、Android 4.0からは、Android Beam
という機能が加わり、
2つのAndroid搭載のデバイス間でのピアツーピアのデータ交換が可能となりました。
アプリケーションへの NFC タグのディスパッチ方式
AndroidデバイスがNFCを検知すると対応するインテントを発行します。
NFCに関する起動インテントには、下記の3種類があり、
それぞれの優先度が決まっています。
[ACTION_NDEF_DISCOVERED]
読み込んだタグが、NDEF(NFC Data Exchange Format)
ペイロードを持つ場合、
このアクションが定義されたアクティビティにIntentが通知されます。
起動インテントの優先度としては、最も高く、
このアクションでアクティビティが起動した場合は、ACTION_TECH_DISCOVERED
またはACTION_TAG_DISCOVERED
で登録されているアクティビティがあっても起動されません。
[ACTION_TECH_DISCOVERED]
ACTION_NDEF_DISCOVERED
インテントをハンドルするアクティビティが登録されていない場合には、
このアクションでが定義されたアクティビティにIntentが通知されます。
優先度としては、ACTION_NDEF_DISCOVERED
の次に高いです。
[ACTION_TAG_DISCOVERED]
このインテントはACTION_NDEF_DISCOVERED
または、ACTION_TECH_DISCOVERED
インテントをハンドルするアクティビティがない場合に開始されます。
読み込みサンプル
以下のサンプルは、NFCカードをかざすとNFCの識別子情報を読み取るサンプルになります。
Android Manufestの定義
Android Manufest
には、NFCを使用するためのパーミッションの定義と、
各ディスパッチ方式に対応するintent-filter
の定義が必要です。
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.test.nfcreadsample" android:versionCode="1" android:versionName="1.0" > <!-- NFCを使用する為のパーミッションを付与 --> <uses-permission android:name="android.permission.NFC" /> <!-- Google Playで、NFCハードウェアを持つデバイスのみに制限するための 機能を定義 --> <uses-feature android:name="android.hardware.nfc" android:required="true" /> ・・・ <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="com.test.nfcreadsample.MainActivity" android:label="@string/app_name" > ・・・ <!-- NFC NDEF text --> <intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> <data android:mimeType="text/plain" /> </intent-filter> <!-- NFC TECH --> <intent-filter> <action android:name="android.nfc.action.TECH_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> <!-- ACTION_TAG_DISCOVEREDで登録するフィルタを参照する --> <meta-data android:name="android.nfc.action.TECH_DISCOVERED" android:resource="@xml/nfc_tech_filter" /> <!-- NFC TAG --> <intent-filter> <action android:name="android.nfc.action.TAG_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity> </application> </manifest>
ACTION_NDEF_DISCOVERED
インテントをフィルタするには、
フィルタしたい対象データのタイプを加えたインテントフィルタを宣言します。
上記では、ACTION_NDEF_DISCOVERED
フィルタにtext/plain
のMIMEタイプを付加しています。
ACTION_TECH_DISCOVERED
インテントをフィルタさせる場合は、
XMLリソースファイルを作成し、tech-listセットの中にアクティビティがサポートするNFCのフォーマット形式を定義します。
作成したXMLファイルは、<project-root>/res/xml
ディレクトリ配下へ保存します。
以下は、tech-listリソースファイルのサンプルです。
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <tech-list> <tech>android.nfc.tech.IsoDep</tech> </tech-list> <tech-list> <tech>android.nfc.tech.NfcA</tech> </tech-list> <tech-list> <tech>android.nfc.tech.NfcB</tech> </tech-list> <tech-list> <tech>android.nfc.tech.NfcF</tech> </tech-list> <tech-list> <tech>android.nfc.tech.NfcV</tech> </tech-list> <tech-list> <tech>android.nfc.tech.Ndef</tech> </tech-list> <tech-list> <tech>android.nfc.tech.NdefFormatable</tech> </tech-list> <tech-list> <tech>android.nfc.tech.MifareClassic</tech> </tech-list> <tech-list> <tech>android.nfc.tech.MifareUltralight</tech> </tech-list> </resources>
NFCを読み込む
下記では、起動Activityより受信インテントを受け取り、
NFCの起動によるものかを判定しています。
インテントがNFCのアクションである場合、
NfcAdapter.EXTRA_ID
というキーを使ってNFCのIDm(固有識別子)を読み込んでいます。
public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Intent intent = getIntent(); String action = intent.getAction(); setContentView(R.layout.activity_main); // NFCかどうかActionの判定 if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action) || NfcAdapter.ACTION_TECH_DISCOVERED.equals(action) || NfcAdapter.ACTION_TAG_DISCOVERED.equals(action)) { // IDm(固有識別子)を表示させる String idm = getIdm(getIntent()); if (idm != null) { TextView idmView = (TextView) findViewById(R.id.idm); idmView.setText(idm); } } } /** * IDmを取得する * @param intent 受信インテント * @return IDm文字列 */ private String getIdm(Intent intent) { String idm = null; StringBuffer idmByte = new StringBuffer(); byte[] rawIdm = intent.getByteArrayExtra(NfcAdapter.EXTRA_ID); if (rawIdm != null) { for (int i = 0; i < rawIdm.length; i++) { idmByte.append(Integer.toHexString(rawIdm[i] & 0xff)); } idm = idmByte.toString(); } return idm; } }
【Android】GCMを使ってみる
GCM(Google Cloud Messaging for Android)は、
開発者がサーバからAndroidデバイス上のAndroidアプリケーションに対して、
データを送信できるようにする仕組みです。
Developers Consoleの準備
Developers Consoleにて、アプリケーションを登録してAPI実行に必要なKey情報を取得します。
1.任意のアプリケーションを作成する
アプリケーションを作成すると、APIコンソールのDashboardにProject Number
が表示されます。
この数字は、後ほど作成するGCM受信アプリにて、登録ID(registration ID)取得の際に必要になるので覚えておきます。
2.GCMの設定を有効にする
APIs & auth
を選択し、表示されるリストの中からGoogle Cloud Messaging for Android
を探してONにします。
3. API Keyを発行する
API Keyを作成するには、左メニューのAPIs & auth
> credential
ボタンを押下し、
Public API access
領域にあるCREATE NEW KEY
ボタンを押下します 。
以下のように作成するキーを選択するダイアログが表示されるます。
今回は、Pushの確認テストとしてサーバーからリクエストを送るため、Server key
を選択します。
Server key
ボタンを押下すると、アクセスを許可するIPアドレスを設定するためのダイアログが表示されるので、
アクセスを許可するグローバルIPを入力します。
処理が正常に完了すると下記のようにAPI keyが発行されます。
このKeyを使用して、サーバー側からのGCMのメッセージを送信します。(後述)
Androidアプリの準備
GCMを受信するためのAndroidアプリケーションを実装します。
1.GSM用のライブラリをeclipseにimportする
Android SDK Manager
を起動し、Extras
配下のGoogle Play services
を選択し、
importします。
importが完了すると<ANDROID_HOME>/extras/google/google_play_services/libproject/
配下に、google-play-services_lib
というディレクトリがDLされているので、
これをAndroid Project From Exting Code形式でeclipseにimportします。
次に、GCMを受信する為のプロジェクトを新規で作成し、
Projectを選択 > 右クリックでPropertiesを選択 > Androidから、
先ほど、eclipseにimportしたライブラリプロジェクトを追加します。
これで、Android プロジェクトでGCMクラスを使用するための準備は完了です。
2. GCM受信の準備
GCMの通知を受け取るためのReceiverクラスを実装します。
GCMの受信処理中に端末がスリープしないように、ReceiverクラスはWakefulBroadcastReceiver
を継承しています。
WakefulBroadcastReceiver
は、処理を実行している間は、デバイスがスリープしないことが保証できる特殊なReceiverクラスです。
public class GcmBroadcastReceiver extends WakefulBroadcastReceiver { public GcmBroadcastReceiver() { super(); } @Override public void onReceive(Context context, Intent intent) { // GCMを受信 メッセージ受信用のサービスを起動する ComponentName comp = new ComponentName(context.getPackageName(), GcmIntentService.class.getName()); startWakefulService(context, (intent.setComponent(comp))); setResultCode(Activity.RESULT_OK); } }
Receiverクラスが受け取ったGCMのインテントを処理するServiceクラスを作成します。
public class GcmIntentService extends IntentService { private static final String TAG = "GcmIntentService"; // 引数なしのコンストラクタを作成しないと例外で落ちてしまった public GcmIntentService() { super(GcmIntentService.class.getName()); } public GcmIntentService(String name) { super(name); } @Override protected void onHandleIntent(Intent intent) { Bundle extras = intent.getExtras(); // intentからGCMのメッセージを取得する GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this); String messageType = gcm.getMessageType(intent); // GCMのメッセージをタイプ別にフィルタリングする。 // 将来的に拡張されることを考慮し、存在しないタイプを無視するようにする if (!extras.isEmpty()) { if (GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR.equals(messageType)) { // エラー Log.d(TAG,"messageType: " + messageType + ",send error:" + extras.toString()); } else if (GoogleCloudMessaging.MESSAGE_TYPE_DELETED.equals(messageType)) { // サーバー側でメッセージを削除された Log.d(TAG,"messageType: " + messageType + ",message deleted:" + extras.toString()); } else if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE.equals(messageType)) { // メッセージ受信 Log.d(TAG,"messageType: " + messageType + ",received message:" + extras.toString()); } } // 処理の終了をReceiverに通知し、ロックを解放する GcmBroadcastReceiver.completeWakefulIntent(intent); } }
3. AndroidManifestを更新する
GCMを受け取るためのPermissionおよび、
上記で実装したメッセージ受信するReceiverクラス、
メッセージを処理するServiceクラスの定義をAndroidManifest
に記載します。
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.test.gcmtest" android:versionCode="1" android:versionName="1.0" > ・・・ <!-- Permissionの宣言 --> <permission android:name="com.test.gcmtest.permission.C2D_MESSAGE" android:protectionLevel="signature" /> <uses-permission android:name="com.test.gcmtest.permission.C2D_MESSAGE" /> <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" /> <uses-permission android:name="android.permission.WAKE_LOCK"/> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > ・・・ <!-- Receiverクラスの宣言 --> <receiver android:name=".GcmBroadcastReceiver" android:permission="com.google.android.c2dm.permission.SEND" > <intent-filter> <action android:name="com.google.android.c2dm.intent.RECEIVE" /> <category android:name="com.test.gcmtest" /> </intent-filter> </receiver> <!-- Serviceクラスの宣言 --> <service android:name="com.test.gcmtest.GcmIntentService" /> </application> ・・・
これで、受信側の準備は完了です。
3. GCM送信の準備
次に、サーバーからGCMを送信するために必要なregistration_id
を取得するクラスを実装します。
下記サンプルでは、Activity起動時に非同期でregist処理を行っています。
onPostExecute()
で取得できる文字列がregistration_id
です。
※
gcm.register()
の引数に渡すIDには、Developer Consolに表示されていたProject Number
を指定します。
public class MainActivity extends Activity { private GoogleCloudMessaging gcm; private Context context; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); context = getApplicationContext(); // GCMクラスを作成して非同期でregist処理を行う。 gcm = GoogleCloudMessaging.getInstance(this); registerInBackground(); } private void registerInBackground() { new AsyncTask<Void, Void, String>() { @Override protected String doInBackground(Void... params) { String msg = ""; try { if (gcm == null) { gcm = GoogleCloudMessaging.getInstance(context); } String regid = gcm.register("<app_id>"); msg = regid; Log.d("tag", "Device registered, registration ID=" + msg); } catch (IOException ex) { msg = "Error :" + ex.getMessage(); } return msg; } @Override protected void onPostExecute(String msg) { // registration IDを取得 // 従来であれば、ここから送信サーバーへregistration IDを送信するような流れになる Log.d("tag", msg); } }.execute(null, null, null); } }
GCMのテスト送信
最後に、サーバーからのGCMテスト送信を行います。
下記、curlコマンドでは、
Developers Consoleの準備
手順で取得したAPI Key
と上記で取得したregistration ID
を使って、
作成したAndroidアプリへ”Hello”という文字列を送信しています。
curl --header "Authorization: key=<API Key>" --header Content-Type:"application/json" https://android.googleapis.com/gcm/send -d "{\"registration_ids\":[\"<registration ID>\"],\"data\":{\"message\":\"Hello\"}}"
参考
http://zatomiya.blogspot.jp/2013/05/androidnotification.html
http://dev.classmethod.jp/smartphone/android/gcm/
http://developer.android.com/google/gcm/gs.html
http://developer.android.com/google/gcm/client.html
【Android】コンテンツプロバイダ(ContentProvider)を使ってみる
コンテンツプロバイダは、Androidのアプリケーションが管理しているリソースを 他アプリケーションから参照するための仕組みです。
例えば、連絡先アプリなど他アプリケーションから活用できるデータを持つアプリケーションが、
その他アプリケーションへデータを提供する際に使用されます。
今回は、SQLiteデータベースの情報を取得するサンプルを作成しました。
SQLiteデータベースへアクセスするためのクラスを作成
コンテンツプロバイダのデータ提供元となるデータベースを作成します。
testdb
という名前のDBにfruit
というテーブルを作成しています。
public class ShareDbHelpler extends SQLiteOpenHelper { private static final String DB_NAME = "testdb"; private static final int DB_VERSION = 1; // テーブル情報を定義 public static final String TABLE_NAME = "fruit"; public static final String COL_NAME = "firstName"; // カラムには、必ず「_id」という主キーをAUTOINCREMENTで作成する必要がある private static final String STRING_CREATE = "CREATE TABLE " + TABLE_NAME + " (_id INTEGER PRIMARY KEY AUTOINCREMENT, " +COL_NAME+" TEXT);"; public ShareDbHelpler(Context context) { super(context, DB_NAME, null, DB_VERSION); } @Override public void onCreate(SQLiteDatabase sqLiteDatabase) { // データベースのテーブルを作成する sqLiteDatabase.execSQL(STRING_CREATE); // データベースにサンプル値を挿入 ContentValues cv = new ContentValues(1); cv.put(COL_NAME, "Apple"); sqLiteDatabase.insert(TABLE_NAME, null, cv); cv = new ContentValues(3); cv.put(COL_NAME, "Orange"); sqLiteDatabase.insert(TABLE_NAME, null, cv); cv = new ContentValues(3); cv.put(COL_NAME, "Banana"); sqLiteDatabase.insert(TABLE_NAME, null, cv); } @Override public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i2) { // DBに変更があった場合は、とりあえずテーブルを削除する sqLiteDatabase.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME); } }
コンテンツプロバイダを継承したクラスを作成
コンテンツプロバイダを提供するためにContentProvider
のサブクラスを定義します。
ContentProviderを継承したクラスは、以下の6つのメソッドを実装する必要があります。
- query()
- insert()
- update()
- delete()
- getType()
- onCreate()
また、
サブクラスには、ContentProviderへアクセスするためのURI(content://~
)および、アクセス可能なカラム名を定数として定義します。
ContentProviderがアクセスする先がデータベースの場合、定義するカラム名とデータベースのカラム名を同じにするのが一般的です。
カラム名には、
レコードのIDとして整数型の_id
(定数ID)という名前のカラムを必ず含めるようにしなくてはなりません。
※他に全レコードで一意になるであろうフィールド ( URL など ) を持っていても含めなくてはならない
さらに、SQLiteデータベースを使用する場合は、この ID フィールドをINTEGER PRIMARY KEY AUTOINCREMENT
にしなくてはいけません。
以下は、frauit
テーブルへアクセスするためのContentProviderのサンプルです。
public class TestProvider extends ContentProvider { // コンテンツプロバイダのURIを定義 public static final Uri CONTENT_URI = Uri.parse("content://com.inon.shareddb.testsprovider/frauit"); // アクセスが可能なカラムを定義 public static final class Columns { public static final String _ID = "_id"; public static final String NAME = "name"; } /* URI マッチング */ // 全行取得とidでの取得を行えるよう、UriMatcherを使用する private static final int FRAUIT = 1; private static final int FRAUIT_ID = 2; private static final UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH); static { matcher.addURI(CONTENT_URI.getAuthority(), "frauit", FRAUIT); matcher.addURI(CONTENT_URI.getAuthority(), "frauit/#", FRAUIT_ID); } SQLiteDatabase db; @Override public boolean onCreate() { // 接続DBの作成 ShareDbHelpler helpler = new ShareDbHelpler(getContext()); db = helpler.getWritableDatabase(); return false; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { int result = matcher.match(uri); // 指定のURIが正しければ、取得結果(Cursor)を返却する switch (result) { case FRAUIT: return db.query(ShareDbHelpler.TABLE_NAME, projection, selection, selectionArgs, null, null, sortOrder); case FRAUIT_ID: return db.query(ShareDbHelpler.TABLE_NAME, projection, "_ID = ?", new String[]{uri.getLastPathSegment()}, null, null, sortOrder); default: return null; } } @Override public String getType(Uri uri) { return null; } @Override public Uri insert(Uri uri, ContentValues contentValues) { long id = db.insert(ShareDbHelpler.TABLE_NAME, null, contentValues); if (id >= 0) { return Uri.withAppendedPath(uri, String.valueOf(id)); } else { return null; } } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { int result = matcher.match(uri); switch (result) { case FRAUIT: return db.delete(ShareDbHelpler.TABLE_NAME, selection, selectionArgs); case FRAUIT_ID: return db.delete(ShareDbHelpler.TABLE_NAME, "_ID = ?", new String[] {uri.getLastPathSegment()}); default: return 0; } } @Override public int update(Uri uri, ContentValues contentValues, String selection, String[] selectionArgs) { int result = matcher.match(uri); switch (result) { case FRAUIT: return db.update(ShareDbHelpler.TABLE_NAME, contentValues, selection, selectionArgs); case FRAUIT_ID: return db.update(ShareDbHelpler.TABLE_NAME, contentValues, "_ID = ?", new String[]{uri.getLastPathSegment()}); default: return 0; } } }
AndroidManifestでコンテンツプロバイダを宣言する
Content Providerを使用するためにAndroidManifestに定義を追加する必要があります。
<provider android:authorities="com.sample.shareddb.testsprovider" android:name="com.sample.shareddb.TestProvider"> </provider>
android:name
には、クラス名を定義します。
android:authorities
には、外部からアクセスする際に使用するURIを定義します。
これは、パッケージ名を含めたクラス名を定義するのが一般的です。
コンテンツプロバイダへの問い合わせ
コンテンツプロバイダを介してデータを取得するには、ContentResolver
インスタンスを利用します。
query()
メソッドを使って取得したCursor
オブジェクトから各取得データへのアスセスが可能となります。
以下のサンプルでは、ActivityからContentResolverを利用してデータを取得し、ListViewへデータを表示しています。
本来は、取得したCursorオブジェクトは使用しなくなったタイミングで適切に破棄する必要がありますが、
今回は、サンプルのため何もしていません。
public class MainActivity extends Activity { Cursor mCoursor; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); String[] projection = new String[] {TestProvider.Columns._ID, TestProvider.Columns.NAME}; mCoursor = getContentResolver().query(TestProvider.CONTENT_URI, projection, null, null, null); SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_1, mCoursor, new String[] {TestProvider.Columns.NAME}, new int[] {android.R.id.text1}, 0); ListView list = (ListView) findViewById(R.id.list_view); list.setAdapter(adapter); } }
参考
http://www.techdoctranslator.com/android/guide/content-providers