com.dragon4.owo.ar_trace.ARCore.MixView.java Source code

Java tutorial

Introduction

Here is the source code for com.dragon4.owo.ar_trace.ARCore.MixView.java

Source

/*
 * Copyright (C) 2010- Peer internet solutions
 *
 * This file is part of mixare.
 *
 * This program is free software: you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License
 * for more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <http://www.gnu.org/licenses/>
 */
package com.dragon4.owo.ar_trace.ARCore;
/*
 * Copyright (C) 2010- Peer internet solutions
 *
 * This file is part of mixare.
 *
 * This program is free software: you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License
 * for more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <http://www.gnu.org/licenses/>
 */

/**
 * edited by joyeongje,Mansu on 2016. 12. 31..
 */

import android.app.Activity;
import android.app.AlertDialog;
import android.app.SearchManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Color;
import android.hardware.Camera;
import android.hardware.GeomagneticField;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.provider.Settings;
import android.support.design.widget.Snackbar;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentTransaction;
import android.text.Editable;
import android.text.SpannableString;
import android.text.SpannableStringBuilder;
import android.text.TextWatcher;
import android.text.style.ForegroundColorSpan;
import android.util.Log;
import android.util.TypedValue;
import android.view.*;
import android.view.View.OnTouchListener;
import android.view.ViewGroup.LayoutParams;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.dragon4.owo.ar_trace.ARCore.Activity.SearchCategoryListActivity;
import com.dragon4.owo.ar_trace.ARCore.Activity.SearchKeywordListActivity;
import com.dragon4.owo.ar_trace.ARCore.Activity.TraceActivity;
import com.dragon4.owo.ar_trace.ARCore.Activity.WriteReviewActivity;
import com.dragon4.owo.ar_trace.ARCore.Marker.ARMarker;
import com.dragon4.owo.ar_trace.ARCore.Marker.Compatibility;
import com.dragon4.owo.ar_trace.ARCore.Marker.SocialARMarker;
import com.dragon4.owo.ar_trace.ARCore.data.DataHandler;
import com.dragon4.owo.ar_trace.ARCore.data.DataProcessor.DataConvertor;
import com.dragon4.owo.ar_trace.ARCore.data.DataSource;
import com.dragon4.owo.ar_trace.ARCore.gui.PaintScreen;
import com.dragon4.owo.ar_trace.ARCore.render.Matrix;
import com.dragon4.owo.ar_trace.Configure.ClientInstance;
import com.dragon4.owo.ar_trace.FCM.FCMMessagingService;
import com.dragon4.owo.ar_trace.NaverMap.FragmentMapview;
import com.dragon4.owo.ar_trace.NaverMap.NMapPOIflagType;
import com.dragon4.owo.ar_trace.R;
import com.nhn.android.maps.maplib.NGeoPoint;
import com.tsengvn.typekit.TypekitContextWrapper;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.UnsupportedEncodingException;
import java.lang.reflect.Array;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ExecutionException;

import static android.hardware.SensorManager.SENSOR_DELAY_GAME;

// ??  ? () ?

public class MixView extends FragmentActivity implements SensorEventListener, LocationListener, OnTouchListener {

    private Sensor orientationSensor;
    private SensorManager sensorMgr_ori;

    public static double gpsLat = 0;//gps?   
    public static double gpsLong = 0;

    // ? ? ?? 
    private CameraSurface camScreen;
    private AugmentedView augScreen;

    private boolean isInited; //  ? ? 
    private MixContext mixContext; // ? ?
    static PaintScreen dWindow; // ? ?
    private static DataView dataView;
    private Thread downloadThread; // ? ?   

    // ? ?  
    private float RTmp[] = new float[9];
    private float Rot[] = new float[9];
    private float I[] = new float[9];
    private float grav[] = new float[3];
    private float mag[] = new float[3];

    //    ? 
    private SensorManager sensorMgr;
    private List<Sensor> sensors;
    private Sensor sensorGrav, sensorMag;
    private LocationManager locationMgr;
    private boolean isGpsEnabled;

    // ? ?  ?
    private int rHistIdx = 0;
    private Matrix tempR = new Matrix();
    private Matrix finalR = new Matrix();
    private Matrix smoothR = new Matrix();
    private Matrix histR[] = new Matrix[60];
    private Matrix m1 = new Matrix();
    private Matrix m2 = new Matrix();
    private Matrix m3 = new Matrix();
    private Matrix m4 = new Matrix();

    private WakeLock mWakeLock; // ? ??   

    private boolean fError; // ? 

    //  ?
    private int compassErrorDisplayed = 0;

    // MixView ? ?  & 
    public TopLayoutOnMixView topLayoutOnMixView;

    //? ?  ? 
    private Navigator navigator;

    public static final int SHOW_TRACE = 3;

    @Override
    protected void attachBaseContext(Context newBase) {
        super.attachBaseContext(TypekitContextWrapper.wrap(newBase));
    }

    static public DataView getDataView() {
        return dataView;
    }

    // ? ? 
    private TextView searchNotificationTxt;

    // ? ? 
    public static final String TAG = "Mixare";

    //  ? ? ?? ? ?
    public static final String PREFS_NAME = "MyPrefsFileForMenuItems";

    // GPS ?   
    public boolean isGpsEnabled() {
        return isGpsEnabled;
    }

    // ?  
    public void doError(Exception ex1) {
        if (!fError) {
            fError = true; // ?  true

            setErrorDialog(); // ? ? 

            ex1.printStackTrace(); // ? ? 
            try {
            } catch (Exception ex2) {
                ex2.printStackTrace();
            }
        }

        try {
            augScreen.invalidate(); // ?? ? ?
        } catch (Exception ignore) {
        }
    }

    // ? ?
    public void killOnError() throws Exception {
        if (fError)
            throw new Exception();
    }

    // ?. ??  ? ? ?  ?
    public void repaint() {
        dataView = new DataView(mixContext);
        dWindow = new PaintScreen();
    }

    // ? ?
    public void setErrorDialog() {
        //  ?? ? ?
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        // ??  ? 
        builder.setMessage(getString(DataView.CONNECTION_ERROR_DIALOG_TEXT));
        builder.setCancelable(false);

        // ? ? 
        /*Retry*/
        builder.setPositiveButton(DataView.CONNECTION_ERROR_DIALOG_BUTTON1, new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int id) {
                fError = false;
                //TODO improve
                try {
                    repaint(); // ? 
                } catch (Exception ex) { //  ? 
                    doError(ex);
                }
            }
        });
        /*Open settings*/
        builder.setNeutralButton(DataView.CONNECTION_ERROR_DIALOG_BUTTON2, new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int id) {
                //   ?? 
                Intent intent1 = new Intent(Settings.ACTION_WIRELESS_SETTINGS);
                startActivityForResult(intent1, 42);
            }
        });
        /*Close application*/
        builder.setNegativeButton(DataView.CONNECTION_ERROR_DIALOG_BUTTON3, new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int id) {
                System.exit(0); // ?  
            }
        });
        AlertDialog alert = builder.create();
        alert.show(); //  ? 
    }

    public void navercategoryClicked(View v) throws ExecutionException, InterruptedException {

        //  if (dataView.isFrozen())
        //   dataView.setFrozen(false);

        DataSource.DATASOURCE selectedDatasource = null;

        DataConvertor dataConvertor = new DataConvertor();

        // TODO: 2016. 12. 9.   ?.
        switch (v.getId()) {
        case R.id.ar_mixview_cafe:
            selectedDatasource = DataSource.DATASOURCE.CAFE;
            break;

        case R.id.ar_mixview_bus:
            selectedDatasource = DataSource.DATASOURCE.BUSSTOP;
            break;

        case R.id.ar_mixview_convenience_store:
            selectedDatasource = DataSource.DATASOURCE.Convenience;
            break;

        case R.id.ar_mixview_restaurant:
            selectedDatasource = DataSource.DATASOURCE.Restaurant;
            break;

        case R.id.ar_mixview_bank:
            selectedDatasource = DataSource.DATASOURCE.BANK;
            break;

        case R.id.ar_mixview_hospital:
            selectedDatasource = DataSource.DATASOURCE.HOSPITAL;
            break;

        case R.id.ar_mixview_lodgment:
            selectedDatasource = DataSource.DATASOURCE.ACCOMMODATION;
            break;

        default:
            selectedDatasource = null;
            break;
        }

        if (selectedDatasource == null)
            Toast.makeText(mixContext, "? ???", Toast.LENGTH_SHORT).show();

        else {
            Location location = mixContext.getCurrentLocation();

            dataView.getDataHandler().clearMarkerList(); //  
            topLayoutOnMixView.naverFragment.clearCategoryMarker(); // ??   

            for (DataSource.DATASOURCE dataSource : DataSource.DATASOURCE.values()) {

                if (dataSource != selectedDatasource)
                    mixContext.setDataSource(dataSource, false);
                else
                    mixContext.setDataSource(selectedDatasource,
                            !mixContext.isDataSourceSelected(selectedDatasource));
            }

            //dataView.getDataHandler().cleaMarketListUnCheckedDataSource(selectedDatasource); //  
            Log.i(selectedDatasource.toString(), "?");
            if (mixContext.isDataSourceSelected(selectedDatasource)) {
                dataView.requestData(
                        DataSource.createRequestCategoryURL(selectedDatasource, location.getLatitude(),
                                location.getLongitude(), location.getAltitude(), 20),
                        DataSource.dataFormatFromDataSource(selectedDatasource), selectedDatasource);
            }

        }
    }

    //  ?? ? 
    private BroadcastReceiver naviRecevicer = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals("NAVI")) {
                String guide = intent.getStringExtra("GUIDE");
                Snackbar.make(getWindow().getDecorView().getRootView(), guide, Snackbar.LENGTH_INDEFINITE)
                        .setAction("", new View.OnClickListener() {
                            @Override
                            public void onClick(View v) {
                                Toast.makeText(getApplicationContext(), "?? .",
                                        Toast.LENGTH_SHORT).show();
                                MixState.enterNaviEnd = true;
                            }
                        }).show();
            }
        }
    };

    //  ?
    @Override
    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        DataSource.createIcons(getResources());

        try {
            // ??
            final PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
            // ?    ?? ?
            this.mWakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "My Tag");
            // ?? 
            locationMgr = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
            //  ?? . 2 ?? (1/1000s), 3 ?? (m)? ? 
            locationMgr.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 3, this);

            //orientation sensor 
            sensorMgr_ori = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
            orientationSensor = sensorMgr_ori.getDefaultSensor(Sensor.TYPE_ORIENTATION);

            killOnError(); // ?  ?
            requestWindowFeature(Window.FEATURE_NO_TITLE); // ?   ? 

            //  ?? 
            FrameLayout frameLayout = new FrameLayout(this);

            //  ?    ?, ? 
            frameLayout.setMinimumWidth(3000);
            frameLayout.setPadding(10, 0, 10, 10);

            // ? ? ? ?? ?
            camScreen = new CameraSurface(this);
            augScreen = new AugmentedView(this);
            setContentView(camScreen); // ? ?? ?  ? 

            // ? ?? ? 
            addContentView(augScreen, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));

            // ? ? ? ?   ?.
            // ? ?  ?  ?? ?  ?  ?
            addContentView(frameLayout, new FrameLayout.LayoutParams(LayoutParams.FILL_PARENT,
                    LayoutParams.WRAP_CONTENT, Gravity.BOTTOM));

            topLayoutOnMixView = new TopLayoutOnMixView(this);
            RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
                    ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT);
            addContentView(topLayoutOnMixView.mainArView, params);

            // ? ? ? topLayoutOnMixView ?  ?
            handleIntent(getIntent()); // ?? 

            //  ? ? ?
            if (!isInited) {
                mixContext = new MixContext(this); // ? ?
                // ? ?
                mixContext.downloadManager = new DownloadManager(mixContext);

                //? ?  ? 
                navigator = new Navigator(mixContext, topLayoutOnMixView.naverFragment);

                // ? ? ?? ? ?
                dWindow = new PaintScreen();
                dataView = new DataView(mixContext);

                isInited = true; //   true

            }

            if (mixContext.isActualLocation() == false) {
                Toast.makeText(this, getString(DataView.CONNECTION_GPS_DIALOG_TEXT), Toast.LENGTH_LONG).show();
            }

        } catch (Exception ex) {
            doError(ex); //  ? ? 
        }

        //   ? 
        IntentFilter naviBraodFilter = new IntentFilter();
        naviBraodFilter.addAction("NAVI");
        registerReceiver(naviRecevicer, naviBraodFilter);
    }

    // ?? 
    private void handleIntent(Intent intent) {
        //  ? ? 
        if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
            String query = intent.getStringExtra(SearchManager.QUERY); //  ?
            //  doMixSearch(query);    //  
        } else if (intent.getExtras() != null) {
            FCMMessagingService.clear(intent.getStringExtra("traceID"));
            Intent traceIntent = new Intent(this, TraceActivity.class);
            traceIntent.putExtras(intent.getExtras());
            topLayoutOnMixView.mainArView.setVisibility(View.GONE);
            startActivityForResult(traceIntent, SHOW_TRACE);
        }
    }

    //  ?? ?
    @Override
    protected void onNewIntent(Intent intent) {
        setIntent(intent);
        handleIntent(intent);
    }

    private void doMixSearch(String query) {
        DataHandler jLayer = dataView.getDataHandler(); // ??  ?

        //     
        ArrayList<ARMarker> searchResults = new ArrayList<ARMarker>();

        // ? ? 1 ?? ? 
        if (jLayer.getMarkerCount() > 0) {
            // ? ?  ? 
            for (int i = 0; i < jLayer.getMarkerCount(); i++) {
                ARMarker ma = jLayer.getMarker(i);
                if (ma.getTitle().toLowerCase().indexOf(query.toLowerCase()) != -1) {
                    searchResults.add(ma);
                    /*?? ?? ?*/
                }
            }
        }
        //  ? ?? ? ? 
        if (searchResults.size() > 0) {
            dataView.setFrozen(true); // ??  
            jLayer.setMarkerList(searchResults); //  ? 
        } else //  ?   
            Toast.makeText(this, getString(DataView.SEARCH_FAILED_NOTIFICATION), Toast.LENGTH_LONG).show();
    }

    //  ?? 
    @Override
    protected void onPause() {
        super.onPause();

        try {
            this.mWakeLock.release(); // ?? ?? 

            // ?  ?? ?? 
            try {
                sensorMgr.unregisterListener(this, sensorGrav);
            } catch (Exception ignore) {
            }
            try {
                sensorMgr.unregisterListener(this, sensorMag);
            } catch (Exception ignore) {
            }
            try {
                sensorMgr_ori.unregisterListener(this, orientationSensor);
            } catch (Exception ignore) {

            }
            sensorMgr = null;

            //  ?? ?? 
            try {
                locationMgr.removeUpdates(this);
            } catch (Exception ignore) {
            }
            locationMgr = null;

            //  ? 
            try {
                mixContext.downloadManager.stop();
            } catch (Exception ignore) {
            }

            // ? ?? 
            if (fError) {
                finish();
            }
        } catch (Exception ex) {
            doError(ex); //  ? ? 
        }
    }

    //  ?? . ?  ??...
    @Override
    protected void onResume() {
        super.onResume();

        try {
            this.mWakeLock.acquire(); // ?? ?

            killOnError(); // ?  ?
            mixContext.mixView = this; // ??  
            dataView.doStart(); // ?? 
            dataView.clearEvents(); // ? ?

            double angleX, angleY; // ? x, y

            /*? ?  ? */
            angleX = Math.toRadians(-90);
            m1.set(1f, 0f, 0f, 0f, (float) Math.cos(angleX), (float) -Math.sin(angleX), 0f,
                    (float) Math.sin(angleX), (float) Math.cos(angleX));

            angleX = Math.toRadians(-90);
            angleY = Math.toRadians(-90);
            m2.set(1f, 0f, 0f, 0f, (float) Math.cos(angleX), (float) -Math.sin(angleX), 0f,
                    (float) Math.sin(angleX), (float) Math.cos(angleX));
            m3.set((float) Math.cos(angleY), 0f, (float) Math.sin(angleY), 0f, 1f, 0f, (float) -Math.sin(angleY),
                    0f, (float) Math.cos(angleY));

            m4.toIdentity();

            for (int i = 0; i < histR.length; i++) {
                histR[i] = new Matrix();
            }
            /*   */

            //  ? 
            sensorMgr = (SensorManager) getSystemService(SENSOR_SERVICE);

            // ?  ?
            // ?? 
            sensors = sensorMgr.getSensorList(Sensor.TYPE_ACCELEROMETER);
            if (sensors.size() > 0) {
                sensorGrav = sensors.get(0);
            }

            // ? 
            sensors = sensorMgr.getSensorList(Sensor.TYPE_MAGNETIC_FIELD);
            if (sensors.size() > 0) {
                sensorMag = sensors.get(0);
            }
            //// TODO: 2016-06-01
            if (sensors.size() > 0) {
                sensors = sensorMgr_ori.getSensorList(Sensor.TYPE_ORIENTATION);
                orientationSensor = sensors.get(0);
            }
            //  ??  ? ? ? ?
            sensorMgr.registerListener(this, sensorGrav, SENSOR_DELAY_GAME);
            sensorMgr.registerListener(this, sensorMag, SENSOR_DELAY_GAME);

            if (orientationSensor != null) {
                sensorMgr_ori.registerListener(this, orientationSensor, sensorMgr_ori.SENSOR_DELAY_GAME);
            }

            try {
                // ?? (Criteria)
                // http://developer.android.com/reference/android/location/Criteria.html
                Criteria c = new Criteria();

                // ? 
                c.setAccuracy(Criteria.ACCURACY_FINE);
                //c.setBearingRequired(true);

                // ?  
                locationMgr = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
                // ?? ? ?  ? . 2 , 3 
                locationMgr.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 4, this);

                // ?? ? ,   
                String bestP = locationMgr.getBestProvider(c, true);
                isGpsEnabled = locationMgr.isProviderEnabled(bestP);

                // gps, ? ? ?   
                Location hardFix = new Location("reverseGeocoded");

                try {
                    //  ? gps, ??     
                    Location gps = locationMgr.getLastKnownLocation(LocationManager.GPS_PROVIDER);
                    Location network = locationMgr.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);

                    //  ?  ?   
                    //  gps > ? > 
                    if (gps != null)
                        mixContext.curLoc = gps;
                    else if (network != null)
                        mixContext.curLoc = network;
                    else
                        mixContext.curLoc = hardFix;

                } catch (Exception ex2) { //  ? 
                    ex2.printStackTrace(); //  
                    mixContext.curLoc = hardFix; //   
                }
                // ? ?  ??  
                mixContext.setLocationAtLastDownload(mixContext.curLoc);

                // ?? .   ?   
                GeomagneticField gmf = new GeomagneticField((float) mixContext.curLoc.getLatitude(),
                        (float) mixContext.curLoc.getLongitude(), (float) mixContext.curLoc.getAltitude(),
                        System.currentTimeMillis());

                // ??   
                angleY = Math.toRadians(-gmf.getDeclination());
                m4.set((float) Math.cos(angleY), 0f, (float) Math.sin(angleY), 0f, 1f, 0f,
                        (float) -Math.sin(angleY), 0f, (float) Math.cos(angleY));
                mixContext.declination = gmf.getDeclination();
            } catch (Exception ex) {
                Log.d("mixare", "GPS Initialize Error", ex); //  ? 
            }
            //  ? 
            downloadThread = new Thread(mixContext.downloadManager);
            downloadThread.start();

        } catch (Exception ex) {
            doError(ex); // ? 

            try {
                // ???  
                if (sensorMgr != null) {
                    sensorMgr.unregisterListener(this, sensorGrav);
                    sensorMgr.unregisterListener(this, sensorMag);
                    sensorMgr = null;
                }
                //  ??   
                if (locationMgr != null) {
                    locationMgr.removeUpdates(this);
                    locationMgr = null;
                }
                // ??  ?? 
                if (mixContext != null) {
                    if (mixContext.downloadManager != null)
                        mixContext.downloadManager.stop();
                }
            } catch (Exception ignore) {
            }
        }

        //  ?? 
        // ??   ? ( ?? ) ?    
        if (dataView.isFrozen() && searchNotificationTxt == null) {
            searchNotificationTxt = new TextView(this);
            searchNotificationTxt.setWidth(dWindow.getWidth());
            searchNotificationTxt.setPadding(10, 2, 0, 0);
            searchNotificationTxt.setBackgroundColor(Color.DKGRAY);
            searchNotificationTxt.setTextColor(Color.WHITE);

            searchNotificationTxt.setOnTouchListener(this);
            addContentView(searchNotificationTxt,
                    new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
        } else if (!dataView.isFrozen() && searchNotificationTxt != null) {
            searchNotificationTxt.setVisibility(View.GONE);
            searchNotificationTxt = null;
        }
    }

    // ? ?  
    public void onSensorChanged(SensorEvent evt) {
        try {
            //         killOnError();

            // ?? , ?  ???  ? ? ? 
            if (evt.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
                grav[0] = evt.values[0];
                grav[1] = evt.values[1];
                grav[2] = evt.values[2];

                augScreen.postInvalidate(); // ? 
            } else if (evt.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
                mag[0] = evt.values[0];
                mag[1] = evt.values[1];
                mag[2] = evt.values[2];

                augScreen.postInvalidate(); // ? 
            }

            //  ? 
            SensorManager.getRotationMatrix(RTmp, I, grav, mag);
            //  (?)
            SensorManager.remapCoordinateSystem(RTmp, SensorManager.AXIS_X, SensorManager.AXIS_MINUS_Z, Rot);

            //  ? ? 
            tempR.set(Rot[0], Rot[1], Rot[2], Rot[3], Rot[4], Rot[5], Rot[6], Rot[7], Rot[8]);

            //       ,  
            finalR.toIdentity();
            finalR.prod(m4);
            finalR.prod(m1);
            finalR.prod(tempR);
            finalR.prod(m3);
            finalR.prod(m2);
            finalR.invert();

            // ? ?  ? ??   ...
            histR[rHistIdx].set(finalR);
            rHistIdx++;
            if (rHistIdx >= histR.length)
                rHistIdx = 0;

            smoothR.set(0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f);
            for (int i = 0; i < histR.length; i++) {
                smoothR.add(histR[i]);
            }
            smoothR.mult(1 / (float) histR.length);

            synchronized (mixContext.rotationM) {
                mixContext.rotationM.set(smoothR);
            }

        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    //  ? 
    @Override
    public boolean onTouchEvent(MotionEvent me) {
        try {
            killOnError(); // ?  ?

            //  ? x, y  
            float xPress = me.getX();
            float yPress = me.getY();

            // ?? ??  ?? ? ?? 
            if (me.getAction() == MotionEvent.ACTION_UP) {
                dataView.clickEvent(xPress, yPress);
            }

            return true;

        } catch (Exception ex) { //  
            //doError(ex);
            ex.printStackTrace();
            return super.onTouchEvent(me);
        }
    }

    // ? ? 
    public void onProviderDisabled(String provider) {
        if (locationMgr != null)
            isGpsEnabled = locationMgr.isProviderEnabled(LocationManager.GPS_PROVIDER);
    }

    // ?   . ?    ??
    public void onProviderEnabled(String provider) {
        if (locationMgr != null)
            isGpsEnabled = locationMgr.isProviderEnabled(LocationManager.GPS_PROVIDER);
    }

    // ?  . ?? 
    public void onStatusChanged(String provider, int status, Bundle extras) {

    }

    //  ?? 
    public void onLocationChanged(Location location) {
        try {
            killOnError(); // ?  ?
            gpsLat = location.getLatitude();
            gpsLong = location.getLongitude();

            // ? ?  ?. ? ? ?
            Log.v(TAG,
                    "Location Changed: " + location.getProvider() + " lat: " + location.getLatitude() + " lon: "
                            + location.getLongitude() + " alt: " + location.getAltitude() + " acc: "
                            + location.getAccuracy());

            //  ? ?? 
            if (LocationManager.GPS_PROVIDER.equals(location.getProvider())) {
                // ?  ?  
                synchronized (mixContext.curLoc) {
                    mixContext.curLoc = location;
                }
                // ??   
                if (!dataView.isFrozen()) // ??? ?? ?  
                    dataView.getDataHandler().onLocationChanged(location);

                /*   ??    3km ?? *
                 *   ??, ??        */
                //  ?  
                Location lastLoc = mixContext.getLocationAtLastDownload();
                if (lastLoc == null) // ??  
                    mixContext.setLocationAtLastDownload(location); // ?    
                else {
                    //  
                    float threshold = dataView.getRadius() * 1000f / 3f;
                    Log.v(TAG, "Location Change: " + " threshold " + threshold + " distanceto "
                            + location.distanceTo(lastLoc));
                    //    ??  
                    if (location.distanceTo(lastLoc) > threshold) {
                        Log.d(TAG, "Restarting download due to location change");
                        dataView.doStart();
                    }
                }
                isGpsEnabled = true; // GPS  ?
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    // ? ?? 
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
        // ? ? ?  ? 
        if (sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD && accuracy == SensorManager.SENSOR_STATUS_UNRELIABLE
                && compassErrorDisplayed == 0) {
            for (int i = 0; i < 2; i++) {
                //  ?? . ? 
                Toast.makeText(mixContext, "Compass data unreliable. Please recalibrate compass.",
                        Toast.LENGTH_LONG).show();
            }
            compassErrorDisplayed++;
        }
    }

    //  ?. onTouchEvent   ?
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        dataView.setFrozen(false); // ?? ?
        if (searchNotificationTxt != null) { // ? 
            searchNotificationTxt.setVisibility(View.GONE); // ? 
            searchNotificationTxt = null;
        }
        return false;
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        topLayoutOnMixView.mainArView.setVisibility(View.VISIBLE);

        if (requestCode == TopLayoutOnMixView.WRITE_REVIEW) {

        }

        else if (resultCode == RESULT_OK && requestCode == TopLayoutOnMixView.SEARCH_LIST) {
            double lat = data.getExtras().getDouble("lat");
            double lon = data.getExtras().getDouble("lon");

            //?  ?  
            if (navigator != null)
                navigator.run(lat, lon);
            else
                Toast.makeText(this, "? ?   .", Toast.LENGTH_LONG)
                        .show();
        } else if (resultCode == RESULT_OK && requestCode == MixView.SHOW_TRACE) {

        }
    }

    @Override
    public void onBackPressed() {
        if (!topLayoutOnMixView.onBackPressed())
            finish();
    }

    public void drawCategoryMarkers(List<ARMarker> markerList) {

        int naverCategory = -1;
        switch (markerList.get(0).getDatasource()) {
        case CAFE:
            naverCategory = NMapPOIflagType.CAFE;
            break;

        case BUSSTOP:
            naverCategory = NMapPOIflagType.BUS;
            break;

        case Convenience:
            naverCategory = NMapPOIflagType.CONVENIENCE_STORE;
            break;

        case Restaurant:
            naverCategory = NMapPOIflagType.RESTAURANT;
            break;

        case BANK:
            naverCategory = NMapPOIflagType.BANK;
            break;

        case HOSPITAL:
            naverCategory = NMapPOIflagType.HOSPITAL;
            break;

        case ACCOMMODATION:
            naverCategory = NMapPOIflagType.LODGEMENT;
            break;
        }

        topLayoutOnMixView.naverFragment.drawCategoryMarkers(markerList, naverCategory);
    }
}

/**
 * @author daniele
 */

// ? (? ?) ?
class CameraSurface extends SurfaceView implements SurfaceHolder.Callback {
    MixView app; // ? 
    SurfaceHolder holder; // ? ?
    Camera camera;

    // ??
    CameraSurface(Context context) {
        super(context);

        try {
            app = (MixView) context; // ?(? ) ?

            // ? ? ? ?
            holder = getHolder();
            holder.addCallback(this);
            holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); // ? 
        } catch (Exception ex) {

        }
    }

    // ? ?
    public void surfaceCreated(SurfaceHolder holder) {
        try {
            // ?   
            if (camera != null) {
                try {
                    camera.stopPreview();
                } catch (Exception ignore) {
                }
                try {
                    camera.release();
                } catch (Exception ignore) {
                }
                camera = null;
            }

            camera = Camera.open(); // ? 
            camera.setPreviewDisplay(holder); // ? ?? ???   
        } catch (Exception ex) {
            try { //  ? ?  ? 
                if (camera != null) {
                    try {
                        camera.stopPreview();
                    } catch (Exception ignore) {
                    }
                    try {
                        camera.release();
                    } catch (Exception ignore) {
                    }
                    camera = null;
                }
            } catch (Exception ignore) {

            }
        }
    }

    // ? 
    public void surfaceDestroyed(SurfaceHolder holder) {
        try { // ?  ? 
            if (camera != null) {
                try {
                    camera.stopPreview();
                } catch (Exception ignore) {
                }
                try {
                    camera.release();
                } catch (Exception ignore) {
                }
                camera = null;
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    // ? 
    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
        try {
            // ? ?? ? ? ?
            Camera.Parameters parameters = camera.getParameters();
            try {
                // ?? ?? ? 
                List<Camera.Size> supportedSizes = null;

                // ??  ? 1.6 ? ? 
                // ??  ? ?...

                // ? ??  ?? ?
                supportedSizes = Compatibility.getSupportedPreviewSizes(parameters);

                //  ? 
                float ff = (float) w / h;
                Log.d("Mixare", "Screen res: w:" + w + " h:" + h + " aspect ratio:" + ff);

                //holder for the best form factor and size
                // ?? ?  ?? ? 
                float bff = 0;
                int bestw = 0;
                int besth = 0;
                Iterator<Camera.Size> itr = supportedSizes.iterator();

                // ?(??) ? ?? ? 
                while (itr.hasNext()) {
                    Camera.Size element = itr.next();

                    //  ?  (current form factor)
                    float cff = (float) element.width / element.height;

                    // ? ? ?  ?
                    Log.d("Mixare", "Candidate camera element: w:" + element.width + " h:" + element.height
                            + " aspect ratio:" + cff);

                    //   ? ??     ?
                    //  ?  ?? ?  ?
                    // ? ? ? ? , ?? ?  
                    // * ? ?  ? ?  ? ?
                    if ((ff - cff <= ff - bff) && (element.width <= w) && (element.width >= bestw)) {
                        bff = cff;
                        bestw = element.width;
                        besth = element.height;
                    }
                }
                // ??   ? ?
                Log.d("Mixare", "Chosen camera element: w:" + bestw + " h:" + besth + " aspect ratio:" + bff);

                //   ? ?? ? ? 0 ? ?.
                // ?  ? ?  ? ? ? ? ??,
                // ? ? ? (480*320)? ?? 
                if ((bestw == 0) || (besth == 0)) {
                    Log.d("Mixare", "Using default camera parameters!");
                    bestw = 480;
                    besth = 320;
                }
                parameters.setPreviewSize(bestw, besth); //  ?  
            } catch (Exception ex) { //  ??? ? ...
                parameters.setPreviewSize(480, 320);
            }

            //  ? ? ? ?? ?
            camera.setParameters(parameters);
            camera.startPreview(); //  
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}

// ?? 
class AugmentedView extends View {
    MixView app; // ? 

    // ??
    public AugmentedView(Context context) {
        super(context);

        try {
            app = (MixView) context; // ?(? ) ?

            app.killOnError(); // ?  ?
        } catch (Exception ex) {
            app.doError(ex);
        }
    }

    //  
    @Override
    protected void onDraw(Canvas canvas) {
        try {

            app.killOnError(); // ?  ?

            // ? ??  (? ???  ?)
            MixView.dWindow.setWidth(canvas.getWidth());
            MixView.dWindow.setHeight(canvas.getHeight());
            MixView.dWindow.setCanvas(canvas); //  

            // ??   ? ?   
            if (!MixView.getDataView().isInited()) {
                MixView.getDataView().init(MixView.dWindow.getWidth(), MixView.dWindow.getHeight());
            }

            // ?? ? ??? ?? 
            MixView.getDataView().draw(MixView.dWindow);

        } catch (Exception ex) {
            app.doError(ex);
        }
    }
}

class TopLayoutOnMixView {
    static public String TAG = "TopLayoutOnMixView";
    public static final int WRITE_REVIEW = 1;
    public static final int SEARCH_LIST = 2;

    //? ?
    public FragmentMapview naverFragment;

    //
    private LinearLayout parentButtonView;
    private LinearLayout parentCategoryView;
    private LinearLayout buttonViewLayout;

    // 
    private LinearLayout searchbar;
    private Button searchBtn;
    private Button hideSearchbar;
    private EditText searchText;

    // ?? ?
    public View mainArView;

    //expansion, reduction level
    private int naver_map_width = 130;
    private int naver_map_height = 130;

    private LayoutInflater inflater;
    private Context context;

    public TopLayoutOnMixView(final Context context) {
        this.context = context;
        inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        mainArView = inflater.inflate(R.layout.activity_ar_mixview, null);

        initButtonViews();
        initNaverMap();
        initSearchbar();
    }

    public void initButtonViews() {
        parentButtonView = (LinearLayout) mainArView.findViewById(R.id.ar_mixview_parent_buttonview);
        parentCategoryView = (LinearLayout) mainArView.findViewById(R.id.ar_mixview_parent_categoryview);

        mainArView.findViewById(R.id.ar_mixview_search_erase).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                searchText.setText("");
            }
        });

        mainArView.findViewById(R.id.ar_mixview_category).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                parentButtonView.setVisibility(View.GONE);
                parentCategoryView.setVisibility(View.VISIBLE);
            }
        });
        mainArView.findViewById(R.id.ar_mixview_category_hide).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                parentCategoryView.setVisibility(View.GONE);
                parentButtonView.setVisibility(View.VISIBLE);
            }
        });

        mainArView.findViewById(R.id.ar_mixview_write_review).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                // TODO: 2017. 2. 12. wrieReviewActivity

                NGeoPoint nGeoPoint = naverFragment.getCurrentLocation();
                if (nGeoPoint == null)
                    Toast.makeText(context, "? ?  ? .",
                            Toast.LENGTH_SHORT).show();
                else {
                    Intent intent = new Intent(context, SearchCategoryListActivity.class);

                    intent.putExtra("lat", nGeoPoint.getLatitude());
                    intent.putExtra("lon", nGeoPoint.getLongitude());
                    mainArView.setVisibility(View.GONE);
                    ((Activity) context).startActivityForResult(intent, WRITE_REVIEW);
                }
            }
        });

        buttonViewLayout = (LinearLayout) mainArView.findViewById(R.id.ar_mixview_buttonview);
        final Button hideBtn = (Button) mainArView.findViewById(R.id.ar_mixview_buttonview_hide);
        hideBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (buttonViewLayout.getVisibility() == View.GONE) {
                    buttonViewLayout.setVisibility(View.VISIBLE);
                    hideBtn.setBackgroundResource(R.drawable.icon_menu_up);
                } else if (buttonViewLayout.getVisibility() == View.VISIBLE) {
                    buttonViewLayout.setVisibility(View.GONE);
                    hideBtn.setBackgroundResource(R.drawable.icon_menu_down);
                }
            }
        });
    }

    public void initSearchbar() {
        final ListView searchListView = (ListView) mainArView.findViewById(R.id.ar_mixview_search_list);

        searchbar = (LinearLayout) mainArView.findViewById(R.id.ar_mixview_searchbar);
        hideSearchbar = (Button) mainArView.findViewById(R.id.ar_mixview_hide_searchbar);
        searchBtn = (Button) mainArView.findViewById(R.id.ar_mixview_search);
        searchBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                parentButtonView.setVisibility(View.GONE);
                searchbar.setVisibility(View.VISIBLE);
            }
        });
        hideSearchbar.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                searchbar.setVisibility(View.GONE);
                parentButtonView.setVisibility(View.VISIBLE);
            }
        });

        searchText = (EditText) mainArView.findViewById(R.id.ar_mixview_search_text);
        searchText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
            @Override
            public boolean onEditorAction(TextView v, int actionId, android.view.KeyEvent event) {
                switch (actionId) {
                case EditorInfo.IME_ACTION_SEARCH:
                    String queryString = searchText.getText().toString();
                    Intent intent = new Intent(context, SearchKeywordListActivity.class);
                    intent.putExtra("searchName", queryString);
                    InputMethodManager imm = (InputMethodManager) context
                            .getSystemService(Context.INPUT_METHOD_SERVICE);
                    imm.hideSoftInputFromWindow(mainArView.getWindowToken(), 0);
                    mainArView.setVisibility(View.GONE);
                    ((Activity) context).startActivityForResult(intent, SEARCH_LIST);
                    break;
                default:
                    Toast.makeText(context, "", Toast.LENGTH_LONG).show();
                    return false;
                }
                return true;
            }
        });

        TextWatcher watcher = new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

            }

            @Override
            public void onTextChanged(final CharSequence charSequence, int i, int i1, int i2) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        String queryString = searchText.getText().toString();
                        try {
                            List<ARMarker> searchList = null;
                            String encodedQueryString = URLEncoder.encode(queryString, "UTF-8");

                            String tempCallbackUrl = "http://ac.map.naver.com/ac?q=" + encodedQueryString
                                    + "&st=10&r_lt=10&r_format=json";
                            String rawData = new NaverHttpHandler().execute(tempCallbackUrl).get();
                            Log.i("rawData", rawData);

                            JSONObject root = new JSONObject(rawData);
                            JSONArray dataArray = root.getJSONArray("items");
                            JSONArray locationData = dataArray.getJSONArray(0);

                            Log.i("dataArray", locationData.toString());

                            final ArrayList<String> list = new ArrayList<>();
                            for (int index = 0; index < locationData.length(); index++)
                                list.add(locationData.getString(index).substring(2,
                                        locationData.getString(index).length() - 2));

                            ((Activity) context).runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    SearchViewAdapter adapter = new SearchViewAdapter(inflater);
                                    adapter.setDataList(list);
                                    adapter.setCurrentText(charSequence.toString());
                                    searchListView.setAdapter(adapter);
                                    searchListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                                        @Override
                                        public void onItemClick(AdapterView<?> adapterView, View view, int i,
                                                long l) {
                                            String queryString = list.get(i);
                                            searchText.setText(queryString);
                                        }
                                    });
                                }
                            });
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        } catch (ExecutionException e) {
                            e.printStackTrace();
                        } catch (UnsupportedEncodingException e) {
                            e.printStackTrace();
                        } catch (JSONException e) {
                            e.printStackTrace();
                        }
                    }
                }).start();
            }

            @Override
            public void afterTextChanged(Editable editable) {

            }
        };
        searchText.addTextChangedListener(watcher);
    }

    public void initNaverMap() {
        naverFragment = new FragmentMapview();
        naverFragment.setArguments(new Bundle());

        final Button expandView = (Button) mainArView.findViewById(R.id.ar_mixview_naverview_expand);
        expandView.setOnClickListener(new View.OnClickListener() {
            boolean isFull = false;

            @Override
            public void onClick(View view) {
                RelativeLayout navermapWrapper = (RelativeLayout) mainArView
                        .findViewById(R.id.ar_mixview_naverview_wrapper);
                if (isFull) {
                    RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
                            (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, naver_map_width,
                                    Resources.getSystem().getDisplayMetrics()),
                            (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, naver_map_height,
                                    Resources.getSystem().getDisplayMetrics()));
                    int tenMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10,
                            Resources.getSystem().getDisplayMetrics());
                    params.setMargins(0, tenMargin, tenMargin, 0);
                    params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
                    params.addRule(RelativeLayout.ALIGN_PARENT_TOP);
                    navermapWrapper.setLayoutParams(params);
                    expandView.setBackgroundResource(R.drawable.ic_minimap_zoom_in);
                    isFull = false;
                } else {
                    RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT,
                            LayoutParams.MATCH_PARENT);
                    params.setMargins(0, 0, 0, 0);
                    navermapWrapper.setLayoutParams(params);
                    expandView.setBackgroundResource(R.drawable.ic_minimap_zoom_out);
                    isFull = true;
                }
            }
        });

        try {
            FragmentTransaction fragmentTransaction = ((FragmentActivity) context).getSupportFragmentManager()
                    .beginTransaction();
            fragmentTransaction.add(R.id.ar_mixview_naverview, naverFragment);
            fragmentTransaction.commit();
        } catch (Exception e) {
            e.printStackTrace();
            Log.i(TAG, "Only FragmentActivity can use naver maps");
        }
    }

    public void cancelSearchbar() {
        searchText.setText("");
        searchbar.setVisibility(View.GONE);
    }

    public boolean onBackPressed() {
        if (searchbar.getVisibility() != View.GONE) {
            cancelSearchbar();
            parentButtonView.setVisibility(View.VISIBLE);
            return true;
        } else if (parentCategoryView.getVisibility() != View.GONE) {
            parentCategoryView.setVisibility(View.GONE);
            parentButtonView.setVisibility(View.VISIBLE);
            return true;
        } else if (buttonViewLayout.getVisibility() != View.GONE) {
            buttonViewLayout.setVisibility(View.GONE);
            return true;
        }
        return false;
    }

    private class SearchViewAdapter extends BaseAdapter {
        private ArrayList<String> dataList = new ArrayList<>();
        private String currentText;
        private LayoutInflater inflater;

        public SearchViewAdapter(LayoutInflater inflater) {
            this.inflater = inflater;
        }

        @Override
        public int getCount() {
            return dataList.size();
        }

        @Override
        public Object getItem(int i) {
            return dataList.get(i);
        }

        @Override
        public long getItemId(int i) {
            return i;
        }

        @Override
        public View getView(int i, View view, ViewGroup viewGroup) {
            view = inflater.inflate(R.layout.layout_search_item, null);
            TextView searchItem = (TextView) view.findViewById(R.id.search_item);

            String data = dataList.get(i);
            int index = data.indexOf(currentText);

            if (index != -1) {
                SpannableStringBuilder builder = new SpannableStringBuilder();

                String before = data.substring(0, index);
                SpannableString beforeSpannable = new SpannableString(before);
                beforeSpannable.setSpan(new ForegroundColorSpan(Color.BLACK), 0, before.length(), 0);
                builder.append(beforeSpannable);

                String current = data.substring(index, index + currentText.length());
                SpannableString currentSpannable = new SpannableString(current);
                currentSpannable.setSpan(new ForegroundColorSpan(Color.parseColor("#88C290")), 0, current.length(),
                        0);
                builder.append(currentSpannable);

                String after = data.substring(index + currentText.length(), data.length());
                SpannableString afterSpannable = new SpannableString(after);
                afterSpannable.setSpan(new ForegroundColorSpan(Color.BLACK), 0, after.length(), 0);
                builder.append(afterSpannable);

                searchItem.setText(builder, TextView.BufferType.SPANNABLE);

                return view;
            }

            String currentTextNoSpace = currentText.replaceAll(" ", "");
            index = data.indexOf(currentTextNoSpace);

            if (index != -1) {
                SpannableStringBuilder builder = new SpannableStringBuilder();

                String before = data.substring(0, index);
                SpannableString beforeSpannable = new SpannableString(before);
                beforeSpannable.setSpan(new ForegroundColorSpan(Color.BLACK), 0, before.length(), 0);
                builder.append(beforeSpannable);

                String current = data.substring(index, index + currentTextNoSpace.length());
                SpannableString currentSpannable = new SpannableString(current);
                currentSpannable.setSpan(new ForegroundColorSpan(Color.parseColor("#88C290")), 0, current.length(),
                        0);
                builder.append(currentSpannable);

                String after = data.substring(index + currentTextNoSpace.length(), data.length());
                SpannableString afterSpannable = new SpannableString(after);
                afterSpannable.setSpan(new ForegroundColorSpan(Color.BLACK), 0, after.length(), 0);
                builder.append(afterSpannable);

                searchItem.setText(builder, TextView.BufferType.SPANNABLE);

                return view;
            }

            searchItem.setText(data);
            return view;
        }

        public void setDataList(ArrayList<String> dataList) {
            this.dataList = dataList;
        }

        public String getCurrentText() {
            return currentText;
        }

        public void setCurrentText(String currentText) {
            this.currentText = currentText;
        }
    }
}