通常、SATCHのトラッキング・シナリオはassetsから読み込みますが、今回は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





トップページ| サイトマップ|