diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..aa724b7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,15 @@ +*.iml +.gradle +/local.properties +/.idea/caches +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..61a9130 --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 0000000..23a89bb --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,22 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml new file mode 100644 index 0000000..a5f05cd --- /dev/null +++ b/.idea/jarRepositories.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..d5d35ec --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/LICENSE b/LICENSE deleted file mode 100644 index e39e8a3..0000000 --- a/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2020 源文雨 - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..4258db3 --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,123 @@ +plugins { + id 'com.android.application' + id 'kotlin-android' + id 'kotlin-android-extensions' + id 'AndResGuard' +} + +android { + compileSdkVersion 30 + buildToolsVersion "30.0.2" + + defaultConfig { + applicationId "top.fumiama.base16384" + minSdkVersion 23 + targetSdkVersion 30 + versionCode 1 + versionName "1.0" + resConfigs "zh", "en" + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + externalNativeBuild { + cmake { + cppFlags "" + } + } + multiDexEnabled = false + } + + signingConfigs { + release { + storeFile file('../../../OneDrive/swc/developer/android_key/open_key') + storePassword 'fumiama' + keyAlias 'default' + keyPassword 'fumiama' + v1SigningEnabled true + v2SigningEnabled true + } + } + + buildTypes { + release { + minifyEnabled true + shrinkResources true + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + signingConfig signingConfigs.release + } + debug{ + applicationIdSuffix '.test' + } + } + externalNativeBuild { + cmake { + path "src/main/cpp/CMakeLists.txt" + //version "3.10.2" + } + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + kotlinOptions { + jvmTarget = '1.8' + } +} + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" + implementation 'androidx.core:core-ktx:1.3.2' + implementation 'androidx.appcompat:appcompat:1.2.0' + implementation 'com.google.android.material:material:1.2.1' + implementation 'androidx.constraintlayout:constraintlayout:2.0.4' + testImplementation 'junit:junit:4.13.1' + androidTestImplementation 'androidx.test.ext:junit:1.1.2' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' +} + +andResGuard { + // mappingFile = file("./resource_mapping.txt") + mappingFile = null + use7zip = true + useSign = true + // 打开这个开关,会keep住所有资源的原始路径,只混淆资源的名字 + keepRoot = false + // 设置这个值,会把arsc name列混淆成相同的名字,减少string常量池的大小 + fixedResName = "arg" + // 打开这个开关会合并所有哈希值相同的资源,但请不要过度依赖这个功能去除去冗余资源 + mergeDuplicatedRes = true + whiteList = [ + // for your icon + "R.drawable.icon", + // for fabric + "R.string.com.crashlytics.*", + // for google-services + "R.string.google_app_id", + "R.string.gcm_defaultSenderId", + "R.string.default_web_client_id", + "R.string.ga_trackingId", + "R.string.firebase_database_url", + "R.string.google_api_key", + "R.string.google_crash_reporting_api_key" + ] + compressFilePattern = [ + "*.png", + "*.jpg", + "*.jpeg", + "*.gif", + ] + sevenzip { + artifact = 'com.tencent.mm:SevenZip:1.2.20' + //path = "/usr/local/bin/7za" + } + + /** + * 可选: 如果不设置则会默认覆盖assemble输出的apk + **/ + // finalApkBackupPath = "${project.rootDir}/final.apk" + + /** + * 可选: 指定v1签名时生成jar文件的摘要算法 + * 默认值为“SHA-1” + **/ + // digestalg = "SHA-256" +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/androidTest/java/top/fumiama/base16384/ExampleInstrumentedTest.kt b/app/src/androidTest/java/top/fumiama/base16384/ExampleInstrumentedTest.kt new file mode 100644 index 0000000..e5bedd8 --- /dev/null +++ b/app/src/androidTest/java/top/fumiama/base16384/ExampleInstrumentedTest.kt @@ -0,0 +1,24 @@ +package top.fumiama.base16384 + +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.ext.junit.runners.AndroidJUnit4 + +import org.junit.Test +import org.junit.runner.RunWith + +import org.junit.Assert.* + +/** + * Instrumented test, which will execute on an Android device. + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +@RunWith(AndroidJUnit4::class) +class ExampleInstrumentedTest { + @Test + fun useAppContext() { + // Context of the app under test. + val appContext = InstrumentationRegistry.getInstrumentation().targetContext + assertEquals("top.fumiama.base16384", appContext.packageName) + } +} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..c546105 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/cpp/CMakeLists.txt b/app/src/main/cpp/CMakeLists.txt new file mode 100644 index 0000000..755dbc5 --- /dev/null +++ b/app/src/main/cpp/CMakeLists.txt @@ -0,0 +1,48 @@ +# For more information about using CMake with Android Studio, read the +# documentation: https://d.android.com/studio/projects/add-native-code.html + +# Sets the minimum version of CMake required to build the native library. + +cmake_minimum_required(VERSION 3.10.2) + +# Declares and names the project. + +project("base16384") + +# Creates and names a library, sets it as either STATIC +# or SHARED, and provides the relative paths to its source code. +# You can define multiple libraries, and CMake builds them for you. +# Gradle automatically packages shared libraries with your APK. + +add_library( # Sets the name of the library. + base16384 + + # Sets the library as a shared library. + SHARED + + # Provides a relative path to your source file(s). + base16384.cpp ) + +# Searches for a specified prebuilt library and stores the path as a +# variable. Because CMake includes system libraries in the search path by +# default, you only need to specify the name of the public NDK library +# you want to add. CMake verifies that the library exists before +# completing its build. + +find_library( # Sets the name of the path variable. + log-lib + + # Specifies the name of the NDK library that + # you want CMake to locate. + log ) + +# Specifies libraries CMake should link to your target library. You +# can link multiple libraries, such as libraries you define in this +# build script, prebuilt third-party libraries, or system libraries. + +target_link_libraries( # Specifies the target library. + base16384 + + # Links the target library to the log library + # included in the NDK. + ${log-lib} ) \ No newline at end of file diff --git a/app/src/main/cpp/base16384.cpp b/app/src/main/cpp/base16384.cpp new file mode 100644 index 0000000..d7b36de --- /dev/null +++ b/app/src/main/cpp/base16384.cpp @@ -0,0 +1,28 @@ +#include +#include +#include +#include "base16384.h" + +FILE *fp, *fpo; + +#define execute(function){\ + const char *inputFileDir = env->GetStringUTFChars(sf, JNI_FALSE);\ + const char *outputFileDir = env->GetStringUTFChars(df, JNI_FALSE);\ + fp = fpo = nullptr;\ + fp = fopen(inputFileDir, "rb");\ + fpo = fopen(outputFileDir, "wb");\ + if(fp != nullptr && fpo != nullptr){\ + function(fp, fpo);\ + env->ReleaseStringUTFChars(sf, inputFileDir);\ + env->ReleaseStringUTFChars(df, outputFileDir);\ + fclose(fp);\ + fclose(fpo);\ + return 0;\ + }else return 1;\ +} + +extern "C" JNIEXPORT int JNICALL +Java_top_fumiama_base16384_MainActivity_encode(JNIEnv* env, jobject, jstring sf, jstring df) execute(encode) + +extern "C" JNIEXPORT int JNICALL +Java_top_fumiama_base16384_MainActivity_decode(JNIEnv* env, jobject, jstring sf, jstring df) execute(decode) \ No newline at end of file diff --git a/app/src/main/cpp/base16384.h b/app/src/main/cpp/base16384.h new file mode 100644 index 0000000..76e411c --- /dev/null +++ b/app/src/main/cpp/base16384.h @@ -0,0 +1,78 @@ +// +// Created by rumia on 2020/12/16. +// + +#ifndef BASE16384_BASE16384_H +#define BASE16384_BASE16384_H + +//base16384.h +//MIT fumiama 20200416 +#include "bitio.h" +#define HEAD 0x4E +BIT outbuf; +unsigned char buf[BUFSIZ]; +void push(int istrue, FILE *fpo, int offset){ + if(!~pushbit(&outbuf, istrue)){ + if(offset) for(int i = 0; i < BITBUFSIZE; i += 2) outbuf.b[i] += offset; + fwrite(outbuf.b, sizeof(char), BITBUFSIZE, fpo); + outbuf.p = 0; + pushbit(&outbuf, istrue); + } +} +#define setoffset(x, offset){\ + char flag = 0;\ + ch1 = ch2 = x;\ + while(!feof(fp) && (ch1 = fgetc(fp)) == x && (ch2 = fgetc(fp)) == x) {cnt8 -= offset; flag++;}\ + if(ch2 != x) {ungetc(ch2, fp); ch2 = x;}\ + if(ch1 != x) {ungetc(ch1, fp); ch1 = x;}\ + while(feof(fp) && buf[cnt - 1] == x && buf[cnt - 2] == x) {cnt8 -= offset; cnt -= 2; flag++;}\ + if(flag) cnt8 -= 8;\ +} +void encode(FILE *fp, FILE *fpo){ + int cnt; + + memset(&outbuf, 0, sizeof(BIT)); + fputc(0xFE, fpo); + fputc(0xFF, fpo); + while((cnt = fread(buf, sizeof(char), BUFSIZ, fp))){ + for(int i = 0; i < cnt * 8; i++){ + if(!(outbuf.p % 16)){ + push(0, fpo, HEAD); + push(0, fpo, HEAD); + } + push(buf[i / 8] & (128u >> (i % 8)), fpo, HEAD); + } + } + if(outbuf.p){ + outbuf.b[outbuf.p / 8] &= ~(255u >> outbuf.p % 8); + for(int i = 0; i < outbuf.p / 8 + 1; i += 2) outbuf.b[i] += HEAD; + fwrite(outbuf.b, sizeof(char), (outbuf.p % 8)?outbuf.p / 8 + 1:outbuf.p / 8 , fpo); + if(((outbuf.p % 8)?outbuf.p / 8 + 1:outbuf.p / 8) % 2){ + fputc(0, fpo); + fputc('>', fpo); + fputc('>', fpo); + } + for(int i = 0; i < outbuf.p % 8; i++) fputc('=', fpo); + } +} +void decode(FILE *fp, FILE *fpo){ + int cnt, cnt8; + char ch1, ch2; + memset(&outbuf, 0, sizeof(BIT)); + while((cnt = fread(buf, sizeof(char), BUFSIZ, fp))){ + cnt8 = cnt * 8; + setoffset('=', 14) + setoffset('>', 16) + + for(int i = ((buf[0] == 0xFE)?16:0); i < cnt8; i++){ + if(!(i % 16)){ + buf[i / 8] -= HEAD; + i += 2; + } + push(buf[i / 8] & (128u >> (i % 8)), fpo, 0); + } + } + if(outbuf.p) fwrite(outbuf.b, sizeof(char), (outbuf.p % 8)?outbuf.p / 8 + 1:outbuf.p / 8, fpo); +} + +#endif //BASE16384_BASE16384_H diff --git a/app/src/main/cpp/bitio.h b/app/src/main/cpp/bitio.h new file mode 100644 index 0000000..47d7084 --- /dev/null +++ b/app/src/main/cpp/bitio.h @@ -0,0 +1,53 @@ +// +// Created by rumia on 2020/12/16. +// + +#ifndef BASE16384_BITIO_H +#define BASE16384_BITIO_H +//bitio.h +//made by fumiama +//20200413 +#ifndef BITBUFSIZE +#define BITBUFSIZE 1024 +#endif +struct BIT{ + char b[BITBUFSIZE]; + int p; +}; +typedef struct BIT BIT; + +int pushbit(BIT *buffer, const int isture){ + if(buffer->p >= BITBUFSIZE * 8) return EOF; + else if(isture) buffer->b[buffer->p / 8] |= 128u >> buffer->p % 8; + else buffer->b[buffer->p / 8] &= ~(128u >> buffer->p % 8); + buffer->p++; + return isture; +} + +int fpushbit(BIT *buffer, FILE *fp){ + memset(buffer, 0, sizeof(BIT)); + if((buffer->p = fread(buffer->b, sizeof(char), BITBUFSIZE, fp)) && feof(fp)) + buffer->p = (buffer->p - 2) * 8 + buffer->b[buffer->p - 1] + 1; + else buffer->p *= 8; + return buffer->p; +} + +int changebit(BIT *buffer, const int isture, const int position){ + if(position >= buffer->p) return EOF; + else if(isture) buffer->b[position / 8] |= 128u >> position % 8; + else buffer->b[position / 8] &= ~(128u >> position % 8); + buffer->p++; + return isture; +} + +int readbit(const BIT *buffer, const int position){ + if(position >= buffer->p) return EOF; + else return buffer->b[position / 8] & (128u >> position % 8); +} + +int popbit(BIT *buffer){ + if(buffer->p >= BITBUFSIZE * 8 || buffer->p < 0) return EOF; + buffer->p--; + return buffer->b[(buffer->p+1) / 8] & (128u >> (buffer->p+1) % 8); +} +#endif //BASE16384_BITIO_H diff --git a/app/src/main/java/top/fumiama/base16384/MainActivity.kt b/app/src/main/java/top/fumiama/base16384/MainActivity.kt new file mode 100644 index 0000000..075ad21 --- /dev/null +++ b/app/src/main/java/top/fumiama/base16384/MainActivity.kt @@ -0,0 +1,186 @@ +package top.fumiama.base16384 + +import android.Manifest +import android.app.Activity +import android.content.Intent +import android.content.pm.PackageManager +import android.net.Uri +import android.os.Build +import android.os.Bundle +import android.view.View +import android.widget.Toast +import androidx.core.app.ActivityCompat +import androidx.core.content.ContextCompat +import kotlinx.android.synthetic.main.activity_main.* +import java.io.File +import java.io.FileInputStream + + +class MainActivity : Activity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_main) + sv.viewTreeObserver.addOnGlobalLayoutListener { + val h = sv.getChildAt(0).height + tti.visibility = if(h > resources.displayMetrics.heightPixels) View.GONE else View.VISIBLE + } + fab.setOnClickListener { if(checkReadPermission()) pickFile() } + ben.setOnClickListener { + ten.text?.let { + if(it.isNotEmpty()){ + val inputFile = generateCacheFile("input") + val outputFile = generateCacheFile("output") + inputFile.writeText(it.toString(), Charsets.UTF_16BE) + encode(inputFile.absolutePath, outputFile.absolutePath) + tde.setText(outputFile.readText(Charsets.UTF_16BE)) + } + } + } + bde.setOnClickListener { + tde.text?.let { + if(it.isNotEmpty()){ + val inputFile = generateCacheFile("input") + val outputFile = generateCacheFile("output") + inputFile.writeText(it.toString(), Charsets.UTF_16BE) + decode(inputFile.absolutePath, outputFile.absolutePath) + ten.setText(outputFile.readText(Charsets.UTF_16BE)) + } + } + } + } + + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + super.onActivityResult(requestCode, resultCode, data) + if (resultCode == RESULT_OK) when (requestCode) { + 1 -> data?.data?.let { doFromFile(it) } + 2 -> data?.data?.let { save2Uri(it) } + } + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + when (requestCode) { + 1 -> { + if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) pickFile() + else Toast.makeText(this, R.string.permissionDenied, Toast.LENGTH_SHORT).show() + } + } + } + + /*private fun packZip(zipf: File, outf: File){ + zipf.parentFile?.let { if(!it.exists()) it.mkdirs() } + if(zipf.exists()) zipf.delete() + zipf.createNewFile() + val zip = ZipOutputStream(CheckedOutputStream(zipf.outputStream(), CRC32())) + zip.setLevel(9) + zip.putNextEntry(ZipEntry("output")) + zip.write(outf.readBytes()) + zip.flush() + zip.close() + }*/ + + + private fun doFromFile(uri: Uri){ + val inputFile = generateCacheFile("input") + val outputFile = generateCacheFile("output") + saveFile(inputFile, uri) + val br = inputFile.bufferedReader(Charsets.US_ASCII) + val head1 = br.read() + val head2 = br.read() + val re = if(head1 == 0xFE && head2 == 0xFF) decode(inputFile.absolutePath, outputFile.absolutePath) + else encode(inputFile.absolutePath, outputFile.absolutePath) + Toast.makeText( + this, + if(re == 0) { + createFile(getString(R.string.output)) + R.string.succeed + } else R.string.failed, + Toast.LENGTH_SHORT + ).show() + } + + private fun saveFile(f: File?, uri: Uri) { + val fd = contentResolver.openFileDescriptor(uri, "r") + fd?.fileDescriptor?.let { + val fi = FileInputStream(it) + f?.outputStream()?.let { + fi.copyTo(it) + it.close() + } + fi.close() + } + fd?.close() + } + + private fun save2Uri(uri: Uri){ + val outputFile = generateCacheFile("output") + contentResolver.openOutputStream(uri)?.let { + val fi = outputFile.inputStream() + fi.copyTo(it) + fi.close() + it.close() + } + } + + private fun createFile(fileName: String, type: String = "*/*"){ + val intent = Intent(Intent.ACTION_CREATE_DOCUMENT) + intent.addCategory(Intent.CATEGORY_OPENABLE) + intent.type = type + intent.putExtra(Intent.EXTRA_TITLE, fileName) + startActivityForResult(intent, 2) + } + + /*private fun shareFile(file: File, type: String) { + if (file.exists()) { + val share = Intent(Intent.ACTION_SEND) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + val contentUri = FileProvider.getUriForFile(this, BuildConfig.APPLICATION_ID + ".fileprovider", file) + share.putExtra(Intent.EXTRA_STREAM, contentUri) + share.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) + }else share.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(file)) + share.type = type //此处可发送多种文件 + share.flags = Intent.FLAG_ACTIVITY_NEW_TASK + share.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) + startActivity(Intent.createChooser(share, getString(R.string.share))) + } else Toast.makeText(this, getString(R.string.read_file_err), Toast.LENGTH_SHORT).show() + }*/ + + private fun checkReadPermission(): Boolean { + return if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N && ContextCompat.checkSelfPermission( + this, + Manifest.permission.READ_EXTERNAL_STORAGE + ) != PackageManager.PERMISSION_GRANTED) { + ActivityCompat.requestPermissions( + this, + arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE), + 1 + ) + false + } else true + } + + private fun pickFile() { + val i = Intent(Intent.ACTION_GET_CONTENT) + i.type = "*/*" + startActivityForResult(i, 1) + } + + private fun generateCacheFile(name: String) = File(cacheDir, name) + + /** + * A native method that is implemented by the 'native-lib' native library, + * which is packaged with this application. + */ + private external fun encode(sf: String, df: String): Int + private external fun decode(sf: String, df: String): Int + + companion object { + // Used to load the 'native-lib' library on application startup. + init { + System.loadLibrary("base16384") + } + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-anydpi/ic_add.xml b/app/src/main/res/drawable-anydpi/ic_add.xml new file mode 100644 index 0000000..624632f --- /dev/null +++ b/app/src/main/res/drawable-anydpi/ic_add.xml @@ -0,0 +1,13 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable-anydpi/ic_launcher_background.xml b/app/src/main/res/drawable-anydpi/ic_launcher_background.xml new file mode 100644 index 0000000..f2195d5 --- /dev/null +++ b/app/src/main/res/drawable-anydpi/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable-anydpi/ic_xi.xml b/app/src/main/res/drawable-anydpi/ic_xi.xml new file mode 100644 index 0000000..9e842b9 --- /dev/null +++ b/app/src/main/res/drawable-anydpi/ic_xi.xml @@ -0,0 +1,10 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/font/gotham.ttf b/app/src/main/res/font/gotham.ttf new file mode 100644 index 0000000..58018ad Binary files /dev/null and b/app/src/main/res/font/gotham.ttf differ diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..a0b01f4 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + +