SATCHのトラッキング・シナリオをSDカードからロードして使う
これで、トラッキングできる対象が無制限になるというわけです。
そんな必要はないかもしれませんが.....。
目次
初期画面はこんな感じ。
画面にタッチして、下段のメニュを消します。
メニューをタップ(クリック)してシナリオをロード。
「真珠の耳飾りの少女」を選んだ場合。
絵をトラッキングして、文字を表示。
この状態で、下段のメニュをタップすると、画面が変わります。
カメラを絵から外すと、何も表示しません。
Map Viewをタップした場合、マウリッツハイス美術館の場所を表示。
Web Viewをタップした場合、情報を表示。
StreetViewをタップした場合、新しい画面でストリートビューを表示。
左側に見えるのが、マウリッツハイス美術館です。
マウリッツハイス美術館の場合、indoor StreetViewが作成されていないので、単に周辺をウロウロするだけです。
例えば、「紳士とワインを飲む女」を選んだ場合。
ストリートビューはindoorなので、「ベルリン、絵画館」の中を移動できます。
コンパスモードにすれば、傾けたり見回したりすれば、ストリートビューはその動きに連動します。
手順はこんな感じです。
SATCHのシナリオを作る
SDカードにシナリオを保存する
アプリからシナリオをロードする
TOP
SATCHのシナリオを作る
SATCHでシナリオを作る雛形フォルダーを用意。
サンプル
トラキング用の画像を用意しておきます。
SATCHを起動して、フォルダーのdpdファイルを読み込みます。
メニュ -> Tools -> Computer Visionでトラッキングデータを作成。
データ作成の方法はこちらを参照(SATCHを使ってArt_ProjectでAR)
出来たら、メニュ-> SAve as で、trackerフォルダーにデータを保存。
シナリオを保存(Export)するフォルダーをデスクトップに作っておきます。
ネーミングは「Scenario_」に続いて、画像の名前を後ろに付けておきます。
画像の名前は、Eclipseでアプリを作成する際に使用しますので、シンプルなものが望ましいです。
アプリケーションIDを決めておきます。
例:com.kddi.satch.abcd123
このIDは他のシナリオに共通で使います。Eclipseでパッケージを作る際にも使用します。
Solution Explorerの中で、赤いマークがついたものがあれば、右クリックして Include in export listを選択。
赤いマークがなくなるまで続けます。
メニュ -> Project -> Exportでシナリオをエクスポート。
他の画像については......
サンプルフォルダーの中のtrackerフォルダーで、**.jpg、**.bin、tracker.xmlファイルを削除。
SATCHを再起動して、上の手順を繰り返します。
参考までに、サンプルとして使った絵はVermeerのもので、
The Wine of Glass
The Love Letter
The Milkmaid
Girl With a Pearl Earring
の4つです。上の3つまではArt_Projectで探せますが、最後の1つはArt_Projectにありません。
このリンクを参照
TOP
SDカードにシナリオを保存する
上で作成したシナリオが、
Scenario_girlwithapearlearring
Scenario_glasswine
Scenario_loveletter
Scenario_milkmaid
の4つだとします。
保存する前に、それぞれのシナリオで署名ファイルを取得しておいてください。
署名ファイルの取得方法は、SATCH Developers site
を参照。
署名ファイル取得時のIDはすべて共通で、シナリオ作成時に決めておいたものを使います。
スマホをPCとUSBで接続、SDカードはPC側から新規の外部ストレージとして認識されます。
開いて、Scenarioというフォルダーを作成して、この中に、上の4つのフォルダーをコピー。
何か警告がでるかもしれませんが、無視して実行。
フォルダー構造はこんな感じ。
TOP
アプリからシナリオをロードする
Eclipseでアプリを作成します。
参照するのは、SATCHのViewFlipperです。
ViewFlipperプロジェクトを参考にして、新しくプロジェクトを作成してください。
ただし、パッケージを作る際、com.kddi.satch.sampleviewflipperパッケージ名は、SATCHで使ったアプリケーションIDに変更。
主要な変更は3つ。
【SampleActivity_simpleMap.java】
public void onStart()内のloadScenario();は、コメントアウトするか削除し、起動時のシナリオ読み込みを停止。
loadScenario()関数は、引数ありに変更します。
こんな感じ。
public void loadScenario(String s_name){ String SDFile = android.os.Environment.getExternalStorageDirectory().getPath(); String dpdfile = SDFile + "/Scenario/Scenario_" + s_name + "/scenario_Multiread.dpd"; _kddiComponent.loadScenario(dpdfile); }
【SampleViewFlipper.java】
*メニュ用WebViewの追加
*下段メニュをタップした際の動き方修正
*StreetView表示用コードの追加
*メニュタップ時JavaScriptのインターフェース追加....etc
package com.kddi.satch.scenariomultiread; import java.util.List; import com.google.android.maps.*; import android.location.*; import com.kddi.satch.scenariomultireadactivity.MultireadActivity_simpleMap; import android.app.Activity; import android.content.Context; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.os.Handler; import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.webkit.WebChromeClient; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.ViewFlipper; import android.net.Uri;//add import android.content.Intent;//add public class ScenarioMultireadActivity extends MultireadActivity_simpleMap { private static final String THIS_CLASS_SHORT_NAME = ScenarioMultireadActivity.class.getName().replace("com.kddi.satch.scenariomultiread.", ""); private static final String THIS_LOGTAG = THIS_CLASS_SHORT_NAME; private static final String SCENARIO_NAME = "/assets/Scenario/Scenario_a/artDetection_multi.dpd"; protected String getSampleScenarioName() { return SCENARIO_NAME; } protected String getSampleLogTag() { return THIS_LOGTAG; } private ViewFlipper _viewFlipper; private MapView _mapView; private GoogleMapsItemizedOverlay _itemizedoverlay1; private GoogleMapsItemizedOverlay _itemizedoverlay2; private OverlayItem _overlayitem1; private OverlayItem _overlayitem2; private GeoPoint _point1; private GeoPoint _point2; private WebView _webView; //add private WebView _webView_menu;//menu private Handler mHandler; private String scenario_name = ""; double sv_latitude = 0; double sv_longitude = 0; private String _urlTargetPlace; private boolean _trackingStatus; private LocationManager mLocationManager; private static final int MENU_DETECTION = 0; private static final int MENU_WEBVIEW = 1; private static final int MENU_MAPVIEW = 2; private static final int MENU_STREETVIEW = 3; //add private static final int MENU_WEBMENU = 4; private void resetMembers() { _viewFlipper = null; _mapView = null; _itemizedoverlay1 = null; _itemizedoverlay2 = null; _overlayitem1 = null; _overlayitem2 = null; _point1 = null; _point2 = null; _webView = null; //add _webView_menu = null; //_trackingX = _trackingY = _trackingZ = 0; //prev_lat1 = prev_lat1 = 0; _trackingStatus = false; _urlTargetPlace = "http://www.google.com"; } @Override protected boolean isRouteDisplayed() { // from MapActivity return false; } @Override public void onCreate(Bundle savedInstanceState) { //Log.i( getSampleLogTag(), ".... onCreate" ); super.onCreate(savedInstanceState); // initialize values resetMembers(); // initialize inflated views {// Web view LayoutInflater li = (LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE); _webView = (WebView) li.inflate(R.layout.web, null); initWebView(); } {// Map view LayoutInflater li = (LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE); _mapView = (MapView) li.inflate(R.layout.map, null); initMapView(); } {// Menu view LayoutInflater li = (LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE); _webView_menu = (WebView) li.inflate(R.layout.web, null); initWebView_menu(); } mLocationManager = (LocationManager) getSystemService(LOCATION_SERVICE); Criteria criteria = new Criteria(); criteria.setAccuracy(Criteria.ACCURACY_FINE); // criteria.setAltitudeRequired(false); // criteria.setBearingRequired(false); // criteria.setCostAllowed(false); // criteria.setPowerRequirement(Criteria.POWER_LOW); // criteria.setSpeedRequired(false); // // String provider = mLocationManager.getBestProvider(criteria, true); mLocationManager.requestLocationUpdates(provider, 1000, // 1, // locationListener); //add mHandler = new Handler(); } @Override public void onDestroy() { //Log.i( getSampleLogTag(), ".... onDestroy" ); // release what we inflated _mapView = null; _webView = null; //add _webView_menu = null; super.onDestroy(); // final clean-up resetMembers(); } @Override public void postInitComponent() { //Log.i( getSampleLogTag(), "postInitComponent" ); _kddiComponent.activateAutoFocusOnDownEvent(true); _kddiComponent.registerCommunicationCallback("setTrackingStatus", this, "setTrackingStatus"); } @Override public void initContentView() { //Log.i( getSampleLogTag(), "initContentView" ); if (_isInitializedCorrectly) { _viewFlipper = new ViewFlipper(this); // Child 0 : D'Fusion View _viewFlipper.addView(_frameLayout); // Child 1 : Web View _viewFlipper.addView(_webView); // Child 2 : Map View _viewFlipper.addView(_mapView); // Child 3 : Menu View add _viewFlipper.addView(_webView_menu); // Activity content view will be the view flipper setContentView(_viewFlipper); new Handler().postDelayed(new Runnable() { public void run() { openOptionsMenu(); } }, 1000 ); //initial display _viewFlipper.setDisplayedChild(3); } } @Override public void releaseContentView() { //Log.i( getSampleLogTag(), "releaseContentView" ); if (_isInitializedCorrectly) { if (_viewFlipper != null) { _viewFlipper.removeAllViews(); } _viewFlipper = null; } } public void setTrackingStatus(String [] arrayOfString) { if(arrayOfString.length ==1){ if(arrayOfString[0].equals("true")){ _trackingStatus = true; }else if(arrayOfString[0].equals("false")){ _trackingStatus = false; } } } public void setMuseumPosition(double latitude,double longitude) { //double latitude1 = Double.parseDouble(pos_lis[0]); //double longitude1 = Double.parseDouble(pos_lis[1]); int lat2 = (int)(latitude*1E6); int lon2 = (int)(longitude*1E6); _point2 = new GeoPoint(lat2,lon2); } public void setUrlTargetPlace(int target_num) { MapController ctrl = _mapView.getController(); if(ctrl != null){ List<Overlay> mapOverlays = _mapView.getOverlays(); mapOverlays.clear(); initMapView(); if(target_num == 1){ ctrl.setCenter(_point1); }else if(target_num == 2){ ctrl.setCenter(_point2); } } _webView.loadUrl(_urlTargetPlace); } public boolean onCreateOptionsMenu(Menu menu) { menu.add(0, MENU_DETECTION, 0, "Art Detection").setIcon(R.drawable.easel); menu.add(0, MENU_WEBVIEW, 0, "Web View").setIcon(R.drawable.web); menu.add(0, MENU_MAPVIEW, 0, "Map View").setIcon(R.drawable.map); menu.add(0, MENU_STREETVIEW, 0, "StreetView").setIcon(R.drawable.pegman); menu.add(0, MENU_WEBMENU, 0, "Menu").setIcon(R.drawable.menu); return true; } public boolean onOptionsItemSelected(MenuItem item) { switch ( item.getItemId() ) { case MENU_DETECTION: _viewFlipper.setDisplayedChild(0); return true; case MENU_WEBVIEW: if (_trackingStatus == true){ _viewFlipper.setDisplayedChild(1); } return true; case MENU_MAPVIEW: if (_trackingStatus == true){ setUrlTargetPlace(2); } else{ setUrlTargetPlace(1); } if (_trackingStatus == true){ _viewFlipper.setDisplayedChild(2); } return true; case MENU_STREETVIEW: if (_trackingStatus == true){ String uri = "google.streetview:cbll="+ sv_latitude +"," + sv_longitude; Intent streetView = new Intent(android.content.Intent.ACTION_VIEW,Uri.parse(uri)); startActivity(streetView); } return true; case MENU_WEBMENU: // _viewFlipper.setDisplayedChild(3); return true; } return false; } private class MyWebViewClient extends WebViewClient { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { view.loadUrl(url); return true; } } public void initMapView() { _mapView.setBuiltInZoomControls(true); List<Overlay> mapOverlays = _mapView.getOverlays(); //overlay2 Drawable drawableMuseum = this.getResources().getDrawable(R.drawable.museum); _itemizedoverlay1 = new GoogleMapsItemizedOverlay(drawableMuseum, this.getApplicationContext()); if (_point2 == null){ double latitude2 = 0;//dummy double longitude2 = 0;//dummy int lat2 = (int)(latitude2*1E6); int lon2 = (int)(longitude2*1E6); _point2 = new GeoPoint(lat2,lon2); _overlayitem2 = new OverlayItem(_point2, "Hello!", "I'm 2"); _itemizedoverlay1.addOverlay(_overlayitem2); }else{ _overlayitem2 = new OverlayItem(_point2, "Hello!", "I'm 2"); _itemizedoverlay1.addOverlay(_overlayitem2); mapOverlays.add(_itemizedoverlay1); } // overlay1 Drawable drawableMyloc = this.getResources().getDrawable(R.drawable.person); _itemizedoverlay2 = new GoogleMapsItemizedOverlay(drawableMyloc, this.getApplicationContext()); if (_point1 == null) { double latitude1 = 35.36286726458948; double longitude1 = 138.73157501220703; int lat1 = (int)(latitude1*1E6); int lon1 = (int)(longitude1*1E6); _point1 = new GeoPoint(lat1,lon1); } _overlayitem1 = new OverlayItem(_point1, "Hello!", "I'm 1"); _itemizedoverlay2.addOverlay(_overlayitem1); mapOverlays.add(_itemizedoverlay2); } public void initWebView() { _webView.getSettings().setJavaScriptEnabled(true); _webView.getSettings().setBuiltInZoomControls(true); _webView.getSettings().setSupportZoom(true); final ScenarioMultireadActivity activity = this; _webView.setWebChromeClient(new WebChromeClient() { public void onProgressChanged(WebView view, int progress) { // Activities and WebViews measure progress with different scales. // The progress meter will automatically disappear when we reach 100% ((Activity) activity).setProgress(progress * 1000); } }); // to handle its own URL requests : _webView.setWebViewClient(new MyWebViewClient()); _webView.loadUrl("http://www.google.fr"); } public void initWebView_menu() { final ScenarioMultireadActivity activity = this; _webView_menu.setWebChromeClient(new WebChromeClient() { public void onProgressChanged(WebView view, int progress) { // Activities and WebViews measure progress with different scales. // The progress meter will automatically disappear when we reach 100% ((Activity) activity).setProgress(progress * 1000); } }); // to handle its own URL requests : _webView_menu.setWebViewClient(new MyWebViewClient()); //add _webView_menu.getSettings().setJavaScriptEnabled(true); JavascriptAdapter jsobj = new JavascriptAdapter(this); _webView_menu.addJavascriptInterface(jsobj, "android_ar"); _webView_menu.loadUrl("file:///android_asset/www/index.html"); } //------------------------------------ private LocationListener locationListener = new LocationListener() { @Override public void onLocationChanged(Location location) { double latitude = location.getLatitude(); double longitude = location.getLongitude(); int lat = (int)(latitude*1E6); int lon = (int)(longitude*1E6); _point1 = new GeoPoint(lat,lon); } @Override public void onProviderDisabled(String provider) { } @Override public void onProviderEnabled(String provider) { } @Override public void onStatusChanged(String provider, int status, Bundle extras) { switch (status) { case LocationProvider.AVAILABLE: //Log.v("Status", "AVAILABLE"); break; case LocationProvider.OUT_OF_SERVICE: //Log.v("Status", "OUT_OF_SERVICE"); break; case LocationProvider.TEMPORARILY_UNAVAILABLE: //Log.v("Status", "TEMPORARILY_UNAVAILABLE"); break; } } }; //-- javaScript ->java interface add class JavascriptAdapter { private Context con; public JavascriptAdapter(Context con) { this.con = con; } // public void load_scenario(String s_name){ scenario_name = s_name; if(scenario_name.equals("girlwithapearlearring")){ setMuseumPosition(52.080266, 4.31473); sv_latitude = 52.080266; sv_longitude = 4.31473; //_urlTargetPlace = "http://wisteriahill.sakura.ne.jp/jqm_viewflipper/index.html"; _urlTargetPlace = "http://ja.wikipedia.org/wiki/%E7%9C%9F%E7%8F%A0%E3%81%AE%E8%80%B3%E9%A3%BE%E3%82%8A%E3%81%AE%E5%B0%91%E5%A5%B3"; }else if(scenario_name.equals("glasswine")){ setMuseumPosition(52.508472,13.365417); sv_latitude = 52.508472; sv_longitude = 13.365417; _urlTargetPlace = "http://wisteriahill.sakura.ne.jp/jqm_viewflipper/glasswine.html"; }else if(scenario_name.equals("loveletter")){ setMuseumPosition(52.359767, 4.884356); sv_latitude = 52.359767; sv_longitude = 4.884356; _urlTargetPlace = "http://wisteriahill.sakura.ne.jp/jqm_viewflipper/loveletter.html"; }else if(scenario_name.equals("milkmaid")){ setMuseumPosition(52.359767, 4.884356); sv_latitude = 52.359767; sv_longitude = 4.884356; _urlTargetPlace = "http://wisteriahill.sakura.ne.jp/jqm_viewflipper/milkmaid.html"; } // loadScenario(scenario_name); (new Thread(new Runnable() { @Override public void run() { mHandler.post(new Runnable() { @Override public void run() { _viewFlipper.setDisplayedChild(0); } }); } })).start(); } } }
メニュ用のファイルを追加しておきます。メニュはWebViewで表示するので、HTMLファイルを追加。
assetsにwwwというフォルダーを作成し、そのなかにindex.htmlをおきます。
【index.html】
<!DOCTYPE HTML> <html> <head> <meta charset="UTF-8"> <title></title> <meta name="viewport" content="width=device-width, initial-scale=1,minimum-scale=1, maximum-scale=1, user-scalable=no"> <link rel="stylesheet" href="http://code.jquery.com/mobile/1.0.1/jquery.mobile-1.0.1.min.css" /> <script src="http://code.jquery.com/jquery-1.6.1.min.js"></script> <script src="http://code.jquery.com/mobile/1.0.1/jquery.mobile-1.0.1.min.js"></script> <link rel="stylesheet" href="http://code.jquery.com/mobile/1.0.1/jquery.mobile-1.0.1.min.css" /> <link href="http://www.google.com/uds/css/gsearch.css" type="text/css" rel="stylesheet"/> <script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=true&language=ja"></script> <script type="text/javascript" charset="utf-8"> var information = ""; function load_scenario(s_name){ android_ar.load_scenario(s_name); } </script> </head> <body> <div id="message" style="top:30px;left:30px;position:absolute;visibility:visible"> <br> <br> 右のボタンをクリック <br> <br> して、検出用データを <br> <br> ロードしてください。 </div> <div id="detect_operation" style="top:30px;left:250px;position:absolute;visibility:visible"> <table border=03 bgcolor="#ffffff" cellspacing=0 cellpadding=0> <tr> <td> <table border=0 cellspacing=1 cellpadding=3> <tr><td><img src="img/girlpearlearring.png"></td><td><input type="button" style="width:180px" value="真珠の耳飾の少女" onClick="load_scenario('girlwithapearlearring')"></td></tr> <tr align=center><td><img src="img/glasswine.png"></td><td><input type="button" style="width:180px" value="紳士とワインを飲む女" onClick="load_scenario('glasswine')"></td></tr> <tr align=center><td><img src="img/loveletter.png"></td><td><input type="button" style="width:180px" value="恋文" onClick="load_scenario('loveletter')"></td></tr> <tr align=center><td><img src="img/milkmaid.png"></td><td><input type="button" style="width:180px" value="牛乳を注ぐ女" onClick="load_scenario('milkmaid')"></td></tr> </table> </td> </tr> </table> </div> </body> </html>
これで、メニュをそれぞれタップ(クリック)するごとに対応するシナリオがSDカードからロードされます。
TOP
トップページ| サイトマップ|