modify
diff --git a/Cargo.toml b/Cargo.toml
index 7645052..25d96e5 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,2 +1,6 @@
 [workspace]
-members = ["daliqrcode", "dlsmk"]
+members = ["dlqrcode", "dlsmk"]
+
+
+[profile.release]
+opt-level = "s"
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..643a3dc
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,15 @@
+CARGO ?=cargo
+RM ?=rm
+
+.PHONY: clean
+
+
+build:
+	$(CARGO) build --release
+
+android:
+	$(CARGO) build --target aarch64-linux-android --release -- -C prefer-dynamic
+	$(CARGO) build --target armv7-linux-androideabi --release -- -C prefer-dynamic
+
+clean:
+	$(RM) -rf target
diff --git a/daliqrcode/Cargo.toml b/dlqrcode/Cargo.toml
similarity index 100%
rename from daliqrcode/Cargo.toml
rename to dlqrcode/Cargo.toml
diff --git a/daliqrcode/src/lib.rs b/dlqrcode/src/lib.rs
similarity index 98%
rename from daliqrcode/src/lib.rs
rename to dlqrcode/src/lib.rs
index 9bb1114..fdcad91 100644
--- a/daliqrcode/src/lib.rs
+++ b/dlqrcode/src/lib.rs
@@ -38,6 +38,7 @@
 }
 
 impl DaliQrData {
+    #[allow(dead_code)]
     fn new() -> Self {
         Self {
             uid: String::from(""),
@@ -210,7 +211,7 @@
 
         let qrcode = unsafe {
             let s = slice::from_raw_parts(qrcode, len);
-            println!("qr input : {}", String::from_utf8_lossy(s));
+            // println!("qr input : {}", String::from_utf8_lossy(s));
             if let Ok(code) = base64_url::decode(s) {
                 code
             } else {
diff --git a/dlsmk/Cargo.toml b/dlsmk/Cargo.toml
index 4042d47..76c2eaa 100644
--- a/dlsmk/Cargo.toml
+++ b/dlsmk/Cargo.toml
@@ -14,6 +14,6 @@
 
 [dependencies]
 jni = "0.18.0"
-dlqrcode = { path = "../daliqrcode" }
+dlqrcode = { path = "../dlqrcode" }
 libc = "0.2.80"
 hex = "0.4.2"
diff --git a/dlsmk/src/lib.rs b/dlsmk/src/lib.rs
index 402a0c0..fa982de 100644
--- a/dlsmk/src/lib.rs
+++ b/dlsmk/src/lib.rs
@@ -25,7 +25,7 @@
 pub mod android {
     extern crate jni;
 
-    use self::jni::objects::{JClass, JObject, JString};
+    use self::jni::objects::{JClass, JMap, JObject, JString};
     use self::jni::sys::{jboolean, jlong, JNI_FALSE, JNI_TRUE};
     use self::jni::JNIEnv;
     // use super::*;
@@ -34,6 +34,14 @@
 
     use dlqrcode::DaliQrCode;
 
+    fn put_data(env: &JNIEnv, map: &JMap, key: &str, value: &str) {
+        map.put(
+            *env.new_string(key).unwrap(),
+            *env.new_string(value).unwrap(),
+        )
+        .unwrap();
+    }
+
     #[no_mangle]
     pub unsafe extern "C" fn Java_com_supwisdom_dlsmk_DLSMKQrCode_decode(
         env: JNIEnv,
@@ -43,42 +51,57 @@
         offset: jlong,
         result: JObject,
     ) -> jboolean {
-        // Our Java companion code might pass-in "world" as a string, hence the name.
-        let key = env
-            .get_string(key_hex)
-            .expect("invalid key string")
-            .as_ptr();
-        let keylen = libc::strlen(key);
-
-        println!("decode test, key length {}", keylen);
         let key = {
-            let k: &[u8] = slice::from_raw_parts(key as *const u8, keylen);
-            println!("key is : {}", String::from_utf8_lossy(k));
-            let mut key = [0u8; 32];
-            if let Ok(v) = hex::decode(k) {
-                key.clone_from_slice(v.as_slice());
-                key
+            let s = env
+                .get_string(key_hex)
+                .expect("invalid key string")
+                .as_ptr();
+            let keylen = libc::strlen(s);
+            let mut k = Vec::new();
+            k.extend_from_slice(slice::from_raw_parts(s as *const u8, keylen));
+            k
+        };
+
+        let qrcode = {
+            let s = env
+                .get_string(qrcode)
+                .expect("invalid qrcode string")
+                .as_ptr();
+            let qrlen = libc::strlen(s);
+            let mut q = Vec::new();
+            q.extend_from_slice(slice::from_raw_parts(s as *const u8, qrlen));
+            q
+        };
+
+        let qrdata = env.get_map(result).expect("invalid qrdata map");
+
+        let key = {
+            let mut k = [0u8; 32];
+            if let Ok(v) = hex::decode(key.as_slice()) {
+                k.clone_from_slice(v.as_slice());
+                k
             } else {
+                put_data(
+                    &env,
+                    &qrdata,
+                    "error",
+                    "key must be hex format and 64 characters",
+                );
                 return JNI_FALSE;
             }
         };
 
-        let qrcode = env
-            .get_string(qrcode)
-            .expect("invalid qrcode string")
-            .as_ptr();
-        let qrlen = libc::strlen(qrcode);
-
-
         let decode = match DaliQrCode::new(key, None, None, None, None) {
             Ok(d) => d,
-            Err(e) => panic!("invalid key {}", e),
+            Err(e) => {
+                let s = format!("invalid input parameter {:?}", e);
+                put_data(&env, &qrdata, "error", &s);
+                return JNI_FALSE;
+            }
         };
 
-        println!("decode qrcode begin , length : {}...", qrlen);
-        match decode.decode(qrcode as *const u8, qrlen, offset as i32) {
+        match decode.decode(qrcode.as_ptr(), qrcode.len(), offset as i32) {
             Ok(d) => {
-                let qrdata = env.get_map(result).expect("invalid qrdata map");
                 qrdata
                     .put(
                         *env.new_string("cardno").unwrap(),
@@ -100,9 +123,10 @@
                 return JNI_TRUE;
             }
             Err(e) => {
-                println!("Error {:?}", e);
+                let s = format!("{:?}", e);
+                put_data(&env, &qrdata, "error", &s);
                 return JNI_FALSE;
-            },
+            }
         };
     }
 }
diff --git a/java/src/main/java/com/supwisdom/dlsmk/DLSMK.java b/java/src/main/java/com/supwisdom/dlsmk/DLSMK.java
index 6150741..219284f 100644
--- a/java/src/main/java/com/supwisdom/dlsmk/DLSMK.java
+++ b/java/src/main/java/com/supwisdom/dlsmk/DLSMK.java
@@ -26,18 +26,18 @@
     public static void main(String[] args) {
         System.setProperty("java.library.path" , ".");
         String key = encodeHex(Base64.decodeBase64("Vbb1syh8U1+CdLmTVGdtDiVvKBQ81n4GmgBEO/ohSbU="));
-        String iv = "55b6f5b3287c535f8274b99354676d0e";
 
         String qrcode = "6lHyFX_vg5U2hymn8OsdNUD7dT0-sCmEQkKrm9cnzHlku6-FYxuL6nP5YR2Fve8Sfj-Asd-3dfQUkaiqqbfQWO8B_811B3uhHmGm9IjlpLicz_c1H1_ORb9tJl-IhMKu";
 
-
-        System.out.format("Key is %s", key);
-        System.out.println();
         Map<Object, Object> result = new HashMap();
         if (DLSMKQrCode.decode(key, qrcode, 0L, result)) {
             System.out.println("Decode OK");
+            System.out.format("cardno : %s", result.get("cardno").toString());
+            System.out.format("cardtype : %s", result.get("cardtype").toString());
+            System.out.println();
         } else {
-            System.out.println("Decode failed");
+            System.out.format("decode failed: %s", result.get("error").toString());
+            System.out.println();
         }
 
     }
diff --git a/java/src/main/java/com/supwisdom/dlsmk/DLSMKQrCode.java b/java/src/main/java/com/supwisdom/dlsmk/DLSMKQrCode.java
index c83a4a0..e9ee765 100644
--- a/java/src/main/java/com/supwisdom/dlsmk/DLSMKQrCode.java
+++ b/java/src/main/java/com/supwisdom/dlsmk/DLSMKQrCode.java
@@ -6,5 +6,5 @@
     static {
         System.loadLibrary("dlsmk");
     }
-    public static native boolean decode(String keyHex,String qrcode, Long offset, Map<Object, Object> result);
+    public static native boolean decode(String keyHex,String qrcodeBase64, Long offset, Map<Object, Object> result);
 }