Add Android App without objc glue

This commit is contained in:
Mimoja 2017-08-12 02:01:00 +02:00
parent a0047e1b54
commit 9e72a78c97
35 changed files with 786 additions and 0 deletions

1
Android/app/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
/build

View file

@ -0,0 +1,44 @@
# 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.4.1)
# 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.
native-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
src/main/jni/native-lib.m )
# 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.
native-lib
# Links the target library to the log library
# included in the NDK.
${log-lib} )

41
Android/app/build.gradle Normal file
View file

@ -0,0 +1,41 @@
apply plugin: 'com.android.application'
android {
compileSdkVersion 26
buildToolsVersion "26.0.1"
defaultConfig {
applicationId "mimoja.abfackeln.jetzt.scryptpwgen"
minSdkVersion 15
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
cppFlags ""
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:26.+'
compile 'com.android.support.constraint:constraint-layout:1.0.2'
compile 'com.android.support:design:26.+'
testCompile 'junit:junit:4.12'
}

25
Android/app/proguard-rules.pro vendored Normal file
View file

@ -0,0 +1,25 @@
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in /home/mimoja/Android/Sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# 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

View file

@ -0,0 +1,26 @@
package mimoja.abfackeln.jetzt.scryptpwgen;
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.*;
/**
* Instrumentation test, which will execute on an Android device.
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() throws Exception {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getTargetContext();
assertEquals("mimoja.abfackeln.jetzt.scryptpwgen", appContext.getPackageName());
}
}

View file

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="mimoja.abfackeln.jetzt.scryptpwgen">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

View file

@ -0,0 +1,173 @@
package mimoja.abfackeln.jetzt.scryptpwgen;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.support.v7.app.AlertDialog;
import android.text.InputType;
import android.view.ContextMenu;
import android.view.MenuInflater;
import android.view.textclassifier.TextClassification;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.ListView;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.view.MenuItem;
import android.widget.PopupWindow;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class MainActivity extends AppCompatActivity {
// Used to load the 'native-lib' library on application startup.
static {
System.loadLibrary("native-lib");
}
List<String> mKnownSites = null;
ArrayAdapter<String> mAdapter = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
//Fetch known sites
final SharedPreferences sharedPref = getPreferences(Context.MODE_PRIVATE);
Set<String> savedSites = sharedPref.getStringSet("knownSites", new HashSet<String>());
mKnownSites = new ArrayList<>(savedSites);
//Get Handle to List
ListView siteListView = (ListView) findViewById(R.id.siteList);
registerForContextMenu(siteListView);
mAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, mKnownSites);
siteListView.setAdapter(mAdapter);
for (String site : savedSites) {
mAdapter.add(site);
}
mAdapter.notifyDataSetChanged();
// site List
siteListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, final View view, int i, long l) {
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder.setTitle("Choose an action")
.setItems(R.array.actions, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
final String chosen = ((TextView)view).getText().toString();
final EditText userInput = new EditText(MainActivity.this);
userInput.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
switch (which){
case 0:
createTextDialog(userInput, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
String masterPasswd = userInput.getText().toString();
String passwd = generatePassword(chosen, masterPasswd);
ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
clipboard.setText(passwd);
Toast.makeText(MainActivity.this, "Password generated", Toast.LENGTH_LONG).show();
}
});
break;
case 1:
createTextDialog(userInput, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
String masterPasswd = userInput.getText().toString();
String passwd = generatePassword(chosen, masterPasswd);
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(MainActivity.this);
alertDialogBuilder.setTitle(passwd).setCancelable(true).show();
Toast.makeText(MainActivity.this, "Password generated", Toast.LENGTH_LONG).show();
}
});
break;
case 2:
mAdapter.remove(chosen);
saveItemList();
Toast.makeText(MainActivity.this, "Deleted", Toast.LENGTH_LONG).show();
break;
}
}
});
builder.create().show();
}
});
// Add button
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
final EditText userInput = new EditText(MainActivity.this);
createTextDialog(userInput, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
String site = userInput.getText().toString();
if(site.length() != 0){
//Show on screen
if(mKnownSites.contains(site)){
Toast.makeText(MainActivity.this, "Already cointained", Toast.LENGTH_LONG).show();
return;
}
mKnownSites.add(site);
saveItemList();
}
}
});
}
});
}
public void createTextDialog(EditText userInput, DialogInterface.OnClickListener listener){
final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(MainActivity.this);
alertDialogBuilder.setView(userInput);
alertDialogBuilder
.setCancelable(false)
.setPositiveButton("Go",listener)
.setNegativeButton("Cancel",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int id) {
dialog.dismiss();
}
}
);
AlertDialog alertDialog = alertDialogBuilder.create();
alertDialog.show();
userInput.requestFocus();
}
public void saveItemList(){
mAdapter.notifyDataSetChanged();
final SharedPreferences sharedPref = getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
editor.clear();
editor.putStringSet("knownSites", new HashSet<>(mKnownSites));
editor.commit();
}
public native String generatePassword(String site, String password);
}

View file

@ -0,0 +1,16 @@
#include <jni.h>
JNIEXPORT jstring JNICALL
Java_mimoja_abfackeln_jetzt_scryptpwgen_MainActivity_generatePassword(JNIEnv *env, jobject instance,
jstring site_,
jstring password_) {
const char *site = (*env)->GetStringUTFChars(env, site_, 0);
const char *password = (*env)->GetStringUTFChars(env, password_, 0);
const char *returnPassword = "Fix me in native-lib.m";
(*env)->ReleaseStringUTFChars(env, site_, site);
(*env)->ReleaseStringUTFChars(env, password_, password);
return (*env)->NewStringUTF(env, returnPassword);
}

View file

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="mimoja.abfackeln.jetzt.scryptpwgen.MainActivity">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
<include layout="@layout/content_main" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="@dimen/fab_margin"
app:srcCompat="@android:drawable/ic_input_add" />
</android.support.design.widget.CoordinatorLayout>

View file

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context="mimoja.abfackeln.jetzt.scryptpwgen.MainActivity"
tools:showIn="@layout/activity_main">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="2"
android:fillViewport="true"
android:gravity="top" >
<ListView
android:id="@+id/siteList"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</ScrollView>
</android.support.constraint.ConstraintLayout>

View file

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.javacodegeeks.android.menu.MainActivity" >
<item
android:id ="@+id/generateAndCopy"
android:title ="Generate password and copy to clipboard"/>
<item
android:id ="@+id/generateAndShow"
android:title ="Generate password and show"/>
<item
android:id ="@+id/delete"
android:title ="Remove"/>
</menu>

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="actions">
<item>Generate password and copy to clipboard</item>
<item>Generate password and show</item>
<item>Remove</item>
</string-array>
</resources>

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#3F51B5</color>
<color name="colorPrimaryDark">#303F9F</color>
<color name="colorAccent">#4081FF</color>
</resources>

View file

@ -0,0 +1,3 @@
<resources>
<dimen name="fab_margin">16dp</dimen>
</resources>

View file

@ -0,0 +1,4 @@
<resources>
<string name="app_name">SCryptPWGen</string>
<string name="action_settings">Settings</string>
</resources>

View file

@ -0,0 +1,20 @@
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
<style name="AppTheme.NoActionBar">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>
<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
</resources>

View file

@ -0,0 +1,17 @@
package mimoja.abfackeln.jetzt.scryptpwgen;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Example local unit test, which will execute on the development machine (host).
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
public class ExampleUnitTest {
@Test
public void addition_isCorrect() throws Exception {
assertEquals(4, 2 + 2);
}
}