From 6158a7ad2b77e6e6e8fa979565954719611807e7 Mon Sep 17 00:00:00 2001 From: ecpvint Date: Thu, 15 Aug 2024 18:35:25 +0800 Subject: [PATCH] init --- .gitignore | 2 + app.iml | 124 +++++++++++++ build.gradle | 26 +++ libs/Utils.jar | Bin 0 -> 8227 bytes proguard-rules.pro | 21 +++ readme.md | 7 + .../agct/ExampleInstrumentedTest.java | 26 +++ src/main/AndroidManifest.xml | 29 +++ .../java/net/droidtech/agct/DecodeThread.java | 49 +++++ .../java/net/droidtech/agct/EncodeThread.java | 49 +++++ .../java/net/droidtech/agct/MainActivity.java | 172 ++++++++++++++++++ .../drawable-v24/ic_launcher_foreground.xml | 34 ++++ .../res/drawable/ic_launcher_background.xml | 170 +++++++++++++++++ src/main/res/layout/activity_main.xml | 62 +++++++ src/main/res/values/strings.xml | 26 +++ src/main/res/values/styles.xml | 8 + .../net/droidtech/agct/ExampleUnitTest.java | 17 ++ 17 files changed, 822 insertions(+) create mode 100644 .gitignore create mode 100644 app.iml create mode 100644 build.gradle create mode 100644 libs/Utils.jar create mode 100644 proguard-rules.pro create mode 100644 readme.md create mode 100644 src/androidTest/java/net/droidtech/agct/ExampleInstrumentedTest.java create mode 100644 src/main/AndroidManifest.xml create mode 100644 src/main/java/net/droidtech/agct/DecodeThread.java create mode 100644 src/main/java/net/droidtech/agct/EncodeThread.java create mode 100644 src/main/java/net/droidtech/agct/MainActivity.java create mode 100644 src/main/res/drawable-v24/ic_launcher_foreground.xml create mode 100644 src/main/res/drawable/ic_launcher_background.xml create mode 100644 src/main/res/layout/activity_main.xml create mode 100644 src/main/res/values/strings.xml create mode 100644 src/main/res/values/styles.xml create mode 100644 src/test/java/net/droidtech/agct/ExampleUnitTest.java diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..956c004 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/build +/release \ No newline at end of file diff --git a/app.iml b/app.iml new file mode 100644 index 0000000..d99b865 --- /dev/null +++ b/app.iml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..9ef114a --- /dev/null +++ b/build.gradle @@ -0,0 +1,26 @@ +apply plugin: 'com.android.application' + +android { + compileSdkVersion 26 + defaultConfig { + applicationId "net.droidtech.agct" + minSdkVersion 14 + versionCode 1 + versionName "1.0" + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + androidTestImplementation 'com.android.support.test:runner:1.0.2' + androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' + implementation files('libs/Utils.jar') + +} diff --git a/libs/Utils.jar b/libs/Utils.jar new file mode 100644 index 0000000000000000000000000000000000000000..498b61e5e7c81b723e1881e694bc5a9e278ea622 GIT binary patch literal 8227 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利用AGCT四种碱基字符编码任何字符串

+ +

安卓项目

\ No newline at end of file diff --git a/src/androidTest/java/net/droidtech/agct/ExampleInstrumentedTest.java b/src/androidTest/java/net/droidtech/agct/ExampleInstrumentedTest.java new file mode 100644 index 0000000..84f1e20 --- /dev/null +++ b/src/androidTest/java/net/droidtech/agct/ExampleInstrumentedTest.java @@ -0,0 +1,26 @@ +package net.droidtech.agct; + +import android.content.Context; +import android.support.test.InstrumentationRegistry; +import android.support.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.*; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() throws Exception { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getTargetContext(); + + assertEquals("net.droidtech.acgt", appContext.getPackageName()); + } +} diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml new file mode 100644 index 0000000..501185a --- /dev/null +++ b/src/main/AndroidManifest.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/java/net/droidtech/agct/DecodeThread.java b/src/main/java/net/droidtech/agct/DecodeThread.java new file mode 100644 index 0000000..1721fdc --- /dev/null +++ b/src/main/java/net/droidtech/agct/DecodeThread.java @@ -0,0 +1,49 @@ +package net.droidtech.agct; + +import android.os.Handler; +import android.os.Message; + +import net.droidtech.utils.AGCT; + +/** + * Created by root on 2019/7/17. + */ + +public class DecodeThread extends Thread { + + private String data; + private Handler handler; + + public void putEncodedData(String data){ + this.data=data; + } + + public void setHandler(Handler handler){ + this.handler=handler; + } + + + @Override + public void run(){ + + Message msg=handler.obtainMessage(); + + byte[] result=AGCT.decode(this.data); + + if(result!=null){ + + msg.what=4; + + msg.obj=result; + + }else{ + + msg.what=1; + + } + + msg.sendToTarget(); + + } +} + diff --git a/src/main/java/net/droidtech/agct/EncodeThread.java b/src/main/java/net/droidtech/agct/EncodeThread.java new file mode 100644 index 0000000..72c883b --- /dev/null +++ b/src/main/java/net/droidtech/agct/EncodeThread.java @@ -0,0 +1,49 @@ +package net.droidtech.agct; + +import android.os.Handler; +import android.os.Message; + +import net.droidtech.utils.AGCT; + +/** + * Created by root on 2019/7/16. + */ + +public class EncodeThread extends Thread { + + private byte[] data; + private Handler handler; + + public void putRawData(byte[] data){ + this.data=data; + } + + public void setHandler(Handler handler){ + this.handler=handler; + } + + + @Override + public void run(){ + + Message msg=handler.obtainMessage(); + + String result=AGCT.encode(this.data); + + if(result!=null){ + + msg.what=2; + + msg.obj=result; + + }else{ + + msg.what=1; + + } + + msg.sendToTarget(); + + } + +} diff --git a/src/main/java/net/droidtech/agct/MainActivity.java b/src/main/java/net/droidtech/agct/MainActivity.java new file mode 100644 index 0000000..ab78475 --- /dev/null +++ b/src/main/java/net/droidtech/agct/MainActivity.java @@ -0,0 +1,172 @@ +package net.droidtech.agct; + +import android.app.Activity; +import android.app.ProgressDialog; +import android.content.ClipData; +import android.content.ClipboardManager; +import android.content.Context; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.view.View; +import android.widget.Button; +import android.widget.EditText; +import android.widget.Toast; + +public class MainActivity extends Activity { + + private ProgressDialog inProgress; + private EditText msgInput; + private EditText output; + private static ThreadResultHandler threadHandler; + + @Override + protected void onCreate(Bundle savedInstanceState) { + + super.onCreate(savedInstanceState); + + setContentView(R.layout.activity_main); + + inProgress=new ProgressDialog(this); + inProgress.setTitle(R.string.please_wait); + inProgress.setMessage(this.getApplicationContext().getResources().getString(R.string.in_progress)); + inProgress.setCancelable(false); + + threadHandler = new ThreadResultHandler(); +; + this.msgInput=this.findViewById(R.id.messageInput); + this.output=this.findViewById(R.id.output); + + output.setEnabled(false); + + Button encode=this.findViewById(R.id.encode); + encode.setOnClickListener(new View.OnClickListener(){ + + @Override + public void onClick(View view){ + + EncodeThread thread=new EncodeThread(); + + try { + + thread.putRawData(msgInput.getText().toString().getBytes("UTF-8")); + + }catch (Exception e){ + + Toast.makeText(MainActivity.this,R.string.encoding_error,Toast.LENGTH_LONG).show(); + + return; + + } + thread.setHandler(threadHandler); + inProgress.show(); + thread.start(); + + } + + }); + + Button decode=findViewById(R.id.decode); + decode.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + + DecodeThread thread=new DecodeThread(); + thread.setHandler(threadHandler); + + if(msgInput.getText().toString().trim().isEmpty()){ + + String first=((ClipboardManager)getSystemService(Context.CLIPBOARD_SERVICE)).getPrimaryClip().getItemAt(0).getText().toString(); + + Toast.makeText(MainActivity.this,R.string.read_clipboard,Toast.LENGTH_LONG).show(); + thread.putEncodedData(first); + + }else { + + thread.putEncodedData(msgInput.getText().toString()); + + } + + inProgress.show(); + thread.start(); + + } + }); + + Button copy_output=findViewById(R.id.copy_output); + copy_output.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + + if(threadHandler.lastOutputMessage!=null){ + + ClipboardManager cm =(ClipboardManager)getSystemService(Context.CLIPBOARD_SERVICE); + + ClipData cd = ClipData.newPlainText("output",threadHandler.lastOutputMessage); + + cm.setPrimaryClip(cd); + + Toast.makeText(MainActivity.this,R.string.copied,Toast.LENGTH_LONG).show(); + + } + + + } + }); + + } + + private class ThreadResultHandler extends Handler{ + + private String lastOutputMessage=null; + + @Override + public void handleMessage(Message msg){ + try { + + if (msg.what == 2) { + + output.setEnabled(false); + + if(((String)msg.obj).length()>1024){ + + output.setText(MainActivity.this.getResources().getText(R.string.message_too_long)); + + }else { + + output.setText((String) msg.obj); + + } + + lastOutputMessage=(String)msg.obj; + + } else if (msg.what == 4) { + + output.setEnabled(true); + + output.setText(new String(((byte[]) msg.obj), "UTF-8")); + + this.lastOutputMessage=new String(((byte[]) msg.obj), "UTF-8"); + + } + + }catch(Exception e){ + + output.setText(MainActivity.this.getResources().getString(R.string.error)); + output.setEnabled(false); + + } + + if(msg.what==1) { + + output.setText(R.string.error); + lastOutputMessage=MainActivity.this.getString(R.string.error); + output.setEnabled(false); + + } + + inProgress.dismiss(); + } + } + +} diff --git a/src/main/res/drawable-v24/ic_launcher_foreground.xml b/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..c7bd21d --- /dev/null +++ b/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + diff --git a/src/main/res/drawable/ic_launcher_background.xml b/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..d5fccc5 --- /dev/null +++ b/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/res/layout/activity_main.xml b/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..9d72e95 --- /dev/null +++ b/src/main/res/layout/activity_main.xml @@ -0,0 +1,62 @@ + + + + + + + + + + +