SATCHのViewFlipperを使ってみます..の第二弾。

今回は、ゴッホの「ひまわり」のみをトラッキングします。

検出したら、情報表示サイトを開いて、その絵を所蔵している美術館をGoogle Mapsで見てみましょう。

さらに、StreetViewを開いて、美術館の中をウォーキング。

Art_Projectのindoor StreetViewみたいに、フロア・プランなんぞはありませんが、雰囲気は分かります。

こんな感じです

絵画の検出には、SATCHを使ってArt_ProjectでARで使ったやり方を使用。

絵画は、ゴッホの「ひまわり」を使います。




絵画を検出していない場合





メニュの「Map View」をタップすると、GPSで取得した現在地を表示。





GPSでの位置情報が取得できていない場合、とりあえず「富士山」にロケーションされています。





「Web View」をタップすると、ただのGoogleの検索画面を表示。





「StreetView」をタップした場合。








GPSで位置情報が取得できていない場合やご近所にStreetViewのポイントがない場合、単に真っ黒な画面。





絵画を検出した場合

緑色の文字が表示されれば、検出OKです。

緑色の文字が表示された状態のままで、以下を実行。





メニュの「Map View」をタップすると、この絵画を所蔵するゴッホ美術館の場所を表示。





「Web View」をタップすると、絵画などについての情報を表示。





「StreetView」をタップした場合、ゴッホ美術館をストーリートビュー。








美術館の中に入っていきましょう。





「コンパスモード」を使えば、スマホを傾けたり周囲に向けることでストリートビューの方向が変わります。

我が家のボロ部屋が美術館になったみたいで、結構、臨場感があります。

以上

TOP

SATCHのtracking.luaのコード

絵画の検出については、SATCHを使ってArt_ProjectでARを参照。



【tracking.lua】

local text = Text2D(getCurrentScene():getObjectByName("text"))

local componentInterface = getComponentInterface()


-- GLOBAL VARIABLES
-- tracking statuts: if 1 : tracking, if 0 : no tracking
gtrackingStatus = 0
-- get the keyframe index from a tracked object with auto-initialization
gtrackingKeyFrameIndex = -1

-- scene
local scene = getCurrentScene()
-- get the virtual camera, will be used to send to the MLT
local camera = Camera(scene:getCurrentCamera())
-- get the videocapture, will be used to send to the MLT
local videoCapture_live = VideoCapture(scene:getObjectByName("videocapture_live"))

-- Tracking
local MLTPlugin = getMLTPluginManager()
-- Error status
local errorStatus = eOk
-- tracking index : the index of the tracker.xml (because we can open more than 1 tracking.xml file).
local trackingIndex = -1
-- the fps of the Tracking engine
local trackingRate = 0
-- vector to put the tracking position
local trackingPosition = Vector3()
-- quaternion to put the tracking orientation
local trackingOrientation = Quaternion()
-- 3D object receiving tracking pose
--local trackingObject = Object3D(scene:getObjectByName("Tracking_Object"))
-- object index from the tracking scenario (0 : first object, 1 : second object...) (this is the index in the "Objects" panel of the CV GUI)
local trackingObjectIndex = 0

local found_sendflag = false
local lost_sendflag = false


-- this is how to start a tracking. the function needs the path to the tracker.xml file, the videocapture id and the camera object.
errorStatus, trackingIndex = MLTPlugin:startTracking("tracker/tracker.xml", videoCapture_live:getVidCapID(), camera)



-- if the tracking has correctly started, we can proceed to an infinite loop
if errorStatus == eOk then
    repeat
        
        errorStatus, gtrackingStatus = MLTPlugin:getTargetStatus(trackingIndex, trackingObjectIndex)
        
        errorStatus, gtrackingKeyFrameIndex = MLTPlugin:getRecognizedKeyFrameIndex(trackingIndex, trackingObjectIndex)

        -- if our object is detected...
        if (gtrackingStatus == 1) then
            
            if found_sendflag == false then
                --LOG("found")
                
            -- call java method
            componentInterface:executeAppFunc("setTrackingStatus","true")
                
            text:setText("The Sunflowers(Vincent van Gogh)")
            text:setVisible(true)
                
            found_sendflag = true
            lost_sendflag = false
          end
        -- if the tracking is lost
        else
            if lost_sendflag == false then
                --LOG("lost")
                
                -- call java method
                componentInterface:executeAppFunc("setTrackingStatus","false")
                
                
                text:setVisible(false)
                
                found_sendflag = false
                lost_sendflag = true
            end
        end
        
        
    until coroutine.yield()
end


SATCHのシナリオを「com.kddi.satch.xxxxxx」で保存。

xxxxxxのところは、ご自分で適当に設定してください。

このアプリケーションIDは、EclipseのAndroidManifest.xmlのパッケージ名と一致させます。

でないと、アプリをデプロイする際に、ライセンスエラーになります。

TOP

Eclipseのプロジェクト

ソースはSATCHのViewFlipperを参照。

ダウンロードできるようにしておきましたので、なんかの参考にしていただければ...。

ViewFlipper

このままでは、素直に使えません(^^)。

これをベースにして、プロジェクトを再作成してください。

その際必要なのは、

com.kddi.satch.sampleviewflipperのプロジェクト名をSATCHのシナリオ作成で使ったものに変更。
res/layout/map.xmlのGoogleのキーを自分のものに変更(この辺はSATCHのDevelopers siteのViewFlipperを参照)

GPSを使うので、AndroidManifest.xmlに以下を追加。

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />


javaファイルで基本的に変更がかかるのは、SampleViewFlipper.javaだけです。

参考になるかどうか分かりませんが例です。SATCHのオリジナルと異なるのは、GPSの位置情報取得用のコードを入れています。

StreetViewは、本来ViewFlipperで実装したかったのですが、MapViewでsetStreetView()関数が非推奨になって、使い方がわからなかったのでintentで画面遷移して表示しています。

ぜんぜんユーザーフレンドリーじゃないので、コードが分かったら、差し替えます。


package com.kddi.satch.sunflowersviewflipper;

import java.util.List;

import com.google.android.maps.*;
import android.location.*;

import com.kddi.satch.sunflowersactivity.SunflowersActivity_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 SunflowersViewFlipper extends SunflowersActivity_simpleMap
{
    private static final String       THIS_CLASS_SHORT_NAME = SunflowersViewFlipper.class.getName().replace("com.kddi.satch.sunflowersviewflipper.", "");
    private static final String     THIS_LOGTAG           = THIS_CLASS_SHORT_NAME;
    private static final String     SCENARIO_NAME         = "/assets/Scenario/Scenario_a/art_project_sunflowers.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;
    
    private String    _urlTargetPlace;
    private boolean _trackingStatus;
    private LocationManager mLocationManager;
    private double my_latitude = 0;
    private double my_longitude = 0;
    
    private static final int    MENU_VIEW_DFUSION    = 0;
    private static final int    MENU_VIEW_WEB       = 1;
    private static final int    MENU_VIEW_MAP      = 2;
    private static final int            MENU_STREET_VIEW    = 3;
    


    private void resetMembers()
    {
        _viewFlipper = null; 

        _mapView = null;
        _itemizedoverlay1 = null;
        _itemizedoverlay2 = null;
        _overlayitem1 = null;
        _overlayitem2 = null;
        _point1 = null;
        _point2 = null;
        
        _webView = null;
        
        
        _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();
        }
        
        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);
    }
    
    
    @Override
    public void onDestroy() {
        Log.i( getSampleLogTag(),       ".... onDestroy" );   
        
        // release what we inflated
         _mapView = null;
         _webView = 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 : Gogh 
            _viewFlipper.addView(_frameLayout);
        
            // Child 1 : Web View
            _viewFlipper.addView(_webView);
            
            // Child 2 : Map View
            _viewFlipper.addView(_mapView);
            
            
            // Activity content view will be the view flipper
            setContentView(_viewFlipper);
            
            new Handler().postDelayed(new Runnable() {
                        public void run() {
                            openOptionsMenu();
                        }
                    }, 1000
                );
        }
    }
    
    @Override
    public void releaseContentView() {
        Log.i( getSampleLogTag(),       "releaseContentView" );

        if (_isInitializedCorrectly)
        {
            if (_viewFlipper != null) {
                _viewFlipper.removeAllViews();
            }
            _viewFlipper = null;
        }
    }    
    
    
    public void setTrackingStatus(String [] arrayOfString)
    {
        Log.i("STATUS",arrayOfString[0]);
        
        if(arrayOfString.length ==1){
            if(arrayOfString[0].equals("true")){
                
                setTrackingStatus(true);
                
                
            }else{
                
                setTrackingStatus(false);
            }
        }
    }
    
    
    
    
    public void setTrackingStatus(boolean trackingStatus)
    {
        _trackingStatus = trackingStatus;
    }  
    
    
    public void setUrlTargetPlace(int target_num)
    {
        
        MapController ctrl = _mapView.getController();
        if(ctrl != null){
            if(target_num == 1){
                
                
                List<Overlay> mapOverlays = _mapView.getOverlays();
                
                mapOverlays.clear();   
                
                initMapView();

                
                
                ctrl.setCenter(_point1);
                _urlTargetPlace = "http://www.google.fr";
                
            }else if(target_num == 2){
                ctrl.setCenter(_point2);
                _urlTargetPlace = "http://wisteriahill.sakura.ne.jp/jqm_viewflipper/sunflowers.html";
                
            }
        }
        _webView.loadUrl(_urlTargetPlace);
    }
    
    public boolean onCreateOptionsMenu(Menu menu) 
    {
        menu.add(0, MENU_VIEW_DFUSION,  0, "Gogh's Sunflowers").setIcon(R.drawable.sunflowers);
        menu.add(0, MENU_VIEW_WEB,    0, "Web view").setIcon(R.drawable.web);
        menu.add(0, MENU_VIEW_MAP,    0, "Map view").setIcon(R.drawable.map);
        menu.add(0, MENU_STREET_VIEW,   0, "StreetView").setIcon(R.drawable.pegman);
        return true;
    }

    public boolean onOptionsItemSelected(MenuItem item) 
    {
        switch ( item.getItemId() )
        {
            case MENU_VIEW_DFUSION:
                _viewFlipper.setDisplayedChild(0);
                return true;
            case MENU_VIEW_WEB:
                _viewFlipper.setDisplayedChild(1);
                return true;
            case MENU_VIEW_MAP:
                _viewFlipper.setDisplayedChild(2);
                if (_trackingStatus == true){
                    setUrlTargetPlace(2);
                } else{
                    setUrlTargetPlace(1);
                }
                return true;
            case MENU_STREET_VIEW:
                double sv_latitude = 0;
                double sv_longitude = 0;
                
                if (_trackingStatus == true){
                    sv_latitude = 52.358417;
                    sv_longitude = 4.881083;
                } else{
                    sv_latitude = my_latitude;
                    sv_longitude = my_longitude;
                }
                
                
                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;
        }
        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);
        
            //overlay2 Gogh Museum
            List<Overlay> mapOverlays = _mapView.getOverlays();
            Drawable drawableMuseum = this.getResources().getDrawable(R.drawable.van_gogh_museum);
            _itemizedoverlay1 = new GoogleMapsItemizedOverlay(drawableMuseum, this.getApplicationContext());
             
            double latitude2 = 52.358417;
            double longitude2 = 4.881083;
            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);
            mapOverlays.add(_itemizedoverlay1);
            
            
            
            
            // overlay1 MyLoc
            Drawable drawableMyLoc = this.getResources().getDrawable(R.drawable.home);
            _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 SunflowersViewFlipper 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");
    }
    
    //-------------------------------
    private LocationListener locationListener = new LocationListener() {
        @Override
        public void onLocationChanged(Location location) {
            my_latitude = location.getLatitude();
            my_longitude = location.getLongitude();
            int lat = (int)(my_latitude*1E6);
                int lon = (int)(my_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;
            }
        }
    };
}
//-- end of file --




コード内のパッケージ名やファイル名、SCENARIO_NAMEのパスは修正してください。





TOP

公開用Google ApiKey取得

ViewFlipperサンプルでは、MapViewを使ってGoogle Mapsを表示しています。

このサンプルを使って新しくプロジェクトを作成し  apkを公開する場合、公開用のGoogle Apiキーを取得する必要があります。  

 ここでは、既にキーストアが作成されているものとします。  

 キーストアの作成やデジタル署名したapkの作成方法は、
PhoneGapでネイティブアプリ の、「ネイティブアプリを作って、ダウンロード・インストール」の項を参照。

まず、DOS窓を開きます。

以下のコマンドを発行。

keytool -list -keystore <作成したキーストアのフルパス>

パスワードを聞いてきますので、これもキーストア作成時のパスワードを使用。

証明書のフィンガープリントが表示されます。


Sign Up for the Android Maps API のページを開きます。

ページの下の、I have read and agree ...にチェックを入れ、My certificate's MD5 fingerprint:の欄に先ほどのフィンガープリントを入力して、Generate API Keyのボタンをクリック。

表示されたキーが公開用のキーになります。

これを、res->layout->map.xmlのandroid:apiKeyにセットします。

これで、MapViewでGoogle Mapsが表示されるようになります。

TOP





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