package com.aincc.lib.common; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; import android.app.Activity; import android.content.Context; import android.content.DialogInterface.OnCancelListener; import android.content.res.Configuration; import android.graphics.Canvas; import android.graphics.drawable.Drawable; import android.location.Criteria; import android.location.GpsStatus; import android.location.Location; import android.location.LocationListener; import android.location.LocationManager; import android.os.Bundle; import android.os.StrictMode; import android.view.View; import com.aincc.lib.common.annotation.InjectView; import com.aincc.lib.network.common.BaseTrans; import com.aincc.lib.network.common.BaseTransEx; import com.aincc.lib.network.common.INetworkListener; import com.aincc.lib.network.common.NetworkHandler; import com.aincc.lib.ui.control.loading.LoadingDialog; import com.aincc.lib.util.Logger; import com.google.android.maps.GeoPoint; import com.google.android.maps.ItemizedOverlay; import com.google.android.maps.MapActivity; import com.google.android.maps.MapView; import com.google.android.maps.OverlayItem; /** * * <h3><b>MapBaseActivity</b></h3></br> * * 기본 액티비티 * * @author aincc@barusoft.com * @version 1.0.0 * @since 1.0.0 */ abstract public class MapBaseActivity extends MapActivity implements INetworkListener { // 스레드 정책 설정 static { StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build(); StrictMode.setThreadPolicy(policy); } protected static final int INVALID_IDENTIFIER = 0; protected static final int ATOMIC_LOADING_INIT = 0; protected LoadingDialog loadingDialog; protected AtomicInteger loadingAccCount; protected NetworkHandler listener; /** * UI Identifier 맵핑<br> * onCreate 에서 1회만 호출하도록 한다. * * @since 1.0.0 * @param object */ protected void mappingViews(Object object) { if (!(object instanceof Activity)) { return; } Activity activity = (Activity) object; Field[] fields = activity.getClass().getDeclaredFields(); for (Field field : fields) { InjectView injectView = field.getAnnotation(InjectView.class); if (null == injectView) { continue; } int identifier = injectView.id(); if (INVALID_IDENTIFIER == identifier) { String identifierString = field.getName(); identifier = activity.getResources().getIdentifier(identifierString, "id", activity.getPackageName()); } if (INVALID_IDENTIFIER == identifier) { continue; } View view = activity.findViewById(identifier); if (null == view) { continue; } if (field.getType() == view.getClass()) { try { field.setAccessible(true); field.set(object, view); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } // Logger.i(field.getName() + "," + identifier + "," + view); } } /** * 공통 UI 초기화를 구현한다. * * @since 1.0.0 */ protected void initializeUI() { // 네트워크 핸들러 생성 listener = new NetworkHandler(this); loadingAccCount = new AtomicInteger(ATOMIC_LOADING_INIT); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @Override protected void onStart() { super.onStart(); } @Override protected void onRestart() { super.onRestart(); } @Override protected void onResume() { super.onResume(); initLocation(); } @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); } @Override protected void onRestoreInstanceState(Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); } @Override protected void onPause() { super.onPause(); getLocationManager().removeUpdates(locationListener); getLocationManager().removeGpsStatusListener(gpsListener); } @Override protected void onStop() { super.onStop(); } @Override protected void onDestroy() { super.onDestroy(); } synchronized public void startProgress(final String message, final boolean cancelable, final OnCancelListener l, final int fontColor) { if (null != loadingDialog && loadingDialog.isShowing()) { loadingAccCount.incrementAndGet(); return; } runOnUiThread(new Runnable() { @Override public void run() { loadingDialog = LoadingDialog.show(MapBaseActivity.this, (null != message) ? message : "", false, cancelable, l, fontColor); loadingAccCount.incrementAndGet(); } }); } synchronized public void stopProgress() { if (null == loadingDialog) { loadingAccCount.set(ATOMIC_LOADING_INIT); return; } if (loadingDialog.isShowing() && ATOMIC_LOADING_INIT < loadingAccCount.get()) { loadingAccCount.decrementAndGet(); } if (ATOMIC_LOADING_INIT == loadingAccCount.get()) { runOnUiThread(new Runnable() { @Override public void run() { try { loadingDialog.dismiss(); } catch (Exception e) { e.printStackTrace(); } finally { loadingDialog = null; } } }); } } synchronized public boolean isLoading() { // 로딩 누적 계수를 사용하여 다이얼로그 표시여부를 판단한다. return (ATOMIC_LOADING_INIT == loadingAccCount.get() ? false : true); } @Override public void iNetEnabled() { stopProgress(); Logger.i("iNetEnabled() loadingAccCount = " + loadingAccCount.get()); } @Override public void iNetDisabled() { startProgress("", false, null, 0xFFFFFF); Logger.i("iNetDisabled() loadingAccCount = " + loadingAccCount.get()); } @Override public boolean iNetListenedTransaction(BaseTrans tr) { return true; } @Override public boolean iNetListenedError(BaseTransEx ex) { return true; } @Override public void iNetRejectedExecution(BaseTransEx ex) { } @Override public void iNetKeepAlive() { } @Override public void iNetKeepAlive(String param) { } @Override public void iNetConnected() { } @Override public void iNetConnected(String param) { } @Override public void iNetDisconnected() { } @Override public void iNetDisconnected(String param) { } // /////////////////////////////////////////////////////////////////////////////////////////// // TODO: 이하 Map 연동 기본 기능 // /////////////////////////////////////////////////////////////////////////////////////////// /** * 위치기반 프로바이더 명 */ protected static final String PROVIDER_NAME = LocationManager.GPS_PROVIDER; /** * 프로바이더 명 */ protected String bestProvider; /** * 위치 리스너 */ protected MyLocationListener locationListener; /** * GPS 리스너 */ protected GpsStatusListener gpsListener; /** * 위치 매니저 */ protected LocationManager locationManager; /** * 초기화 * * @since 1.0.0 */ protected void initLocation() { locationListener = new MyLocationListener(); gpsListener = new GpsStatusListener(); getLocationManager().requestLocationUpdates(PROVIDER_NAME, 400, 1, locationListener); getLocationManager().addGpsStatusListener(gpsListener); } /** * 위치매니저 가져오기 * * @since 1.0.0 * @return the LocationManager */ protected LocationManager getLocationManager() { if (null == locationManager) { locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); } return locationManager; } /** * Provider 체크 * * @since 1.0.0 * @return */ protected boolean checkProvider() { // 프로바이더 체크 ( Network or GPS ) Criteria criteria = new Criteria(); criteria.setAccuracy(Criteria.ACCURACY_FINE); criteria.setAltitudeRequired(false); criteria.setBearingRequired(false); criteria.setCostAllowed(true); criteria.setPowerRequirement(Criteria.POWER_LOW); bestProvider = getLocationManager().getBestProvider(criteria, false); if (null == bestProvider) { return false; } return getLocationManager().isProviderEnabled(bestProvider); } /** * 마지막 위치 정보 가져오기 * * @since 1.0.0 * @param provider * @return the Location */ protected Location getLastLocation(String provider) { if (null != provider) { return getLocationManager().getLastKnownLocation(provider); } return getLocationManager().getLastKnownLocation(PROVIDER_NAME); } /** * 위치정보 GeoPoint 변환 * * @since 1.0.0 * @param location * @return the GeoPoint */ protected GeoPoint getGeoPoint(Location location) { if (null == location) { return null; } Double lat = location.getLatitude() * 1E6; Double lng = location.getLongitude() * 1E6; return new GeoPoint(lat.intValue(), lng.intValue()); } /** * 위치정보를 상실한 경우 * * @since 1.0.0 */ protected abstract void onLocationLost(); /** * 위치정보가 변경된 경우 * * @since 1.0.0 * @param location */ protected abstract void onLocationChanged(final Location location); /** * 상태정보가 변경된 경우 * * @since 1.0.0 * @param provider * @param status * @param extras */ protected abstract void onStatusChanged(String provider, int status, Bundle extras); /** * GPS 상태가 변경된 경우 * * @since 1.0.0 * @param event */ protected abstract void onGpsStatusChanged(int event); /** * 오버레이 아이템이 선택된 경우 * * @since 1.0.0 * @param index * @param geopoint * @param overlays */ protected abstract void onTapOverlayItem(int index, GeoPoint geopoint, List<OverlayItem> overlays); /** * * <h3><b>MyLocationListener</b></h3></br> * * @author aincc@barusoft.com * @version 1.0.0 * @since 1.0.0 */ public class MyLocationListener implements LocationListener { @Override public void onLocationChanged(Location location) { if (null != location) { MapBaseActivity.this.onLocationChanged(location); } else { MapBaseActivity.this.onLocationLost(); } } @Override public void onProviderDisabled(String provider) { Logger.d("onProviderDisabled " + provider); } @Override public void onProviderEnabled(String provider) { Logger.d("onProviderEnabled " + provider); } @Override public void onStatusChanged(String provider, int status, Bundle extras) { MapBaseActivity.this.onStatusChanged(provider, status, extras); // switch (status) // { // case LocationProvider.TEMPORARILY_UNAVAILABLE: // case LocationProvider.OUT_OF_SERVICE: // case LocationProvider.AVAILABLE: // break; // } } } /** * * <h3><b>GpsStatusListener</b></h3></br> * * @author aincc@barusoft.com * @version 1.0.0 * @since 1.0.0 */ public class GpsStatusListener implements GpsStatus.Listener { @Override public void onGpsStatusChanged(int event) { MapBaseActivity.this.onGpsStatusChanged(event); } } /** * * <h3><b>LocationItemizedOverlay</b></h3></br> * * @author aincc@barusoft.com * @version 1.0.0 * @since 1.0.0 */ public class LocationItemizedOverlay extends ItemizedOverlay<OverlayItem> { /** * 오버레이 리스트 아이템 */ private List<OverlayItem> overlays; /** * 마커 이미지 */ private Drawable marker = null; /** * * @since 1.0.0 * @param defaultMarker */ public LocationItemizedOverlay(Drawable defaultMarker) { super(boundCenterBottom(defaultMarker)); this.marker = defaultMarker; overlays = new ArrayList<OverlayItem>(); } @Override protected OverlayItem createItem(int i) { return overlays.get(i); } @Override public int size() { return overlays.size(); } @Override public void draw(Canvas canvas, MapView mapView, boolean shadow) { /** 팝업 이미지 및 문구 표시하기 */ boundCenterBottom(marker); super.draw(canvas, mapView, shadow); } public void addOverlay(OverlayItem overlay) { overlays.add(overlay); populate(); } public void clearOverlay() { overlays.clear(); populate(); } public void populateImmediate() { populate(); } @Override protected boolean onTap(int index) { GeoPoint geoPoint = getItem(index).getPoint(); MapBaseActivity.this.onTapOverlayItem(index, geoPoint, overlays); return true; } } }