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;
}
}
}