songjunekeun 5 年之前
父節點
當前提交
cf8e79d627

+ 0 - 13
app/src/bonwon_dev/res/drawable-xxxhdpi/ripple.xml

@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<ripple xmlns:android="http://schemas.android.com/apk/res/android"
-    android:color="#00ccb4"> <!-- Ripple Effect 색상 -->
-
-    <!-- 배경색 -->
-    <item android:id="@android:id/background">
-        <shape android:shape="rectangle">
-            <corners android:radius="5dp"/>
-            <solid android:color="@color/loginBtnColor"/>
-        </shape>
-    </item>
-
-</ripple>

+ 0 - 17
app/src/bonwon_dev/res/drawable-xxxhdpi/shape.xml

@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item>
-        <shape android:shape="rectangle">
-            <solid android:color="#CCffffff"/>
-            <stroke android:width="1dp" android:color="#CCCCCC"/>
-            <corners android:radius="5dp"/>
-            <!-- You can create different radius for different corners -->
-            <!--corners
-                android:topLeftRadius="5dp"
-                android:topRightRadius="5dp"
-                android:bottomLeftRadius="5dp"
-                android:bottomRightRadius="5dp"
-                /-->
-        </shape>
-    </item>
-</selector>

+ 0 - 13
app/src/chilgok/res/drawable-xxxhdpi/ripple.xml

@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<ripple xmlns:android="http://schemas.android.com/apk/res/android"
-    android:color="#00ccb4"> <!-- Ripple Effect 색상 -->
-
-    <!-- 배경색 -->
-    <item android:id="@android:id/background">
-        <shape android:shape="rectangle">
-            <corners android:radius="5dp"/>
-            <solid android:color="@color/loginBtnColor"/>
-        </shape>
-    </item>
-
-</ripple>

+ 0 - 17
app/src/chilgok/res/drawable-xxxhdpi/shape.xml

@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item>
-        <shape android:shape="rectangle">
-            <solid android:color="#CCffffff"/>
-            <stroke android:width="1dp" android:color="#CCCCCC"/>
-            <corners android:radius="5dp"/>
-            <!-- You can create different radius for different corners -->
-            <!--corners
-                android:topLeftRadius="5dp"
-                android:topRightRadius="5dp"
-                android:bottomLeftRadius="5dp"
-                android:bottomRightRadius="5dp"
-                /-->
-        </shape>
-    </item>
-</selector>

+ 0 - 13
app/src/chilgok_dev/res/drawable-xxxhdpi/ripple.xml

@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<ripple xmlns:android="http://schemas.android.com/apk/res/android"
-    android:color="#00ccb4"> <!-- Ripple Effect 색상 -->
-
-    <!-- 배경색 -->
-    <item android:id="@android:id/background">
-        <shape android:shape="rectangle">
-            <corners android:radius="5dp"/>
-            <solid android:color="@color/loginBtnColor"/>
-        </shape>
-    </item>
-
-</ripple>

+ 0 - 17
app/src/chilgok_dev/res/drawable-xxxhdpi/shape.xml

@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item>
-        <shape android:shape="rectangle">
-            <solid android:color="#CCffffff"/>
-            <stroke android:width="1dp" android:color="#CCCCCC"/>
-            <corners android:radius="5dp"/>
-            <!-- You can create different radius for different corners -->
-            <!--corners
-                android:topLeftRadius="5dp"
-                android:topRightRadius="5dp"
-                android:bottomLeftRadius="5dp"
-                android:bottomRightRadius="5dp"
-                /-->
-        </shape>
-    </item>
-</selector>

+ 0 - 13
app/src/local/res/drawable-xxxhdpi/ripple.xml

@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<ripple xmlns:android="http://schemas.android.com/apk/res/android"
-    android:color="#00ccb4"> <!-- Ripple Effect 색상 -->
-
-    <!-- 배경색 -->
-    <item android:id="@android:id/background">
-        <shape android:shape="rectangle">
-            <corners android:radius="5dp"/>
-            <solid android:color="@color/loginBtnColor"/>
-        </shape>
-    </item>
-
-</ripple>

+ 0 - 17
app/src/local/res/drawable-xxxhdpi/shape.xml

@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item>
-        <shape android:shape="rectangle">
-            <solid android:color="#CCffffff"/>
-            <stroke android:width="1dp" android:color="#CCCCCC"/>
-            <corners android:radius="5dp"/>
-            <!-- You can create different radius for different corners -->
-            <!--corners
-                android:topLeftRadius="5dp"
-                android:topRightRadius="5dp"
-                android:bottomLeftRadius="5dp"
-                android:bottomRightRadius="5dp"
-                /-->
-        </shape>
-    </item>
-</selector>

+ 4 - 0
app/src/main/java/com/dbs/mplus/knuh/consent/ConsentFacade.java

@@ -0,0 +1,4 @@
+package com.dbs.mplus.knuh.consent;
+
+public class ConsentFacade {
+}

+ 22 - 0
app/src/main/java/com/dbs/mplus/knuh/consent/sign/CertificateInfo.java

@@ -0,0 +1,22 @@
+package com.dbs.mplus.knuh.consent.sign;
+
+import com.lumensoft.ks.KSCertificate;
+
+public class CertificateInfo {
+  private KSCertificate certificate;
+  private String password;
+  
+  public CertificateInfo(KSCertificate certificate, String password) {
+    this.certificate = certificate;
+    this.password = password;
+  }
+  
+  public KSCertificate getCertificate() {
+    return certificate;
+  }
+  
+  public String getPassword() {
+    return password;
+  }
+  
+}

+ 145 - 0
app/src/main/java/com/dbs/mplus/knuh/consent/sign/SignWrapper.java

@@ -0,0 +1,145 @@
+package com.dbs.mplus.knuh.consent.sign;
+
+import android.content.Context;
+import android.util.Base64;
+import android.util.Log;
+
+import com.androidKmi.KmiApi;
+import com.dbs.mplus.knuh.util.ConsentConfig;
+import com.lumensoft.ks.KSCertificate;
+import com.lumensoft.ks.KSCertificateLoader;
+import com.lumensoft.ks.KSCertificateManager;
+import com.lumensoft.ks.KSException;
+import com.lumensoft.ks.KSSign;
+
+import java.io.UnsupportedEncodingException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Vector;
+
+public class SignWrapper {
+  
+  private static final String TAG = "SignWrapper";
+  private static SignWrapper instance;
+  private KmiApi kmiApi;
+  
+  private Map<String, CertificateInfo> certificateMap;
+  
+  public SignWrapper() {
+    kmiApi = new KmiApi();
+    certificateMap = new HashMap<String, CertificateInfo>();
+  }
+  
+  public static SignWrapper getInstance() {
+    if(instance == null) {
+      instance = new SignWrapper();
+    }
+    return instance;
+  }
+  
+  public void deleteAll() {
+    for (String key : certificateMap.keySet()) {
+      if (certificateMap.get(key) != null) {
+        boolean result = this.kmiApi.LocalDelKeyAndCert(certificateMap.get(key).getCertificate().getSubjectDn());
+      }
+    }
+    
+    this.certificateMap.clear();
+  }
+  
+  /**
+  * 인증여부 확인
+  * @author jksong
+  * @Param
+  * @since 2019-08-09 오후 2:05
+  **/
+  public boolean isCertificate(String userId) {
+    return this.certificateMap.containsKey(userId);
+  }
+  
+  /**
+   * 서명
+   * @param userId
+   * @param signData
+   * @return
+   */
+  public String signData(String userId, String signData) {
+    String certResult = null;
+    CertificateInfo certificate = this.certificateMap.get(userId);
+    if(certificate != null) {
+      try {
+        byte[] result = null;
+        // 서명데이터 구분자 ^ 빼고
+        String hashValue = signData.replaceAll("\\^", "");
+        result = KSSign.koscomSign(certificate.getCertificate(), hashValue, certificate.getPassword());
+        certResult = new String(Base64.encode(result, Base64.DEFAULT));
+      } catch (KSException e) {
+        e.printStackTrace();
+      }
+    }
+    return certResult;
+  }
+  
+  /**
+  * 인증서 인증
+  * @author jksong
+  * @Param Context
+  * @Param userId : 사용자 아이디
+  * @Param password : 인증서 비밀번호
+  * @since 2019-08-09 오후 2:06
+  **/
+  public boolean certificate(Context context, String userId, String password) {
+    String certDN = downloadCertificate(userId);
+    Log.e(TAG, "certDN -- > " + certDN);
+    if (certDN == null) {
+      return false;
+    }
+  
+    Vector<KSCertificate> certificateVector = null;
+    int index = 0;
+    boolean certFlag = false;
+    
+    try {
+      certificateVector = KSCertificateLoader.getUserCertificateList(context);
+      index = KSCertificateLoader.getUserCertificate(certDN, context);
+      if (index < 0) {
+        return false;
+      }
+      
+      KSCertificate certificate = certificateVector.get(index);
+      certFlag = KSCertificateManager.checkPwd(certificate, password);
+      
+      if (certFlag == false) {
+        return false;
+      }
+      
+      CertificateInfo certificateInfo = new CertificateInfo(certificate, password);
+      certificateMap.put(userId, certificateInfo);
+    } catch (KSException e) {
+      e.printStackTrace();
+    } catch (UnsupportedEncodingException e) {
+      e.printStackTrace();
+    }
+    
+    return true;
+  }
+  
+  /**
+  * 인증서 DN 정보 가져오기
+  * @author jksong
+  * @Param 
+  * @since 2019-08-09 오후 2:07
+  **/
+  private String downloadCertificate(String userId) {
+    String certDN = null;
+    
+    if (kmiApi.kmsConnect(ConsentConfig.CERTIFICATE_IP, ConsentConfig.CERTIFICATE_PORT) == true) {
+      certDN = kmiApi.GetKeyAndCert(userId);
+    }
+  
+    kmiApi.kmsDisconnect();
+    return certDN;
+  }
+  
+
+}

+ 9 - 0
app/src/main/java/com/dbs/mplus/knuh/httpTask/CallBack.java

@@ -0,0 +1,9 @@
+package com.dbs.mplus.knuh.httpTask;
+
+import org.ksoap2.serialization.SoapObject;
+
+public interface CallBack {
+  void result(SoapObject result);
+  void stop();
+  void error();
+}

+ 39 - 0
app/src/main/java/com/dbs/mplus/knuh/httpTask/HttpRunnable.java

@@ -0,0 +1,39 @@
+package com.dbs.mplus.knuh.httpTask;
+
+import org.ksoap2.serialization.SoapObject;
+
+import java.util.HashMap;
+import java.util.concurrent.ExecutionException;
+
+
+public class HttpRunnable implements Runnable {
+  
+  private static final String TAG = "HttpRunnable";
+  private String soapAction = "";
+  private String callMethod = "";
+  private HashMap<String, String> mData;
+  
+  private CallBack callBack;
+  
+  public HttpRunnable (String soapAction, String callMethod, HashMap<String, String> mData, CallBack callBack) {
+    this.soapAction = soapAction;
+    this.callMethod = callMethod;
+    this.mData      = mData;
+    this.callBack   = callBack;
+  }
+  
+  @Override
+  public void run() {
+    
+    try {
+      HttpSoapConnection httpSoapConnection = new HttpSoapConnection(soapAction, callMethod, mData);
+      
+      SoapObject result = httpSoapConnection.execute().get();
+      
+      callBack.result(result);
+    } catch (ExecutionException e) {
+    } catch (InterruptedException e) {
+    }
+    
+  }
+}

+ 87 - 0
app/src/main/java/com/dbs/mplus/knuh/httpTask/HttpSoapConnection.java

@@ -0,0 +1,87 @@
+package com.dbs.mplus.knuh.httpTask;
+
+import android.os.AsyncTask;
+
+import com.dbs.mplus.knuh.BuildConfig;
+import com.dbs.mplus.knuh.util.ConsentConfig;
+
+import org.ksoap2.SoapEnvelope;
+import org.ksoap2.serialization.SoapObject;
+import org.ksoap2.serialization.SoapSerializationEnvelope;
+import org.ksoap2.transport.HttpTransportSE;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.util.HashMap;
+
+public class HttpSoapConnection extends AsyncTask<Void, Void, SoapObject> {
+  
+  private static final String TAG = "HttpSoapConnection";
+  private HashMap<String, String> mData;
+  private String soapAction  = "";
+  private String callMmethod = "";
+  
+  public HttpSoapConnection(String soapAction, String callMmethod, HashMap<String, String> mData) {
+    this.soapAction  = soapAction;
+    this.callMmethod = callMmethod;
+    this.mData       = mData;
+  }
+  
+  @Override
+  protected void onPreExecute() {
+  }
+  
+  @Override
+  protected SoapObject doInBackground(Void... voids) {
+    
+    SoapObject soapObject  = soapRequestParam(callMmethod, mData);
+    SoapObject soapResponse = null;
+
+    try {
+      
+      SoapSerializationEnvelope soapEnvelope = new SoapSerializationEnvelope(SoapEnvelope.VER12);
+      soapEnvelope.bodyOut = soapObject;
+      soapEnvelope.setOutputSoapObject(soapObject);
+      soapEnvelope.dotNet = true;
+      soapEnvelope.implicitTypes = false;
+      
+      HttpTransportSE hts = new HttpTransportSE(soapAction, ConsentConfig.CONNECT_TIMEOUT);
+      hts.call(soapAction + callMmethod, soapEnvelope);
+      
+      if (soapEnvelope.getResponse() instanceof SoapObject) {
+        soapResponse = (SoapObject) soapEnvelope.getResponse();
+      } else {
+        soapResponse = new SoapObject();
+        soapResponse.addProperty(callMmethod, soapEnvelope.getResponse());
+      }
+      
+      if (soapResponse != null) {
+        return soapResponse;
+      } else {
+//        errorObject.addProperty("ERROR", "ERROR");
+      }
+      
+    } catch (IOException e) {
+      e.printStackTrace();
+    } catch (XmlPullParserException e) {
+      e.printStackTrace();
+    }
+    
+    return null;
+  }
+  
+  @Override
+  protected void onPostExecute(SoapObject o) {
+//    super.onPostExecute(o);
+  }
+  
+  private SoapObject soapRequestParam(String callMmethod, HashMap<String, String> hashMap) {
+    SoapObject soapObject = new SoapObject(BuildConfig.NAME_SPACE, callMmethod);
+    
+    for (String key : hashMap.keySet()) {
+      soapObject.addProperty(key, hashMap.get(key));
+    }
+    
+    return soapObject;
+  }
+}

+ 8 - 0
app/src/main/java/com/dbs/mplus/knuh/util/ConsentConfig.java

@@ -0,0 +1,8 @@
+package com.dbs.mplus.knuh.util;
+
+public class ConsentConfig {
+
+  public final static int CONNECT_TIMEOUT = 5000;
+  public final static String CERTIFICATE_IP = "192.168.100.191";
+  public final static int CERTIFICATE_PORT  = 7001;
+}

+ 657 - 0
app/src/main/java/com/dbs/mplus/knuh/util/Util.java

@@ -0,0 +1,657 @@
+package com.dbs.mplus.knuh.util;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.SharedPreferences;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.graphics.PorterDuff;
+import android.graphics.drawable.Drawable;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.net.wifi.WifiInfo;
+import android.net.wifi.WifiManager;
+import android.util.Log;
+import android.view.ContextThemeWrapper;
+import android.view.WindowManager;
+import android.widget.EditText;
+import android.widget.TextView;
+
+import androidx.core.content.ContextCompat;
+
+import com.dbs.mplus.knuh.R;
+
+import org.kobjects.base64.Base64;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.lang.reflect.Field;
+import java.net.NetworkInterface;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Collections;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.List;
+import java.util.Locale;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.GZIPOutputStream;
+
+public class Util {
+  private static final String TAG = "Util";
+
+  /**
+   * 현재날짜을 가져온다
+   * @author jksong
+   * @Param
+   * @since 2019-06-17 오후 3:49
+   **/
+  public static int[] toDayDate() {
+    Calendar calendar = new GregorianCalendar(Locale.KOREA);
+    int nYear = calendar.get(Calendar.YEAR);
+    int nMonth = calendar.get(Calendar.MONTH) + 1;
+    int nDay = calendar.get(Calendar.DAY_OF_MONTH);
+
+    int toDayDate[] = {nYear, nMonth, nDay};
+//    String toDayDate[] = {String.valueOf(nYear), String.valueOf(nMonth), String.valueOf(nDay)};
+    return toDayDate;
+  }
+
+  /**
+   * wifi 연결 여부 체크
+   * @author jksong
+   * @Param
+   * @since 2019-12-05 오전 9:30
+   **/
+  public static boolean checkWifi(Context context) {
+    boolean rtn = false;
+
+    ConnectivityManager cm = (ConnectivityManager) context.getSystemService(context.CONNECTIVITY_SERVICE);
+    NetworkInfo ni         = cm.getActiveNetworkInfo();
+
+    if(ni != null) {
+      if(ni.getType() == ConnectivityManager.TYPE_WIFI) {
+        rtn = ni.isConnected();
+      }
+    }
+
+    return rtn;
+  }
+
+  /**
+   * 데이터 연결 여부 체크
+   * @author jksong
+   * @Param
+   * @since 2019-12-05 오전 9:31
+   **/
+  public static boolean checkLTE(Context context) {
+    boolean rtn = false;
+
+    ConnectivityManager cm = (ConnectivityManager) context.getSystemService(context.CONNECTIVITY_SERVICE);
+    NetworkInfo ni         = cm.getActiveNetworkInfo();
+
+    if(ni != null) {
+      if(ni.getType() == ConnectivityManager.TYPE_MOBILE) {
+        rtn = ni.isConnected();
+      }
+    }
+
+    return rtn;
+  }
+
+  /**
+   * checkWifi, checkLTE 중 하나라도 연결되어 있으면 네트웍이 가능하다고 판단
+   * @author jksong
+   * @Param
+   * @since 2019-12-05 오전 9:31
+   **/
+  public static boolean checkNetwork(Context context) {
+    boolean rtn = false;
+
+    if(checkLTE(context) || checkWifi(context)) {
+      rtn = true;
+    } else {
+      rtn = false;
+    }
+
+    return rtn;
+  }
+
+  /**
+   * WIFI ssid 비교
+   * @author jksong
+   * @Param Context, wifi ssid
+   * @since 2019-06-14 오전 10:50
+   **/
+  public static boolean checkWifi(Context context, String ssid) {
+    WifiManager manager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
+    WifiInfo wifiInfo = manager.getConnectionInfo();
+    String wifiSSID = wifiInfo.getSSID().toUpperCase();
+    wifiSSID = wifiSSID.substring(1, wifiSSID.length() - 1);
+
+    if (wifiSSID == null) {
+      return false;
+    }
+    return wifiSSID.equals(ssid);
+  }
+
+  /**
+   * 허용된 WIFI환경인지 체크
+   * @author jksong
+   * @Param Context
+   * @since 2019-06-14 오전 11:02
+   **/
+//  public static boolean authWifiCheck(Context mContext) {
+//    boolean bWifi = false;
+//
+//    for (String name : ConfigConstants.SSID) {
+//      String sName = name.toUpperCase();
+//      bWifi = checkWifi(mContext, sName);
+//
+//      if (bWifi == true) {
+//        break;
+//      }
+//    }
+//
+//    return bWifi;
+//  }
+
+  /**
+   * SSID를 "," 구분해서 문자열로 변환
+   * @author jksong
+   * @since 2019-06-14 오전 11:29
+   **/
+//  public static String getSsidName() {
+//    String wifiNames = String.join(", ", ConfigConstants.SSID);
+//    return wifiNames;
+//  }
+
+  /**
+   * DeviceMacAddress 가져오기
+   * @author jksong
+   * @Param
+   * @since 2019-08-22 오후 8:37
+   **/
+  public static String getMACAddress() {
+    try {
+      List<NetworkInterface> interfaces = Collections.list(NetworkInterface.getNetworkInterfaces());
+      for (NetworkInterface intf : interfaces) {
+        if (!intf.getName().equalsIgnoreCase("wlan0")) continue;
+        byte[] mac = intf.getHardwareAddress();
+        if (mac==null) return "";
+        StringBuilder buf = new StringBuilder();
+        for (int idx=0; idx<mac.length; idx++)
+          buf.append(String.format("%02X:", mac[idx]));
+        if (buf.length()>0) buf.deleteCharAt(buf.length()-1);
+        return buf.toString();
+      }
+    } catch (Exception ex) { } // for now eat exceptions
+    return "";
+  }
+//  String macAddress = getMACAddress("wlan0");
+
+
+  /**
+   * 문자열에 / (슬러쉬)를 제거한다
+   * @author jksong
+   * @Param
+   * @since 2019-08-12 오전 9:00
+   **/
+  public static String removeSlashStr(String str) {
+    str = str.replace("/", "");
+    return str;
+  }
+
+  /**
+   * 날짜 포맷에 / (슬러쉬)를 추가한다
+   * @author jksong
+   * @Param
+   * @since 2019-12-05 오전 9:33
+   **/
+  public static String addSlashDate(String dateStr) {
+    String resDate = "";
+    try {
+      SimpleDateFormat df = new SimpleDateFormat("yyyymmdd");
+      Date date = df.parse(dateStr);
+      SimpleDateFormat df1 = new SimpleDateFormat("yyyy/mm/dd");
+      resDate = df1.format(date);
+    } catch (ParseException e) {
+      e.printStackTrace();
+    }
+
+    return resDate;
+  }
+
+  /**
+   * 주민등록번호 앞자리를 생년월일로 변환함
+   * @author jksong
+   * @Param
+   * @since 2019-08-30 오후 2:12
+   **/
+  public static String changeJuminToBirthday(String dateStr) {
+
+    String resDate = "";
+    try {
+      SimpleDateFormat df = new SimpleDateFormat("yymmdd");
+      Date date = date = df.parse(dateStr);
+      SimpleDateFormat df1 = new SimpleDateFormat("yyyy년 mm월 dd일");
+      resDate = df1.format(date);
+    } catch (ParseException e) {
+      e.printStackTrace();
+    }
+
+    return resDate;
+  }
+
+  public static String changeJuminToBirthday2(String dateStr) {
+
+    String resDate = "";
+    try {
+      SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd");
+      Date date = date = df.parse(dateStr);
+      SimpleDateFormat df1 = new SimpleDateFormat("yyyy-MM-dd");
+      resDate = df1.format(date);
+    } catch (ParseException e) {
+      e.printStackTrace();
+    }
+
+    return resDate;
+  }
+
+  /**
+   * 한자리 숫자 일때 앞에 0을 붙여준다
+   * @author jksong
+   * @Param integer
+   * @since 2019-06-17 오후 3:50
+   **/
+  public static String plusZero(int num) {
+    int temp = num;
+    int length = (int) (Math.log10(temp) + 1);
+    String d = "";
+
+    if (length == 1) {
+      d = String.format("%02d", temp);
+    } else {
+      d = String.valueOf(temp);
+    }
+
+    return d;
+  }
+
+  /**
+   * 앱 이름을 가져온다
+   * @author jksong
+   * @Param Context
+   * @since 2019-08-08 오후 7:47
+   **/
+  public static String getAppName(Context mContext) {
+    ApplicationInfo applicationInfo = mContext.getApplicationInfo();
+    int stringId = applicationInfo.labelRes;
+    return stringId == 0 ? applicationInfo.nonLocalizedLabel.toString() : mContext.getString(stringId);
+  }
+
+  /**
+   * 앱 버전 가져오기
+   * @author jksong
+   * @Param
+   * @since 2019-10-25 오후 5:07
+   **/
+  public static String getVersion(Context context) {
+    String version = null;
+
+    try {
+      PackageInfo i = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
+      version = i.versionName;
+    } catch (PackageManager.NameNotFoundException e) {
+
+    }
+
+    return version;
+  }
+
+  /**
+   * SharedPreferences String type data 저장
+   * @author jksong
+   * @Param Context, 저장될 타입, key, value
+   * @since 2019-08-08 오후 7:47
+   **/
+  public static void setStringPreference(Context context, String type, String key, String value) {
+    SharedPreferences prefs = context.getSharedPreferences(type, context.MODE_PRIVATE);
+    SharedPreferences.Editor editor = prefs.edit();
+    editor.putString(key, value);
+    editor.commit();
+  }
+
+  /**
+   * SharedPreferences String type data 가져오기
+   * @author jksong
+   * @Param Context, 저장했던 타입, key
+   * @since 2019-08-08 오후 7:47
+   **/
+  public static String getStringPreference(Context context, String type, String key) {
+//    SharedPreferences prefs = context.getSharedPreferences(type, context.MODE_MULTI_PROCESS);
+    SharedPreferences prefs = context.getSharedPreferences(type, context.MODE_PRIVATE);
+    String rtn = prefs.getString(key, "");
+
+    return rtn;
+  }
+
+  /**
+   * SharedPreferences 저장한 타입을 모두 제거
+   * @author jksong
+   * @Param Context, 저장한 type
+   * @since 2019-08-08 오후 7:47
+   **/
+  public static void clearPreference(Context context, String type) {
+//    SharedPreferences prefs = context.getSharedPreferences(type, context.MODE_MULTI_PROCESS);
+    SharedPreferences prefs = context.getSharedPreferences(type, context.MODE_PRIVATE);
+    SharedPreferences.Editor editor = prefs.edit();
+    editor.clear();
+    editor.commit();
+  }
+
+  /**
+   * sha256 passwd encrypt
+   * @author jksong
+   * @Param
+   * @since 2019-08-08 오후 7:47
+   **/
+  public static String sha256Encrypt(String str) {
+    String SHA = "";
+
+    try {
+      MessageDigest sh = MessageDigest.getInstance("SHA-256");
+      sh.update(str.getBytes());
+      byte byteData[] = sh.digest();
+      StringBuffer sb = new StringBuffer();
+
+      for (int i = 0; i < byteData.length; i++) {
+        sb.append(Integer.toString((byteData[i] & 0xff) + 0x100, 16).substring(1));
+      }
+
+      SHA = sb.toString();
+
+    } catch (NoSuchAlgorithmException e) {
+      e.printStackTrace();
+      SHA = null;
+    }
+
+    return SHA;
+  }
+
+  /**
+   * SHA-256 hash
+   *
+   * @param salt
+   * @param data
+   * @return
+   * @throws Exception
+   */
+  public static String sha256(String salt, byte[] data) throws Exception {
+    if (data == null) {
+      throw new Exception("Hash를 적용할 데이터가 없음");
+    }
+
+    try {
+      final MessageDigest digest = MessageDigest.getInstance("SHA-256");
+      // 초기화
+      digest.reset();
+      if (salt != null) {
+        salt = salt.trim();
+        if (!"".equals(salt)) {
+          digest.update(salt.getBytes());
+        }
+      }
+
+      // 데이터의 hash값 구하기
+      final byte[] hash = digest.digest(data);
+      final StringBuilder hexString = new StringBuilder();
+
+      for (final byte element : hash) {
+        final String hex = Integer.toHexString(0xff & element);
+        if (hex.length() == 1) {
+          hexString.append('0');
+        }
+        hexString.append(hex);
+      }
+
+      return hexString.toString();
+    } catch (final Exception ex) {
+      throw new Exception("SHA-256적용 실패", ex);
+    }
+
+  }
+
+  /**
+   * MD5 encrypt
+   * @author jksong
+   * @Param
+   * @since 2019-11-19 오후 7:09
+   **/
+  public static String md5(String input) throws NoSuchAlgorithmException, UnsupportedEncodingException {
+    MessageDigest md5 = MessageDigest.getInstance("MD5");
+    byte[] digest = md5.digest(input.getBytes("UTF-8"));
+    StringBuilder sb = new StringBuilder();
+    for (int i = 0; i < digest.length; ++i) {
+      sb.append(Integer.toHexString((digest[i] & 0xFF) | 0x100).substring(1, 3));
+    }
+    return sb.toString();
+  }
+
+  /**
+   * 시간 더하기 빼기
+   * @author jksong
+   * @Param
+   * @since 2019-08-30 오후 2:35
+   **/
+  public static String addDate(String fromDate, String format, int addYear, int addMonth, int addDate, int addHour, int addMinute) {
+
+    SimpleDateFormat sdf = new SimpleDateFormat(format);
+    Date date = null;
+    try {
+      date = sdf.parse(fromDate);
+
+      Calendar cal = new GregorianCalendar();
+
+      cal.setTime(date);
+      cal.add(Calendar.YEAR, +addYear);
+      cal.add(Calendar.MONTH, +addMonth);
+      cal.add(Calendar.DATE, +addDate);
+      cal.add(Calendar.HOUR, +addHour);
+      cal.add(Calendar.MINUTE, +addMinute);
+//    cal.add(Calendar.SECOND, +addSecond);
+
+      SimpleDateFormat sdf2 = new SimpleDateFormat(format);
+      String toDate = sdf2.format(cal.getTime());
+
+      return toDate;
+    } catch (ParseException e) {
+      e.printStackTrace();
+    }
+
+    return "";
+  }
+
+  private static AlertDialog createDialog(Context context, String title, String msg, String button1, DialogInterface.OnClickListener button1Listener, String button2, DialogInterface.OnClickListener button2Listener) {
+    final AlertDialog.Builder builder = new AlertDialog.Builder(new ContextThemeWrapper(context, android.R.style.Theme_Holo_Light_Dialog));
+
+    builder.setTitle(title);
+    builder.setMessage(msg);
+    builder.setPositiveButton(button1, button1Listener);
+    if (button2Listener != null) {
+      builder.setNegativeButton(button2, button2Listener);
+    }
+    builder.setCancelable(false);
+
+    return builder.create();
+  }
+
+  public static AlertDialog getOKDialog(Context context, String title, String msg, DialogInterface.OnClickListener okListener) {
+    String okId = context.getString(R.string.confirm);
+    AlertDialog dlg = createDialog(context, title, msg, okId, okListener, "", null);
+    dlg.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
+
+    return dlg;
+  }
+
+  public static AlertDialog getPasswordInputDialog(Context context, String title, String msg, DialogInterface.OnClickListener okListener, DialogInterface.OnClickListener cancelListener) {
+//    int okId = MPlusResourceUtil.getStringIdByName(context, "mf_ok_button_str");
+//    int cancelId = MPlusResourceUtil.getStringIdByName(context, "mf_cancel_button_str");
+
+    String okId = context.getString(R.string.confirm);
+    String cancelId = context.getString(R.string.cancel);
+
+    AlertDialog dlg = createDialog(context, title, msg, okId, okListener, cancelId, cancelListener);
+    dlg.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
+    return dlg;
+  }
+
+  public static void setCursorColor(EditText view, int color) {
+    try {
+      // Get the cursor resource id
+      Field field = TextView.class.getDeclaredField("mCursorDrawableRes");
+      field.setAccessible(true);
+      int drawableResId = field.getInt(view);
+
+      // Get the editor
+      field = TextView.class.getDeclaredField("mEditor");
+      field.setAccessible(true);
+      Object editor = field.get(view);
+
+      // Get the drawable and set a color filter
+      Drawable drawable = ContextCompat.getDrawable(view.getContext(), drawableResId);
+      drawable.setColorFilter(color, PorterDuff.Mode.SRC_IN);
+      Drawable[] drawables = {drawable, drawable};
+
+      // EditTextView underLine color
+      Drawable drawable1 = view.getBackground();
+      drawable1.setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
+      view.setBackground(drawable1);
+
+      // Set the drawables
+      field = editor.getClass().getDeclaredField("mCursorDrawable");
+      field.setAccessible(true);
+      field.set(editor, drawables);
+    } catch (Exception ignored) {
+    }
+  }
+
+  public static String convertDateString(Date date, String format) {
+    SimpleDateFormat dateFormat = new SimpleDateFormat(format, Locale.getDefault());
+    return dateFormat.format(date);
+  }
+
+  public static void DEBUG(Class<?> clazz, String msg) {
+
+    printDebug(clazz, msg);
+    //Log.d(MPlusFrameworkConstants.LOG_TAG, buildMessage(clazz, msg));
+
+  }
+
+  private static void printDebug(Class<?> clazz, String msg) {
+    byte[] msgByte = msg.getBytes();
+    int startIndex = 0;
+    int bufferSize = 3500;
+    while(msgByte.length > bufferSize) {
+      Log.d("JKSONG", buildMessage(clazz, new String(msgByte, startIndex, bufferSize-startIndex)));
+      startIndex = bufferSize;
+      bufferSize = bufferSize + 3500;
+    }
+    Log.d("JKSONG", buildMessage(clazz, new String(msgByte, startIndex, msgByte.length-startIndex)));
+  }
+
+  private static final SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss.SSS", Locale.getDefault());
+
+  /**
+   * 메시지 만들기
+   * @param clazz 로그를 찍는 클래스
+   * @param msg 메시지
+   * @return 출력할 형태의 메시지
+   */
+  private static String buildMessage(Class<?> clazz, String msg) {
+    final StringBuilder builder = new StringBuilder();
+
+    // 시간
+    builder.append(format.format(new Date())).append(" ");
+    // 클래스명
+    builder.append("[").append(clazz.getSimpleName()).append("] ");
+    if(msg != null) {
+      builder.append(msg);
+    }
+
+    return builder.toString();
+  }
+
+  /**
+   * base64Encode
+   * @author jksong
+   * @Param
+   * @since 2019-09-09 오전 8:29
+   **/
+  public static String base64Encode(String text) throws UnsupportedEncodingException {
+    byte[] data = text.getBytes("UTF-8");
+    return Base64.encode(data);
+    //return Base64.encodeToString(data, Base64.NO_WRAP);     //Android에서 Base64 인코딩 시에 개행문자를 삽입하지 않는 옵션은 NO_WRAP입니다.
+  }
+
+  /**
+   * base64Encode
+   * @author jksong
+   * @Param
+   * @since 2019-09-09 오전 8:29
+   **/
+  public static String base64Encode(byte[] digest) throws UnsupportedEncodingException {
+    return Base64.encode(digest);
+  }
+
+  /**
+   * GZip를 이용한 스트링 압축
+   * @author jksong
+   * @Param
+   * @since 2019-09-09 오전 8:30
+   **/
+  public static byte[] zipStringToBytes(String input) throws IOException {
+    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+    GZIPOutputStream gzipOutputStream = new GZIPOutputStream(byteArrayOutputStream);
+    BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(gzipOutputStream);
+    bufferedOutputStream.write(input.getBytes());
+    bufferedOutputStream.close();
+    byteArrayOutputStream.close();
+    return byteArrayOutputStream.toByteArray();
+  }
+
+  /**
+   * GZIPInputStream을 이용하여 byte배열 압축해제하기
+   * @author jksong
+   * @Param
+   * @since 2019-09-09 오전 8:30
+   **/
+  public String unzipStringFromBytes(byte[] bytes) throws IOException {
+    ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
+    GZIPInputStream gzipInputStream = new GZIPInputStream(byteArrayInputStream);
+    BufferedInputStream bufferedInputStream = new BufferedInputStream(gzipInputStream);
+    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+
+    byte[] buffer = new byte[100];
+    int length;
+    while((length = bufferedInputStream.read(buffer)) > 0) {
+      byteArrayOutputStream.write(buffer, 0, length);
+    }
+
+    bufferedInputStream.close();
+    gzipInputStream.close();
+    byteArrayInputStream.close();
+    byteArrayOutputStream.close();
+
+    return byteArrayOutputStream.toString();
+  }
+}

app/src/bonwon/res/drawable-xxxhdpi/ripple.xml → app/src/main/res/drawable/ripple.xml


app/src/bonwon/res/drawable-xxxhdpi/shape.xml → app/src/main/res/drawable/shape.xml


+ 2 - 0
app/src/main/res/values/strings.xml

@@ -6,5 +6,7 @@
     <string name="pwdHint">패스워드</string>
     <string name="certficate">인증적용</string>
     <string name="login">로그인</string>
+    <string name="confirm">확인</string>
+    <string name="cancel">취소</string>
 
 </resources>

+ 19 - 3
app/src/main/res/values/styles.xml

@@ -13,11 +13,22 @@
 
     </style>
 
-    <style name="MyRadioButtonStyle" parent="Widget.AppCompat.CompoundButton.RadioButton">
-        <!--<item name="android:textColor">@drawable/my_compound_button_color_selector</item>-->
-        <item name="buttonTint">@drawable/radio_button_selector</item>
+    <style name="DatePickerDialogTheme" parent="Theme.AppCompat.Light.Dialog">
+        <!--<item name="colorAccent">@color/shapeColor</item>-->
+        <item name="colorAccent">#005BAC</item>
+
+    </style>
+
+    <style name="Theme.AppCompat.Translucent">
+        <item name="android:windowBackground">@android:color/transparent</item>
+        <item name="android:colorBackgroundCacheHint">@null</item>
+        <item name="android:windowIsTranslucent">true</item>
+        <item name="android:windowAnimationStyle">@android:style/Animation</item>
+        <item name="windowNoTitle">true</item>
+        <item name="android:background">#1A000000</item>
     </style>
 
+    <!-- EditText Style -->
     <style name="EditTextStyle" parent="Widget.AppCompat.EditText">
         <item name="colorControlNormal">@color/transparentColor</item>
         <item name="colorControlActivated">@color/transparentColor</item>
@@ -27,4 +38,9 @@
         <!--<item name="android:textColorHighlight">@color/transparentColor</item>-->
     </style>
 
+    <style name="MyRadioButtonStyle" parent="Widget.AppCompat.CompoundButton.RadioButton">
+        <!--<item name="android:textColor">@drawable/my_compound_button_color_selector</item>-->
+        <item name="buttonTint">@drawable/radio_button_selector</item>
+    </style>
+
 </resources>