renamed to MISPBump
|
@ -1,30 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="NullableNotNullManager">
|
||||
<option name="myDefaultNullable" value="android.support.annotation.Nullable" />
|
||||
<option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
|
||||
<option name="myNullables">
|
||||
<value>
|
||||
<list size="5">
|
||||
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
|
||||
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
|
||||
<item index="2" class="java.lang.String" itemvalue="javax.annotation.CheckForNull" />
|
||||
<item index="3" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
|
||||
<item index="4" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
<option name="myNotNulls">
|
||||
<value>
|
||||
<list size="4">
|
||||
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
|
||||
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
|
||||
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
|
||||
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||
</component>
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/MispBump.iml" filepath="$PROJECT_DIR$/MispBump.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/app/app.iml" filepath="$PROJECT_DIR$/app/app.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/misp-auth.iml" filepath="$PROJECT_DIR$/misp-auth.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
|
@ -1,124 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Palette2">
|
||||
<group name="Swing">
|
||||
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
|
||||
</item>
|
||||
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.png" removable="false" auto-create-binding="false" can-attach-label="true">
|
||||
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
|
||||
<initial-values>
|
||||
<property name="text" value="Button" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="RadioButton" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="CheckBox" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="Label" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
|
||||
<preferred-size width="200" height="200" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
|
||||
<preferred-size width="200" height="200" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
|
||||
<preferred-size width="-1" height="20" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
|
||||
</item>
|
||||
</group>
|
||||
</component>
|
||||
</project>
|
|
@ -1,6 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
33
README.md
|
@ -1,33 +0,0 @@
|
|||

|
||||
|
||||
|
||||
# MISPBump
|
||||
|
||||
With MISPBump it is easy to synchronise events on different MISP instances. Instead of generating organisations, sync-users and sync-servers you only have to scan two QR-Codes and you are ready for syncing.
|
||||
|
||||
# Security
|
||||
|
||||
A key agreement is realized with Diffie Hellman (Elliptic Curve 256 Bit), sensible data is encrypted with AES.
|
||||
|
||||
TODO: how are credentials stored in app, keystore?
|
||||
|
||||
|
||||
# How does it work?
|
||||
|
||||
1. Gather your organisation information from your MISP instance
|
||||

|
||||
|
||||
1. Scan your partners generated public key and at the same time share yours
|
||||

|
||||
|
||||
2. Validate the public key you scanned
|
||||

|
||||
|
||||
3. After another scan the information you need to synchronise is securely transmitted to your phone
|
||||

|
||||
|
||||
4. Upload the information to your own MISP instance
|
||||

|
||||
|
||||
5. That's it! You are ready to share events across your instances
|
||||

|
|
@ -2,10 +2,9 @@ apply plugin: 'com.android.application'
|
|||
|
||||
android {
|
||||
compileSdkVersion 27
|
||||
buildToolsVersion "28.0.0"
|
||||
defaultConfig {
|
||||
applicationId "de.overview.wg.its.mispauth"
|
||||
minSdkVersion 23
|
||||
applicationId "de.overview.wg.its.mispbump"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 27
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
|
@ -17,29 +16,26 @@ android {
|
|||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
packagingOptions {
|
||||
exclude 'META-INF/DEPENDENCIES'
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
|
||||
implementation 'com.android.support:appcompat-v7:27.1.1'
|
||||
implementation 'com.android.support.constraint:constraint-layout:1.1.2'
|
||||
testImplementation 'junit:junit:4.12'
|
||||
androidTestImplementation 'com.android.support.test:runner:1.0.2'
|
||||
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
|
||||
implementation 'com.android.support:cardview-v7:27.1.1'
|
||||
implementation 'com.android.support:design:27.1.1'
|
||||
implementation 'com.android.support:gridlayout-v7:27.1.1'
|
||||
implementation 'com.android.support:recyclerview-v7:27.1.1'
|
||||
implementation 'com.android.support:cardview-v7:27.1.1'
|
||||
implementation 'com.android.support.constraint:constraint-layout:1.1.2'
|
||||
|
||||
implementation 'com.google.android.gms:play-services-vision:15.0.2'
|
||||
|
||||
implementation 'com.android.volley:volley:1.1.0'
|
||||
implementation 'com.github.kenglxn.QRGen:android:2.5.0'
|
||||
implementation group: 'org.mongodb', name: 'bson', version: '3.8.0'
|
||||
implementation group: 'com.google.code.gson', name: 'gson', version: '2.8.5'
|
||||
implementation 'org.mongodb:bson:3.8.0'
|
||||
implementation 'com.google.code.gson:gson:2.8.5'
|
||||
|
||||
|
||||
|
||||
implementation 'com.google.android.gms:play-services-vision:15.0.2'
|
||||
implementation 'com.android.support:gridlayout-v7:27.1.1'
|
||||
implementation 'com.ernestoyaquello.stepperform:vertical-stepper-form:0.9.9'
|
||||
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
||||
testImplementation 'junit:junit:4.12'
|
||||
androidTestImplementation 'com.android.support.test:runner:1.0.2'
|
||||
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package de.overview.wg.its.mispauth;
|
||||
package de.overview.wg.its.mispbump;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.test.InstrumentationRegistry;
|
||||
|
@ -16,11 +16,11 @@ import static org.junit.Assert.*;
|
|||
*/
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class ExampleInstrumentedTest {
|
||||
@Test
|
||||
public void useAppContext() throws Exception {
|
||||
// Context of the app under test.
|
||||
Context appContext = InstrumentationRegistry.getTargetContext();
|
||||
@Test
|
||||
public void useAppContext() {
|
||||
// Context of the app under test.
|
||||
Context appContext = InstrumentationRegistry.getTargetContext();
|
||||
|
||||
assertEquals("de.overview.wg.its.mispauth", appContext.getPackageName());
|
||||
}
|
||||
assertEquals("de.overview.wg.its.mispbump", appContext.getPackageName());
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="de.overview.wg.its.mispauth">
|
||||
package="de.overview.wg.its.mispbump">
|
||||
|
||||
<uses-permission android:name="android.permission.CAMERA"/>
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
|
@ -17,6 +17,7 @@
|
|||
android:label="@string/app_name">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
@ -27,14 +28,14 @@
|
|||
android:screenOrientation="portrait"
|
||||
android:theme="@style/AppTheme.Fullscreen">
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".CredentialsActivity"
|
||||
android:label="@string/credentials_activity"
|
||||
android:parentActivityName=".MainActivity"
|
||||
android:screenOrientation="portrait"/>
|
||||
|
||||
<activity android:name=".UploadActivity"/>
|
||||
|
||||
<activity android:name=".SyncUploadActivity"/>
|
||||
<activity
|
||||
android:name=".MyOrganisationActivity"
|
||||
android:label="@string/credentials_activity"
|
||||
android:parentActivityName=".MainActivity"/>
|
||||
<activity android:name=".QrSyncActivity">
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
</manifest>
|
|
@ -1,426 +0,0 @@
|
|||
package de.overview.wg.its.mispauth;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Dialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.support.design.widget.FloatingActionButton;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.support.design.widget.TextInputLayout;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.support.v7.widget.DefaultItemAnimator;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
import com.android.volley.VolleyError;
|
||||
import de.overview.wg.its.mispauth.adapter.OrganisationInfoEntryAdapter;
|
||||
import de.overview.wg.its.mispauth.auxiliary.PreferenceManager;
|
||||
import de.overview.wg.its.mispauth.auxiliary.ReadableError;
|
||||
import de.overview.wg.its.mispauth.cam.DialogFactory;
|
||||
import de.overview.wg.its.mispauth.model.Organisation;
|
||||
import de.overview.wg.its.mispauth.model.StringPair;
|
||||
import de.overview.wg.its.mispauth.model.User;
|
||||
import de.overview.wg.its.mispauth.network.MispRequest;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
@SuppressLint("SetTextI18n")
|
||||
public class CredentialsActivity extends AppCompatActivity implements View.OnClickListener {
|
||||
|
||||
private boolean changesMade;
|
||||
private boolean saveAuthKey;
|
||||
|
||||
private PreferenceManager preferenceManager;
|
||||
|
||||
private TextInputLayout urlLayout, apiLayout;
|
||||
private TextView emptyView;
|
||||
// private ViewGroup organisationView;
|
||||
private ProgressBar progressBar;
|
||||
|
||||
private Organisation myOrganisation;
|
||||
private User myUser;
|
||||
|
||||
private RecyclerView recyclerView;
|
||||
private OrganisationInfoEntryAdapter adapter;
|
||||
private List<StringPair> orgInfoEntries = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_credentials);
|
||||
|
||||
preferenceManager = PreferenceManager.Instance(this);
|
||||
|
||||
initializeViews();
|
||||
loadPreferences();
|
||||
addSaveChangesListener();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
getMenuInflater().inflate(R.menu.menu_credentials, menu);
|
||||
return super.onCreateOptionsMenu(menu);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
|
||||
int id = item.getItemId();
|
||||
|
||||
switch (id) {
|
||||
case android.R.id.home:
|
||||
exitSafely();
|
||||
return true;
|
||||
|
||||
case R.id.load_config:
|
||||
|
||||
// MOTOROLA
|
||||
if (Build.VERSION.SDK_INT <= 25) {
|
||||
urlLayout.getEditText().setText("http://192.168.178.200");
|
||||
apiLayout.getEditText().setText("dcfgDrNy3SyASmo9WRqyJ4LhsN1xWJ7phfTjklFa");
|
||||
} else {
|
||||
urlLayout.getEditText().setText("http://192.168.178.201");
|
||||
apiLayout.getEditText().setText("5BGhMzdHIWvaxyrTUUVNk2NflDPzXJRZQvOa3CE2");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
exitSafely();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
int id = v.getId();
|
||||
|
||||
switch (id) {
|
||||
case R.id.fab_download_own_org_info:
|
||||
downloadOrgInfo();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void initializeViews() {
|
||||
|
||||
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||
setSupportActionBar(toolbar);
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
getSupportActionBar().setDisplayShowHomeEnabled(true);
|
||||
|
||||
progressBar = findViewById(R.id.progressBar);
|
||||
urlLayout = findViewById(R.id.input_layout_server_url);
|
||||
apiLayout = findViewById(R.id.input_layout_api_key);
|
||||
emptyView = findViewById(R.id.empty);
|
||||
// organisationView = findViewById(R.id.myOrganisationView);
|
||||
|
||||
FloatingActionButton fab = findViewById(R.id.fab_download_own_org_info);
|
||||
fab.setOnClickListener(this);
|
||||
|
||||
recyclerView = findViewById(R.id.recyclerView);
|
||||
adapter = new OrganisationInfoEntryAdapter();
|
||||
RecyclerView.LayoutManager manager = new LinearLayoutManager(this);
|
||||
recyclerView.setLayoutManager(manager);
|
||||
recyclerView.setItemAnimator(new DefaultItemAnimator());
|
||||
recyclerView.setAdapter(adapter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads preferences
|
||||
*/
|
||||
private void loadPreferences() {
|
||||
|
||||
saveAuthKey = preferenceManager.saveAuthKeyEnabled();
|
||||
|
||||
urlLayout.getEditText().setText(preferenceManager.getMyServerUrl());
|
||||
apiLayout.getEditText().setText(preferenceManager.getMyServerApiKey());
|
||||
|
||||
myOrganisation = preferenceManager.getMyOrganisation();
|
||||
|
||||
if (myOrganisation == null) {
|
||||
|
||||
emptyView.setVisibility(View.VISIBLE);
|
||||
// organisationView.setVisibility(View.GONE);
|
||||
recyclerView.setVisibility(View.GONE);
|
||||
|
||||
} else {
|
||||
|
||||
emptyView.setVisibility(View.GONE);
|
||||
// organisationView.setVisibility(View.VISIBLE);
|
||||
recyclerView.setVisibility(View.VISIBLE);
|
||||
|
||||
visualizeOrganisation();
|
||||
}
|
||||
}
|
||||
private void savePreferences() {
|
||||
|
||||
preferenceManager.setMyServerUrl(urlLayout.getEditText().getText().toString());
|
||||
preferenceManager.setSaveAuthKeyEnabled(saveAuthKey);
|
||||
|
||||
if (saveAuthKey) {
|
||||
preferenceManager.setMyServerApiKey(apiLayout.getEditText().getText().toString());
|
||||
} else {
|
||||
preferenceManager.setMyServerApiKey("");
|
||||
}
|
||||
|
||||
if (myUser != null) {
|
||||
|
||||
myUser.clearForStorage();
|
||||
preferenceManager.setMyUser(myUser);
|
||||
|
||||
}
|
||||
|
||||
if (myOrganisation != null) {
|
||||
preferenceManager.setMyOrganisation(myOrganisation);
|
||||
}
|
||||
|
||||
changesMade = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether changes were made to the URL or the API Key
|
||||
*/
|
||||
private void addSaveChangesListener() {
|
||||
urlLayout.getEditText().addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
changesMade = true;
|
||||
}
|
||||
});
|
||||
|
||||
apiLayout.getEditText().addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
changesMade = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private boolean validCredentials() {
|
||||
|
||||
boolean inputError = false;
|
||||
|
||||
String url = urlLayout.getEditText().getText().toString();
|
||||
String auth = apiLayout.getEditText().getText().toString();
|
||||
|
||||
if (url.equals("")) {
|
||||
urlLayout.setError(getResources().getString(R.string.error_url_required));
|
||||
inputError = true;
|
||||
}
|
||||
|
||||
if (auth.equals("")) {
|
||||
apiLayout.setError(getResources().getString(R.string.error_api_required));
|
||||
inputError = true;
|
||||
}
|
||||
|
||||
if (inputError) {
|
||||
return false;
|
||||
}
|
||||
|
||||
urlLayout.setError(null);
|
||||
apiLayout.setError(null);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void downloadOrgInfo() {
|
||||
|
||||
if (myOrganisation != null) {
|
||||
DialogInterface.OnClickListener pos = new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
downloadOrgInfo();
|
||||
}
|
||||
};
|
||||
new DialogFactory(this).createOverrideDialog(pos, null).show();
|
||||
}
|
||||
|
||||
if (!validCredentials()) {
|
||||
return;
|
||||
}
|
||||
|
||||
apiLayout.clearFocus();
|
||||
urlLayout.clearFocus();
|
||||
|
||||
progressBar.setVisibility(View.VISIBLE);
|
||||
emptyView.setVisibility(View.GONE);
|
||||
|
||||
final MispRequest mispRequest = MispRequest.Instance(this, false);
|
||||
|
||||
mispRequest.setServerCredentials(urlLayout.getEditText().getText().toString(), apiLayout.getEditText().getText().toString());
|
||||
|
||||
mispRequest.getMyUser(new MispRequest.UserCallback() {
|
||||
@Override
|
||||
public void onResult(JSONObject jsonUser) {
|
||||
try {
|
||||
myUser = new User(jsonUser);
|
||||
} catch (JSONException e) {
|
||||
makeSnackBar("Could not interpret user format");
|
||||
return;
|
||||
}
|
||||
|
||||
mispRequest.getOrganisation(myUser.getId(), new MispRequest.OrganisationCallback() {
|
||||
@Override
|
||||
public void onResult(JSONObject organisationInformation) {
|
||||
try {
|
||||
myOrganisation = new Organisation(organisationInformation);
|
||||
changesMade = true;
|
||||
} catch (JSONException e) {
|
||||
makeSnackBar("Could not interpret organisation format");
|
||||
return;
|
||||
}
|
||||
|
||||
recyclerView.setVisibility(View.VISIBLE);
|
||||
// organisationView.setVisibility(View.VISIBLE);
|
||||
emptyView.setVisibility(View.GONE);
|
||||
|
||||
progressBar.setVisibility(View.GONE);
|
||||
visualizeOrganisation();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(VolleyError volleyError) {
|
||||
makeSnackBar(ReadableError.toReadable(volleyError));
|
||||
progressBar.setVisibility(View.GONE);
|
||||
recyclerView.setVisibility(View.GONE);
|
||||
// organisationView.setVisibility(View.GONE);
|
||||
emptyView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(VolleyError volleyError) {
|
||||
makeSnackBar(ReadableError.toReadable(volleyError));
|
||||
progressBar.setVisibility(View.GONE);
|
||||
recyclerView.setVisibility(View.GONE);
|
||||
// organisationView.setVisibility(View.GONE);
|
||||
emptyView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private void visualizeOrganisation() {
|
||||
|
||||
orgInfoEntries.add(new StringPair("Name", myOrganisation.getName()));
|
||||
// TextView title = organisationView.findViewById(R.id.organisation_title);
|
||||
// TextView title = findViewById(R.id.org_title);
|
||||
// title.setText(myOrganisation.getName());
|
||||
|
||||
orgInfoEntries.add(new StringPair("UUID", myOrganisation.getUuid()));
|
||||
// TextView uuid = organisationView.findViewById(R.id.organisation_uuid);
|
||||
// uuid.setText(myOrganisation.getUuid());
|
||||
|
||||
orgInfoEntries.add(new StringPair("Description", myOrganisation.getDescription()));
|
||||
// TextView description = organisationView.findViewById(R.id.organisation_description);
|
||||
// description.setText(myOrganisation.getDescription());
|
||||
|
||||
orgInfoEntries.add(new StringPair("Nationality", myOrganisation.getNationality()));
|
||||
// TextView nationality = organisationView.findViewById(R.id.organisation_nationality);
|
||||
// nationality.setText(myOrganisation.getNationality());
|
||||
|
||||
orgInfoEntries.add(new StringPair("Sector", myOrganisation.getSector()));
|
||||
// TextView sector = findViewById(R.id.organisation_sector);
|
||||
// sector.setText(myOrganisation.getSector());
|
||||
|
||||
orgInfoEntries.add(new StringPair("User Count", "" + myOrganisation.getUserCount()));
|
||||
// TextView users = findViewById(R.id.organisation_user_count);
|
||||
// users.setText("" + myOrganisation.getUserCount());
|
||||
|
||||
adapter.setList(orgInfoEntries);
|
||||
}
|
||||
|
||||
private void exitSafely() {
|
||||
|
||||
if (changesMade || !preferenceManager.saveAuthKeyEnabledExists()) {
|
||||
saveDialog(new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
savePreferences();
|
||||
finish();
|
||||
}
|
||||
}, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
finish();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
private void makeSnackBar(String message) {
|
||||
Snackbar.make(findViewById(R.id.coordinator), message, Snackbar.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
private void saveDialog(DialogInterface.OnClickListener positive, DialogInterface.OnClickListener negative) {
|
||||
AlertDialog.Builder adb = new AlertDialog.Builder(this);
|
||||
|
||||
adb.setTitle(getResources().getString(R.string.unsaved_changes));
|
||||
adb.setMessage("\n" + getResources().getString(R.string.save_changes));
|
||||
|
||||
@SuppressLint("InflateParams")
|
||||
View checkBoxView = getLayoutInflater().inflate(R.layout.dialog_save_authkey, null);
|
||||
CheckBox c = checkBoxView.findViewById(R.id.checkbox);
|
||||
c.setChecked(saveAuthKey);
|
||||
c.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
||||
@Override
|
||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||
saveAuthKey = isChecked;
|
||||
}
|
||||
});
|
||||
|
||||
adb.setView(checkBoxView);
|
||||
|
||||
adb.setPositiveButton(getResources().getString(R.string.save), positive);
|
||||
adb.setNegativeButton(getResources().getString(R.string.discard), negative);
|
||||
|
||||
Dialog d = adb.create();
|
||||
d.setCancelable(false);
|
||||
d.getWindow().setWindowAnimations(R.style.DialogAnimation);
|
||||
d.show();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
package de.overview.wg.its.mispauth.adapter;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.util.Pair;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
import de.overview.wg.its.mispauth.R;
|
||||
import de.overview.wg.its.mispauth.model.StringPair;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class OrganisationInfoEntryAdapter extends RecyclerView.Adapter<OrganisationInfoEntryAdapter.MyViewHolder> {
|
||||
|
||||
private List<StringPair> list = new ArrayList<>();
|
||||
|
||||
class MyViewHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
TextView title, value;
|
||||
|
||||
private MyViewHolder(View view) {
|
||||
super(view);
|
||||
|
||||
this.title = view.findViewById(R.id.title);
|
||||
this.value = view.findViewById(R.id.value);
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View row = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_org_info_entry, parent, false);
|
||||
return new OrganisationInfoEntryAdapter.MyViewHolder(row);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
|
||||
holder.title.setText(list.get(position).key);
|
||||
holder.value.setText(list.get(position).value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return list.size();
|
||||
}
|
||||
|
||||
public void setList(List<StringPair> list) {
|
||||
this.list = list;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
package de.overview.wg.its.mispauth.adapter;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
import de.overview.wg.its.mispauth.R;
|
||||
import de.overview.wg.its.mispauth.model.SyncedPartner;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class SyncedPartnerAdapter extends RecyclerView.Adapter<SyncedPartnerAdapter.MyViewHolder> {
|
||||
|
||||
private List<SyncedPartner> syncedPartnerList;
|
||||
|
||||
class MyViewHolder extends RecyclerView.ViewHolder {
|
||||
TextView title, dateAdded, url;
|
||||
|
||||
MyViewHolder(View view) {
|
||||
super(view);
|
||||
title = view.findViewById(R.id.title);
|
||||
dateAdded = view.findViewById(R.id.dateSynced);
|
||||
url = view.findViewById(R.id.url);
|
||||
}
|
||||
}
|
||||
|
||||
public SyncedPartnerAdapter(List<SyncedPartner> syncedPartnerList) {
|
||||
this.syncedPartnerList = syncedPartnerList;
|
||||
}
|
||||
|
||||
public void setSyncedPartnerList(List<SyncedPartner> syncedPartnerList) {
|
||||
this.syncedPartnerList = syncedPartnerList;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_synced_organisation, parent, false);
|
||||
return new MyViewHolder(itemView);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
|
||||
SyncedPartner syncedPartner = syncedPartnerList.get(position);
|
||||
|
||||
holder.title.setText(syncedPartner.getName());
|
||||
holder.url.setText(syncedPartner.getUrl());
|
||||
holder.dateAdded.setText(syncedPartner.getSyncDate());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return syncedPartnerList.size();
|
||||
}
|
||||
}
|
|
@ -1,929 +0,0 @@
|
|||
package de.overview.wg.its.mispauth.cam;
|
||||
|
||||
import android.Manifest;
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.*;
|
||||
import android.hardware.camera2.CameraAccessException;
|
||||
import android.hardware.camera2.CameraCaptureSession;
|
||||
import android.hardware.camera2.CameraCharacteristics;
|
||||
import android.hardware.camera2.CameraDevice;
|
||||
import android.hardware.camera2.CameraManager;
|
||||
import android.hardware.camera2.CaptureRequest;
|
||||
import android.hardware.camera2.params.StreamConfigurationMap;
|
||||
import android.media.Image;
|
||||
import android.media.ImageReader;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.renderscript.*;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.app.ActivityCompat;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.util.Log;
|
||||
import android.util.Size;
|
||||
import android.util.SparseArray;
|
||||
import android.util.SparseIntArray;
|
||||
import android.view.*;
|
||||
import android.widget.Toast;
|
||||
import com.google.android.gms.vision.Frame;
|
||||
import com.google.android.gms.vision.barcode.Barcode;
|
||||
import com.google.android.gms.vision.barcode.BarcodeDetector;
|
||||
import de.overview.wg.its.mispauth.SyncActivity;
|
||||
import de.overview.wg.its.mispauth.R;
|
||||
import de.overview.wg.its.mispauth.auxiliary.AESSecurity;
|
||||
import de.overview.wg.its.mispauth.model.PublicKeyQr;
|
||||
import de.overview.wg.its.mispauth.model.SyncInformationQr;
|
||||
import org.json.JSONException;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Semaphore;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class CameraFragment extends Fragment implements ActivityCompat.OnRequestPermissionsResultCallback {
|
||||
|
||||
private SyncActivity parentActivity;
|
||||
|
||||
@Override
|
||||
public void onAttach(Context context) {
|
||||
super.onAttach(context);
|
||||
parentActivity = (SyncActivity) context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Conversion from screen rotation to JPEG orientation.
|
||||
*/
|
||||
private static final SparseIntArray ORIENTATIONS = new SparseIntArray();
|
||||
private static final int REQUEST_CAMERA_PERMISSION = 1;
|
||||
private static final String FRAGMENT_DIALOG = "dialog";
|
||||
|
||||
static {
|
||||
ORIENTATIONS.append(Surface.ROTATION_0, 90);
|
||||
ORIENTATIONS.append(Surface.ROTATION_90, 0);
|
||||
ORIENTATIONS.append(Surface.ROTATION_180, 270);
|
||||
ORIENTATIONS.append(Surface.ROTATION_270, 180);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tag for the {@link Log}.
|
||||
*/
|
||||
private static final String TAG = "MISP_LOGGING";
|
||||
|
||||
/**
|
||||
* Max preview width that is guaranteed by Camera2 API
|
||||
*/
|
||||
private static final int MAX_PREVIEW_WIDTH = 1920;
|
||||
|
||||
/**
|
||||
* Max preview height that is guaranteed by Camera2 API
|
||||
*/
|
||||
private static final int MAX_PREVIEW_HEIGHT = 1080;
|
||||
|
||||
/**
|
||||
* {@link TextureView.SurfaceTextureListener} handles several lifecycle events on a
|
||||
* {@link TextureView}.
|
||||
*/
|
||||
private final TextureView.SurfaceTextureListener mSurfaceTextureListener = new TextureView.SurfaceTextureListener() {
|
||||
|
||||
@Override
|
||||
public void onSurfaceTextureAvailable(SurfaceTexture texture, int width, int height) {
|
||||
openCamera(width, height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSurfaceTextureSizeChanged(SurfaceTexture texture, int width, int height) {
|
||||
configureTransform(width, height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onSurfaceTextureDestroyed(SurfaceTexture texture) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSurfaceTextureUpdated(SurfaceTexture texture) {
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* ID of the current {@link CameraDevice}.
|
||||
*/
|
||||
private String mCameraId;
|
||||
|
||||
/**
|
||||
* An {@link AutoFitTextureView} for camera preview.
|
||||
*/
|
||||
private AutoFitTextureView mTextureView;
|
||||
|
||||
/**
|
||||
* A {@link CameraCaptureSession } for camera preview.
|
||||
*/
|
||||
private CameraCaptureSession mCaptureSession;
|
||||
|
||||
/**
|
||||
* A reference to the opened {@link CameraDevice}.
|
||||
*/
|
||||
private CameraDevice mCameraDevice;
|
||||
|
||||
/**
|
||||
* The {@link android.util.Size} of camera preview.
|
||||
*/
|
||||
private Size mPreviewSize;
|
||||
|
||||
/**
|
||||
* {@link CameraDevice.StateCallback} is called when {@link CameraDevice} changes its state.
|
||||
*/
|
||||
private final CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() {
|
||||
|
||||
@Override
|
||||
public void onOpened(@NonNull CameraDevice cameraDevice) {
|
||||
// This method is called when the camera is opened. We start camera preview here.
|
||||
mCameraOpenCloseLock.release();
|
||||
mCameraDevice = cameraDevice;
|
||||
createCameraPreviewSession();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisconnected(@NonNull CameraDevice cameraDevice) {
|
||||
mCameraOpenCloseLock.release();
|
||||
cameraDevice.close();
|
||||
mCameraDevice = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(@NonNull CameraDevice cameraDevice, int error) {
|
||||
mCameraOpenCloseLock.release();
|
||||
cameraDevice.close();
|
||||
mCameraDevice = null;
|
||||
Activity activity = getActivity();
|
||||
if (null != activity) {
|
||||
activity.finish();
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* An additional thread for running tasks that shouldn't block the UI.
|
||||
*/
|
||||
private HandlerThread mBackgroundThread;
|
||||
|
||||
/**
|
||||
* A {@link Handler} for running tasks in the background.
|
||||
*/
|
||||
private Handler mBackgroundHandler;
|
||||
|
||||
/**
|
||||
* An {@link ImageReader} that handles still image capture.
|
||||
*/
|
||||
private ImageReader mImageReader;
|
||||
|
||||
/**
|
||||
* This a callback object for the {@link ImageReader}. "onImageAvailable" will be called when a
|
||||
* still image is ready to be saved.
|
||||
*/
|
||||
private final ImageReader.OnImageAvailableListener mOnImageAvailableListener = new ImageReader.OnImageAvailableListener() {
|
||||
@Override
|
||||
public void onImageAvailable(ImageReader reader) {
|
||||
|
||||
Image image = reader.acquireNextImage();
|
||||
Bitmap bitmap = YUV2Bitmap(image);
|
||||
|
||||
// final Bitmap bitmap = invertBitmap(YUV2Bitmap(image));
|
||||
|
||||
if (bitmap != null) {
|
||||
|
||||
if (readQrEnabled) {
|
||||
|
||||
Frame frame = new Frame.Builder().setBitmap(bitmap).build();
|
||||
SparseArray<Barcode> barcodes = barcodeDetector.detect(frame);
|
||||
|
||||
if (barcodes.size() > 0) {
|
||||
if (currentScanMode == ScanMode.PUBLIC_KEY) {
|
||||
returnPublicKey(barcodes.valueAt(0).rawValue);
|
||||
} else {
|
||||
returnSyncInformation(barcodes.valueAt(0).rawValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (image != null) {
|
||||
image.close();
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* {@link CaptureRequest.Builder} for the camera preview
|
||||
*/
|
||||
private CaptureRequest.Builder mPreviewRequestBuilder;
|
||||
|
||||
/**
|
||||
* {@link CaptureRequest} generated by {@link #mPreviewRequestBuilder}
|
||||
*/
|
||||
private CaptureRequest mPreviewRequest;
|
||||
|
||||
/**
|
||||
* A {@link Semaphore} to prevent the app from exiting before closing the camera.
|
||||
*/
|
||||
private Semaphore mCameraOpenCloseLock = new Semaphore(1);
|
||||
|
||||
/**
|
||||
* Shows a {@link Toast} on the UI thread.
|
||||
*
|
||||
* @param text The message to show
|
||||
*/
|
||||
private void showToast(final String text) {
|
||||
final Activity activity = getActivity();
|
||||
if (activity != null) {
|
||||
activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Toast.makeText(activity, text, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given {@code choices} of {@code Size}s supported by a camera, choose the smallest one that
|
||||
* is at least as large as the respective texture view size, and that is at most as large as the
|
||||
* respective max size, and whose aspect ratio matches with the specified value. If such size
|
||||
* doesn't exist, choose the largest one that is at most as large as the respective max size,
|
||||
* and whose aspect ratio matches with the specified value.
|
||||
*
|
||||
* @param choices The list of sizes that the camera supports for the intended output
|
||||
* class
|
||||
* @param textureViewWidth The width of the texture view relative to sensor coordinate
|
||||
* @param textureViewHeight The height of the texture view relative to sensor coordinate
|
||||
* @param maxWidth The maximum width that can be chosen
|
||||
* @param maxHeight The maximum height that can be chosen
|
||||
* @param aspectRatio The aspect ratio
|
||||
* @return The optimal {@code Size}, or an arbitrary one if none were big enough
|
||||
*/
|
||||
private static Size chooseOptimalSize(Size[] choices, int textureViewWidth, int textureViewHeight, int maxWidth, int maxHeight, Size aspectRatio) {
|
||||
|
||||
// Collect the supported resolutions that are at least as big as the preview Surface
|
||||
List<Size> bigEnough = new ArrayList<>();
|
||||
// Collect the supported resolutions that are smaller than the preview Surface
|
||||
List<Size> notBigEnough = new ArrayList<>();
|
||||
int w = aspectRatio.getWidth();
|
||||
int h = aspectRatio.getHeight();
|
||||
for (Size option : choices) {
|
||||
if (option.getWidth() <= maxWidth && option.getHeight() <= maxHeight && option.getHeight() == option.getWidth() * h / w) {
|
||||
if (option.getWidth() >= textureViewWidth && option.getHeight() >= textureViewHeight) {
|
||||
bigEnough.add(option);
|
||||
} else {
|
||||
notBigEnough.add(option);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Pick the smallest of those big enough. If there is no one big enough, pick the
|
||||
// largest of those not big enough.
|
||||
if (bigEnough.size() > 0) {
|
||||
return Collections.min(bigEnough, new CompareSizesByArea());
|
||||
} else if (notBigEnough.size() > 0) {
|
||||
return Collections.max(notBigEnough, new CompareSizesByArea());
|
||||
} else {
|
||||
Log.e(TAG, "Couldn't find any suitable preview size");
|
||||
return choices[0];
|
||||
}
|
||||
}
|
||||
|
||||
public static CameraFragment newInstance(ScanMode mode) {
|
||||
|
||||
CameraFragment f = new CameraFragment();
|
||||
|
||||
Bundle args = new Bundle();
|
||||
args.putSerializable(BUNDLE_MODE_KEY, mode);
|
||||
f.setArguments(args);
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
|
||||
View v = inflater.inflate(R.layout.fragment_camera, container, false);
|
||||
|
||||
initRenderScript();
|
||||
|
||||
setUpBarcodeDetector();
|
||||
checkBundle();
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(final View view, Bundle savedInstanceState) {
|
||||
mTextureView = view.findViewById(R.id.texture);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
startBackgroundThread();
|
||||
|
||||
// When the screen is turned off and turned back on, the SurfaceTexture is already
|
||||
// available, and "onSurfaceTextureAvailable" will not be called. In that case, we can open
|
||||
// a camera and start preview from here (otherwise, we wait until the surface is ready in
|
||||
// the SurfaceTextureListener).
|
||||
if (mTextureView.isAvailable()) {
|
||||
openCamera(mTextureView.getWidth(), mTextureView.getHeight());
|
||||
} else {
|
||||
mTextureView.setSurfaceTextureListener(mSurfaceTextureListener);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
closeCamera();
|
||||
stopBackgroundThread();
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
private void requestCameraPermission() {
|
||||
if (shouldShowRequestPermissionRationale(Manifest.permission.CAMERA)) {
|
||||
new ConfirmationDialog().show(getChildFragmentManager(), FRAGMENT_DIALOG);
|
||||
} else {
|
||||
requestPermissions(new String[]{Manifest.permission.CAMERA}, REQUEST_CAMERA_PERMISSION);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||
if (requestCode == REQUEST_CAMERA_PERMISSION) {
|
||||
if (grantResults.length != 1 || grantResults[0] != PackageManager.PERMISSION_GRANTED) {
|
||||
ErrorDialog.newInstance("REQUEST PERMISSION").show(getChildFragmentManager(), FRAGMENT_DIALOG);
|
||||
}
|
||||
} else {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up member variables related to camera.
|
||||
*
|
||||
* @param width The width of available size for camera preview
|
||||
* @param height The height of available size for camera preview
|
||||
*/
|
||||
@SuppressWarnings("SuspiciousNameCombination")
|
||||
private void setUpCameraOutputs(int width, int height) {
|
||||
Activity activity = getActivity();
|
||||
CameraManager manager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);
|
||||
|
||||
try {
|
||||
for (String cameraId : manager.getCameraIdList()) {
|
||||
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
|
||||
|
||||
// We don't use a front facing camera in this sample.
|
||||
Integer facing = characteristics.get(CameraCharacteristics.LENS_FACING);
|
||||
if (facing != null && facing == CameraCharacteristics.LENS_FACING_FRONT) {
|
||||
continue;
|
||||
}
|
||||
|
||||
StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
|
||||
if (map == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// For still image captures, we use the largest available size.
|
||||
Size largest = Collections.max(Arrays.asList(map.getOutputSizes(ImageFormat.YUV_420_888)), new CompareSizesByArea());
|
||||
|
||||
mImageReader = ImageReader.newInstance(largest.getWidth() / 16, largest.getHeight() / 16, ImageFormat.YUV_420_888, 2);
|
||||
mImageReader.setOnImageAvailableListener(mOnImageAvailableListener, mBackgroundHandler);
|
||||
|
||||
// Find out if we need to swap dimension to get the preview size relative to sensor coordinate.
|
||||
int displayRotation = activity.getWindowManager().getDefaultDisplay().getRotation();
|
||||
//noinspection ConstantConditions
|
||||
int mSensorOrientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
|
||||
boolean swappedDimensions = false;
|
||||
switch (displayRotation) {
|
||||
case Surface.ROTATION_0:
|
||||
case Surface.ROTATION_180:
|
||||
if (mSensorOrientation == 90 || mSensorOrientation == 270) {
|
||||
swappedDimensions = true;
|
||||
}
|
||||
break;
|
||||
case Surface.ROTATION_90:
|
||||
case Surface.ROTATION_270:
|
||||
if (mSensorOrientation == 0 || mSensorOrientation == 180) {
|
||||
swappedDimensions = true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Log.e(TAG, "Display rotation is invalid: " + displayRotation);
|
||||
}
|
||||
|
||||
Point displaySize = new Point();
|
||||
activity.getWindowManager().getDefaultDisplay().getSize(displaySize);
|
||||
|
||||
int rotatedPreviewWidth = width;
|
||||
int rotatedPreviewHeight = height;
|
||||
int maxPreviewWidth = displaySize.x;
|
||||
int maxPreviewHeight = displaySize.y;
|
||||
|
||||
if (swappedDimensions) {
|
||||
rotatedPreviewWidth = height;
|
||||
rotatedPreviewHeight = width;
|
||||
maxPreviewWidth = displaySize.y;
|
||||
maxPreviewHeight = displaySize.x;
|
||||
}
|
||||
|
||||
if (maxPreviewWidth > MAX_PREVIEW_WIDTH) {
|
||||
maxPreviewWidth = MAX_PREVIEW_WIDTH;
|
||||
}
|
||||
|
||||
if (maxPreviewHeight > MAX_PREVIEW_HEIGHT) {
|
||||
maxPreviewHeight = MAX_PREVIEW_HEIGHT;
|
||||
}
|
||||
|
||||
// Danger, W.R.! Attempting to use too large a preview size could exceed the camera
|
||||
// bus' bandwidth limitation, resulting in gorgeous previews but the storage of
|
||||
// garbage capture data.
|
||||
mPreviewSize = chooseOptimalSize(map.getOutputSizes(SurfaceTexture.class),
|
||||
rotatedPreviewWidth, rotatedPreviewHeight, maxPreviewWidth,
|
||||
maxPreviewHeight, largest);
|
||||
|
||||
// We fit the aspect ratio of TextureView to the size of preview we picked.
|
||||
int orientation = getResources().getConfiguration().orientation;
|
||||
if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
|
||||
mTextureView.setAspectRatio(mPreviewSize.getWidth(), mPreviewSize.getHeight());
|
||||
} else {
|
||||
mTextureView.setAspectRatio(mPreviewSize.getHeight(), mPreviewSize.getWidth());
|
||||
}
|
||||
|
||||
mCameraId = cameraId;
|
||||
return;
|
||||
}
|
||||
} catch (CameraAccessException e) {
|
||||
e.printStackTrace();
|
||||
} catch (NullPointerException e) {
|
||||
// Currently an NPE is thrown when the Camera2API is used but not supported on the
|
||||
// device this code runs.
|
||||
ErrorDialog.newInstance("CAMERA ERROR").show(getChildFragmentManager(), FRAGMENT_DIALOG);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the camera specified by {@link CameraFragment#mCameraId}.
|
||||
*/
|
||||
private void openCamera(int width, int height) {
|
||||
|
||||
if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
|
||||
requestCameraPermission();
|
||||
return;
|
||||
}
|
||||
|
||||
setUpCameraOutputs(width, height);
|
||||
configureTransform(width, height);
|
||||
|
||||
Activity activity = getActivity();
|
||||
CameraManager manager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);
|
||||
|
||||
try {
|
||||
|
||||
if (!mCameraOpenCloseLock.tryAcquire(2500, TimeUnit.MILLISECONDS)) {
|
||||
throw new RuntimeException("Time out waiting to lock camera opening.");
|
||||
}
|
||||
|
||||
manager.openCamera(mCameraId, mStateCallback, mBackgroundHandler);
|
||||
} catch (CameraAccessException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException("Interrupted while trying to lock camera opening.", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the current {@link CameraDevice}.
|
||||
*/
|
||||
private void closeCamera() {
|
||||
try {
|
||||
mCameraOpenCloseLock.acquire();
|
||||
|
||||
if (null != mCaptureSession) {
|
||||
mCaptureSession.close();
|
||||
mCaptureSession = null;
|
||||
}
|
||||
|
||||
if (null != mCameraDevice) {
|
||||
mCameraDevice.close();
|
||||
mCameraDevice = null;
|
||||
}
|
||||
|
||||
if (null != mImageReader) {
|
||||
mImageReader.close();
|
||||
mImageReader = null;
|
||||
}
|
||||
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException("Interrupted while trying to lock camera closing.", e);
|
||||
} finally {
|
||||
mCameraOpenCloseLock.release();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a background thread and its {@link Handler}.
|
||||
*/
|
||||
private void startBackgroundThread() {
|
||||
mBackgroundThread = new HandlerThread("CameraBackground");
|
||||
mBackgroundThread.start();
|
||||
mBackgroundHandler = new Handler(mBackgroundThread.getLooper());
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops the background thread and its {@link Handler}.
|
||||
*/
|
||||
private void stopBackgroundThread() {
|
||||
mBackgroundThread.quitSafely();
|
||||
try {
|
||||
mBackgroundThread.join();
|
||||
mBackgroundThread = null;
|
||||
mBackgroundHandler = null;
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link CameraCaptureSession} for camera preview.
|
||||
*/
|
||||
private void createCameraPreviewSession() {
|
||||
try {
|
||||
SurfaceTexture texture = mTextureView.getSurfaceTexture();
|
||||
assert texture != null;
|
||||
|
||||
// We configure the size of default buffer to be the size of camera preview we want.
|
||||
texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
|
||||
|
||||
// This is the output Surface we need to start preview.
|
||||
Surface surface = new Surface(texture);
|
||||
Surface mImageSurface = mImageReader.getSurface();
|
||||
|
||||
// We set up a CaptureRequest.Builder with the output Surface.
|
||||
mPreviewRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
|
||||
mPreviewRequestBuilder.addTarget(surface);
|
||||
mPreviewRequestBuilder.addTarget(mImageSurface);
|
||||
|
||||
// Here, we create a CameraCaptureSession for camera preview.
|
||||
mCameraDevice.createCaptureSession(Arrays.asList(surface, mImageReader.getSurface()),
|
||||
new CameraCaptureSession.StateCallback() {
|
||||
|
||||
@Override
|
||||
public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) {
|
||||
// The camera is already closed
|
||||
if (null == mCameraDevice) {
|
||||
return;
|
||||
}
|
||||
|
||||
// When the session is ready, we start displaying the preview.
|
||||
mCaptureSession = cameraCaptureSession;
|
||||
try {
|
||||
// Auto focus should be continuous for camera preview.
|
||||
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
|
||||
|
||||
// Finally, we start displaying the camera preview.
|
||||
mPreviewRequest = mPreviewRequestBuilder.build();
|
||||
mCaptureSession.setRepeatingRequest(mPreviewRequest, null, mBackgroundHandler);
|
||||
} catch (CameraAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) {
|
||||
showToast("Failed");
|
||||
}
|
||||
}, null
|
||||
);
|
||||
} catch (CameraAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the necessary {@link android.graphics.Matrix} transformation to `mTextureView`.
|
||||
* This method should be called after the camera preview size is determined in
|
||||
* setUpCameraOutputs and also the size of `mTextureView` is fixed.
|
||||
*
|
||||
* @param viewWidth The width of `mTextureView`
|
||||
* @param viewHeight The height of `mTextureView`
|
||||
*/
|
||||
private void configureTransform(int viewWidth, int viewHeight) {
|
||||
Activity activity = getActivity();
|
||||
|
||||
if (null == mTextureView || null == mPreviewSize || null == activity) {
|
||||
return;
|
||||
}
|
||||
|
||||
int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
|
||||
Matrix matrix = new Matrix();
|
||||
RectF viewRect = new RectF(0, 0, viewWidth, viewHeight);
|
||||
RectF bufferRect = new RectF(0, 0, mPreviewSize.getHeight(), mPreviewSize.getWidth());
|
||||
float centerX = viewRect.centerX();
|
||||
float centerY = viewRect.centerY();
|
||||
if (Surface.ROTATION_90 == rotation || Surface.ROTATION_270 == rotation) {
|
||||
bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY());
|
||||
matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL);
|
||||
float scale = Math.max(
|
||||
(float) viewHeight / mPreviewSize.getHeight(),
|
||||
(float) viewWidth / mPreviewSize.getWidth());
|
||||
matrix.postScale(scale, scale, centerX, centerY);
|
||||
matrix.postRotate(90 * (rotation - 2), centerX, centerY);
|
||||
} else if (Surface.ROTATION_180 == rotation) {
|
||||
matrix.postRotate(180, centerX, centerY);
|
||||
}
|
||||
mTextureView.setTransform(matrix);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two {@code Size}s based on their areas.
|
||||
*/
|
||||
static class CompareSizesByArea implements Comparator<Size> {
|
||||
|
||||
@Override
|
||||
public int compare(Size lhs, Size rhs) {
|
||||
// We cast here to ensure the multiplications won't overflow
|
||||
return Long.signum((long) lhs.getWidth() * lhs.getHeight() - (long) rhs.getWidth() * rhs.getHeight());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Shows an error message dialog.
|
||||
*/
|
||||
public static class ErrorDialog extends DialogFragment {
|
||||
|
||||
private static final String ARG_MESSAGE = "message";
|
||||
|
||||
public static ErrorDialog newInstance(String message) {
|
||||
ErrorDialog dialog = new ErrorDialog();
|
||||
Bundle args = new Bundle();
|
||||
args.putString(ARG_MESSAGE, message);
|
||||
dialog.setArguments(args);
|
||||
return dialog;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
final Activity activity = getActivity();
|
||||
return new AlertDialog.Builder(activity)
|
||||
.setMessage(getArguments().getString(ARG_MESSAGE))
|
||||
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialogInterface, int i) {
|
||||
activity.finish();
|
||||
}
|
||||
})
|
||||
.create();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows OK/Cancel confirmation dialog about camera permission.
|
||||
*/
|
||||
public static class ConfirmationDialog extends DialogFragment {
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
final Fragment parent = getParentFragment();
|
||||
return new AlertDialog.Builder(getActivity())
|
||||
.setMessage("REQUEST PERMISSION")
|
||||
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
parent.requestPermissions(new String[]{Manifest.permission.CAMERA}, REQUEST_CAMERA_PERMISSION);
|
||||
}
|
||||
})
|
||||
.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
Activity activity = parent.getActivity();
|
||||
if (activity != null) {
|
||||
activity.finish();
|
||||
}
|
||||
}
|
||||
})
|
||||
.create();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static final String BUNDLE_MODE_KEY = "mode";
|
||||
|
||||
public enum ScanMode {
|
||||
PUBLIC_KEY,
|
||||
INFO
|
||||
}
|
||||
|
||||
private ScanMode currentScanMode;
|
||||
private boolean readQrEnabled = true;
|
||||
private BarcodeDetector barcodeDetector;
|
||||
|
||||
private RenderScript renderScript;
|
||||
private static final Matrix4f TRANSFORMATION_MATRIX = new Matrix4f(new float[]{
|
||||
-0.33f, -0.33f, -0.33f, 1.0f,
|
||||
-0.59f, -0.59f, -0.59f, 1.0f,
|
||||
-0.11f, -0.11f, -0.11f, 1.0f,
|
||||
1.0f, 1.0f, 1.0f, 1.0f
|
||||
});
|
||||
|
||||
private void initRenderScript() {
|
||||
renderScript = RenderScript.create(getActivity());
|
||||
}
|
||||
|
||||
private Bitmap YUV2Bitmap(Image image) {
|
||||
|
||||
if (image == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ScriptIntrinsicYuvToRGB yuvToRgbIntrinsic = ScriptIntrinsicYuvToRGB.create(renderScript, Element.U8_4(renderScript));
|
||||
|
||||
int W = image.getWidth();
|
||||
int H = image.getHeight();
|
||||
|
||||
Image.Plane Y = image.getPlanes()[0];
|
||||
Image.Plane U = image.getPlanes()[1];
|
||||
Image.Plane V = image.getPlanes()[2];
|
||||
|
||||
int Yb = Y.getBuffer().remaining();
|
||||
int Ub = U.getBuffer().remaining();
|
||||
int Vb = V.getBuffer().remaining();
|
||||
|
||||
byte[] data = new byte[Yb + Ub + Vb];
|
||||
|
||||
Y.getBuffer().get(data, 0, Yb);
|
||||
V.getBuffer().get(data, Yb, Vb);
|
||||
U.getBuffer().get(data, Yb + Vb, Ub);
|
||||
|
||||
Type.Builder yuvType = new Type.Builder(renderScript, Element.U8(renderScript)).setX(data.length);
|
||||
Allocation in = Allocation.createTyped(renderScript, yuvType.create(), Allocation.USAGE_SCRIPT);
|
||||
|
||||
Type.Builder rgbaType = new Type.Builder(renderScript, Element.RGBA_8888(renderScript)).setX(W).setY(H);
|
||||
Allocation out = Allocation.createTyped(renderScript, rgbaType.create(), Allocation.USAGE_SCRIPT);
|
||||
|
||||
final Bitmap bmpout = Bitmap.createBitmap(W, H, Bitmap.Config.ARGB_8888);
|
||||
|
||||
in.copyFromUnchecked(data);
|
||||
|
||||
yuvToRgbIntrinsic.setInput(in);
|
||||
yuvToRgbIntrinsic.forEach(out);
|
||||
|
||||
out.copyTo(bmpout);
|
||||
image.close();
|
||||
|
||||
return bmpout;
|
||||
}
|
||||
|
||||
private Bitmap invertBitmap(Bitmap source) {
|
||||
|
||||
final Bitmap result = source.copy(source.getConfig(), true);
|
||||
Allocation input = Allocation.createFromBitmap(renderScript, source, Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT);
|
||||
Allocation output = Allocation.createTyped(renderScript, input.getType());
|
||||
|
||||
final ScriptIntrinsicColorMatrix inverter = ScriptIntrinsicColorMatrix.create(renderScript);
|
||||
inverter.setColorMatrix(TRANSFORMATION_MATRIX);
|
||||
inverter.forEach(input, output);
|
||||
output.copyTo(result);
|
||||
|
||||
source.recycle();
|
||||
renderScript.destroy();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void setReadQrEnabled(boolean enabled) {
|
||||
readQrEnabled = enabled;
|
||||
}
|
||||
|
||||
private void checkBundle() {
|
||||
Bundle args = getArguments();
|
||||
|
||||
if (args != null) {
|
||||
currentScanMode = (ScanMode) args.getSerializable(BUNDLE_MODE_KEY);
|
||||
}
|
||||
}
|
||||
|
||||
private void returnPublicKey(String qrData) {
|
||||
|
||||
setReadQrEnabled(false);
|
||||
|
||||
try {
|
||||
final PublicKeyQr pkqr = new PublicKeyQr(qrData);
|
||||
// parentActivity.qrVisible(false, 300);
|
||||
|
||||
DialogInterface.OnClickListener positive = new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
|
||||
parentActivity.onPublicKeyResult(pkqr);
|
||||
// parentActivity.qrVisible(true, 800);
|
||||
|
||||
closeCamera();
|
||||
|
||||
parentActivity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mTextureView.setVisibility(View.GONE);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
DialogInterface.OnClickListener negative = new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
// parentActivity.qrVisible(true, 800);
|
||||
setReadQrEnabled(true);
|
||||
}
|
||||
};
|
||||
|
||||
DialogFactory diaFac = new DialogFactory(parentActivity);
|
||||
diaFac.createKeyDialog(pkqr, positive, negative).show();
|
||||
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void returnSyncInformation(String qrData) {
|
||||
|
||||
setReadQrEnabled(false);
|
||||
|
||||
AESSecurity aesSecurity = AESSecurity.getInstance();
|
||||
String decryptedQrData = aesSecurity.decrypt(qrData);
|
||||
|
||||
final SyncInformationQr siqr;
|
||||
|
||||
try {
|
||||
siqr = new SyncInformationQr(decryptedQrData);
|
||||
|
||||
DialogInterface.OnClickListener positive = new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
parentActivity.onSyncInfoResult(siqr);
|
||||
|
||||
closeCamera();
|
||||
|
||||
parentActivity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mTextureView.setVisibility(View.GONE);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
DialogInterface.OnClickListener negative = new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
setReadQrEnabled(true);
|
||||
}
|
||||
};
|
||||
|
||||
DialogFactory diaFac = new DialogFactory(parentActivity);
|
||||
diaFac.createInformationDialog(siqr, positive, negative).show();
|
||||
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void setUpBarcodeDetector() {
|
||||
barcodeDetector = new BarcodeDetector.Builder(getActivity())
|
||||
.setBarcodeFormats(Barcode.QR_CODE)
|
||||
.build();
|
||||
|
||||
if (!barcodeDetector.isOperational()) {
|
||||
Toast.makeText(getActivity(), "Could not setup QR-Code scanner!", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,106 +0,0 @@
|
|||
package de.overview.wg.its.mispauth.cam;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.content.*;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
import de.overview.wg.its.mispauth.R;
|
||||
import de.overview.wg.its.mispauth.model.PublicKeyQr;
|
||||
import de.overview.wg.its.mispauth.model.SyncInformationQr;
|
||||
|
||||
public class DialogFactory {
|
||||
|
||||
private Context context;
|
||||
|
||||
private AlertDialog.Builder adb;
|
||||
private LayoutInflater inflater;
|
||||
|
||||
|
||||
public DialogFactory(Context context) {
|
||||
this.context = context;
|
||||
adb = new AlertDialog.Builder(context);
|
||||
inflater = LayoutInflater.from(context);
|
||||
}
|
||||
|
||||
|
||||
public Dialog createKeyDialog(PublicKeyQr pkqr,
|
||||
DialogInterface.OnClickListener positiveListener,
|
||||
DialogInterface.OnClickListener negativeListener) {
|
||||
|
||||
View title = inflater.inflate(R.layout.dialog_public_key, null);
|
||||
adb.setCustomTitle(title);
|
||||
|
||||
adb.setMessage("\nOrganisation: " + pkqr.getOrganisation() + "\nEmail: " + pkqr.getEmail());
|
||||
|
||||
adb.setPositiveButton(context.getResources().getString(R.string.accept), positiveListener);
|
||||
adb.setNegativeButton(context.getResources().getString(R.string.reject), negativeListener);
|
||||
|
||||
adb.setCancelable(false);
|
||||
|
||||
Dialog d = adb.create();
|
||||
d.getWindow().setWindowAnimations(R.style.DialogAnimation);
|
||||
d.getWindow().setDimAmount(0.8f);
|
||||
return d;
|
||||
}
|
||||
|
||||
|
||||
public Dialog createInformationDialog(SyncInformationQr siqr,
|
||||
DialogInterface.OnClickListener positiv,
|
||||
DialogInterface.OnClickListener negativ) {
|
||||
|
||||
View title = inflater.inflate(R.layout.dialog_sync_info, null);
|
||||
adb.setCustomTitle(title);
|
||||
|
||||
View orgView = inflater.inflate(R.layout.view_organisation, null);
|
||||
|
||||
TextView orgTitle = orgView.findViewById(R.id.organisation_title);
|
||||
orgTitle.setText(siqr.getOrganisation().getName());
|
||||
|
||||
TextView orgUuid = orgView.findViewById(R.id.organisation_uuid);
|
||||
orgUuid.setText(siqr.getOrganisation().getUuid());
|
||||
|
||||
TextView orgDesc = orgView.findViewById(R.id.organisation_description);
|
||||
orgDesc.setText(siqr.getOrganisation().getDescription());
|
||||
|
||||
TextView orgNat = orgView.findViewById(R.id.organisation_nationality);
|
||||
orgNat.setText(siqr.getOrganisation().getNationality());
|
||||
|
||||
TextView orgSec = orgView.findViewById(R.id.organisation_sector);
|
||||
orgSec.setText(siqr.getOrganisation().getSector());
|
||||
|
||||
TextView orgUser = orgView.findViewById(R.id.organisation_user_count);
|
||||
orgUser.setText("" + siqr.getOrganisation().getUserCount());
|
||||
|
||||
adb.setView(orgView);
|
||||
|
||||
adb.setPositiveButton(context.getResources().getString(R.string.accept), positiv);
|
||||
adb.setNegativeButton(context.getResources().getString(R.string.reject), negativ);
|
||||
|
||||
Dialog d = adb.create();
|
||||
d.getWindow().setWindowAnimations(R.style.DialogAnimation);
|
||||
d.getWindow().setDimAmount(0.8f);
|
||||
return d;
|
||||
}
|
||||
|
||||
|
||||
public Dialog createOverrideDialog(DialogInterface.OnClickListener pos,
|
||||
DialogInterface.OnClickListener neg) {
|
||||
|
||||
adb.setTitle(context.getResources().getString(R.string.override_local_data));
|
||||
adb.setMessage(context.getResources().getString(R.string.override_local_data_msg));
|
||||
|
||||
adb.setPositiveButton(context.getResources().getString(R.string.override), pos);
|
||||
adb.setNegativeButton(android.R.string.cancel, null);
|
||||
|
||||
Dialog d = adb.create();
|
||||
|
||||
d.setCancelable(false);
|
||||
d.getWindow().setWindowAnimations(R.style.DialogAnimation);
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package de.overview.wg.its.mispauth;
|
||||
package de.overview.wg.its.mispbump;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Dialog;
|
||||
|
@ -20,10 +20,9 @@ import android.view.MenuItem;
|
|||
import android.view.View;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.TextView;
|
||||
import de.overview.wg.its.mispauth.adapter.SyncedPartnerAdapter;
|
||||
import de.overview.wg.its.mispauth.auxiliary.PreferenceManager;
|
||||
import de.overview.wg.its.mispauth.cam.DialogFactory;
|
||||
import de.overview.wg.its.mispauth.model.SyncedPartner;
|
||||
import de.overview.wg.its.mispbump.adapter.SyncedPartnerAdapter;
|
||||
import de.overview.wg.its.mispbump.auxiliary.PreferenceManager;
|
||||
import de.overview.wg.its.mispbump.model.SyncedPartner;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
@ -63,7 +62,7 @@ public class MainActivity extends AppCompatActivity {
|
|||
|
||||
switch (id) {
|
||||
case R.id.menu_item_credential_settings:
|
||||
startActivity(new Intent(this, CredentialsActivity.class));
|
||||
startCredentialsActivity();
|
||||
return true;
|
||||
|
||||
case R.id.menu_item_delete_local_data:
|
||||
|
@ -74,13 +73,14 @@ public class MainActivity extends AppCompatActivity {
|
|||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
|
||||
private void initializeViews() {
|
||||
|
||||
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||
setSupportActionBar(toolbar);
|
||||
getSupportActionBar().setDisplayShowTitleEnabled(true);
|
||||
|
||||
FloatingActionButton fab = findViewById(R.id.fab);
|
||||
FloatingActionButton fab = findViewById(R.id.fab_continue_sync_info);
|
||||
fab.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
|
@ -91,7 +91,7 @@ public class MainActivity extends AppCompatActivity {
|
|||
emptyPartnerListView = findViewById(R.id.empty);
|
||||
syncedPartnerRecyclerView = findViewById(R.id.recyclerView);
|
||||
|
||||
syncedPartnerAdapter = new SyncedPartnerAdapter(syncedPartnerList);
|
||||
syncedPartnerAdapter = new SyncedPartnerAdapter(this, syncedPartnerList);
|
||||
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
|
||||
syncedPartnerRecyclerView.setLayoutManager(mLayoutManager);
|
||||
syncedPartnerRecyclerView.setItemAnimator(new DefaultItemAnimator());
|
||||
|
@ -143,7 +143,11 @@ public class MainActivity extends AppCompatActivity {
|
|||
}
|
||||
|
||||
private void refreshSyncedPartnerList() {
|
||||
syncedPartnerList = PreferenceManager.Instance(this).getSyncedPartnerList();
|
||||
// syncedPartnerList = PreferenceManager.Instance(this).getSyncedPartnerList();
|
||||
|
||||
SyncedPartner sp = new SyncedPartner("Main Organisation A", "http://192.168.178.200");
|
||||
sp.generateTimeStamp();
|
||||
syncedPartnerList.add(sp);
|
||||
|
||||
if (syncedPartnerList == null) {
|
||||
emptyPartnerListView.setVisibility(View.VISIBLE);
|
||||
|
@ -175,13 +179,12 @@ public class MainActivity extends AppCompatActivity {
|
|||
adb.show();
|
||||
|
||||
} else {
|
||||
Intent intent = new Intent(this, SyncActivity.class);
|
||||
startActivity(intent);
|
||||
startActivity(new Intent(this, QrSyncActivity.class));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void startCredentialsActivity() {
|
||||
startActivity(new Intent(this, CredentialsActivity.class));
|
||||
startActivity(new Intent(this, MyOrganisationActivity.class));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,332 @@
|
|||
package de.overview.wg.its.mispbump;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Build;
|
||||
import android.support.design.widget.FloatingActionButton;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.support.design.widget.TextInputLayout;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.widget.DefaultItemAnimator;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.ProgressBar;
|
||||
import com.android.volley.VolleyError;
|
||||
import de.overview.wg.its.mispbump.adapter.OrganisationInfoEntryAdapter;
|
||||
import de.overview.wg.its.mispbump.auxiliary.PreferenceManager;
|
||||
import de.overview.wg.its.mispbump.auxiliary.ReadableError;
|
||||
import de.overview.wg.its.mispbump.model.Organisation;
|
||||
import de.overview.wg.its.mispbump.model.StringPair;
|
||||
import de.overview.wg.its.mispbump.model.User;
|
||||
import de.overview.wg.its.mispbump.network.MispRequest;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class MyOrganisationActivity extends AppCompatActivity implements View.OnClickListener {
|
||||
|
||||
private PreferenceManager preferenceManager;
|
||||
private RecyclerView recyclerView;
|
||||
private OrganisationInfoEntryAdapter adapter;
|
||||
private View empty;
|
||||
private ProgressBar progressBar;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_my_organisation);
|
||||
|
||||
initializeContent();
|
||||
loadMyInformation();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
|
||||
int id = v.getId();
|
||||
|
||||
switch (id) {
|
||||
case R.id.fab_download:
|
||||
|
||||
enterCredentialsDialog();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
getMenuInflater().inflate(R.menu.menu_my_org, menu);
|
||||
return super.onCreateOptionsMenu(menu);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
|
||||
int id = item.getItemId();
|
||||
|
||||
switch (id) {
|
||||
|
||||
case R.id.menu_delete_local_data:
|
||||
deleteLocalDataDialog();
|
||||
break;
|
||||
|
||||
case R.id.load_config:
|
||||
|
||||
if (Build.VERSION.SDK_INT > 25) {
|
||||
preferenceManager.setServerUrl("http://192.168.178.200");
|
||||
preferenceManager.setAutomationKey("d2UEstcJiySUWpsaeiXnEFGoI1xcWhAEIiVgZOmW");
|
||||
} else {
|
||||
preferenceManager.setServerUrl("http://192.168.178.201");
|
||||
preferenceManager.setAutomationKey("eCcz0TTLEc8MeZihsoyyeqlYpd4V8PCDsDA4tM75");
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
|
||||
private void initializeContent() {
|
||||
|
||||
Toolbar t = findViewById(R.id.toolbar);
|
||||
setSupportActionBar(t);
|
||||
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
getSupportActionBar().setDisplayShowTitleEnabled(true);
|
||||
|
||||
empty = findViewById(R.id.empty);
|
||||
progressBar = findViewById(R.id.progressBar);
|
||||
|
||||
adapter = new OrganisationInfoEntryAdapter(this);
|
||||
|
||||
recyclerView = findViewById(R.id.recyclerView);
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(this));
|
||||
recyclerView.setItemAnimator(new DefaultItemAnimator());
|
||||
recyclerView.setAdapter(adapter);
|
||||
|
||||
FloatingActionButton fab = findViewById(R.id.fab_download);
|
||||
fab.setOnClickListener(this);
|
||||
|
||||
preferenceManager = PreferenceManager.Instance(this);
|
||||
}
|
||||
|
||||
private void storeCredentials(String url, String automationKey, boolean saveAutomationKey) {
|
||||
|
||||
if (saveAutomationKey) {
|
||||
preferenceManager.setAutomationKey(automationKey);
|
||||
} else {
|
||||
preferenceManager.setAutomationKey("");
|
||||
}
|
||||
|
||||
preferenceManager.setServerUrl(url);
|
||||
}
|
||||
|
||||
private void storeMyInformation(Organisation org, User user) {
|
||||
|
||||
if (org != null) {
|
||||
preferenceManager.setMyOrganisation(org);
|
||||
}
|
||||
|
||||
if (user != null) {
|
||||
preferenceManager.setMyUser(user);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void loadMyInformation() {
|
||||
|
||||
empty.setVisibility(View.VISIBLE);
|
||||
recyclerView.setVisibility(View.GONE);
|
||||
|
||||
Organisation myOrg = preferenceManager.getMyOrganisation();
|
||||
User myUser = preferenceManager.getMyUser();
|
||||
|
||||
visualizeInformation(myOrg, myUser);
|
||||
}
|
||||
|
||||
private void downloadOrganisationInformation(String url, String automationKey) {
|
||||
|
||||
empty.setVisibility(View.GONE);
|
||||
recyclerView.setVisibility(View.GONE);
|
||||
progressBar.setVisibility(View.VISIBLE);
|
||||
|
||||
final MispRequest mispRequest = MispRequest.Instance(this, false);
|
||||
mispRequest.setServerCredentials(url, automationKey);
|
||||
|
||||
final User myUser = new User();
|
||||
final Organisation myOrganisation = new Organisation();
|
||||
|
||||
mispRequest.getMyUser(new MispRequest.UserCallback() {
|
||||
@Override
|
||||
public void onResult(JSONObject jsonUser) {
|
||||
try {
|
||||
|
||||
myUser.fromJSON(jsonUser);
|
||||
|
||||
} catch (JSONException e) {
|
||||
|
||||
alert(e.getMessage());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
mispRequest.getOrganisation(myUser.getId(), new MispRequest.OrganisationCallback() {
|
||||
@Override
|
||||
public void onResult(JSONObject organisationInformation) {
|
||||
try {
|
||||
|
||||
myOrganisation.fromJSON(organisationInformation);
|
||||
|
||||
storeMyInformation(myOrganisation, myUser);
|
||||
visualizeInformation(myOrganisation, myUser);
|
||||
|
||||
} catch (JSONException e) {
|
||||
|
||||
alert(e.getMessage());
|
||||
visualizeInformation(null, null);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(VolleyError volleyError) {
|
||||
alert(ReadableError.toReadable(volleyError));
|
||||
visualizeInformation(null, null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(VolleyError volleyError) {
|
||||
alert(ReadableError.toReadable(volleyError));
|
||||
visualizeInformation(null, null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void visualizeInformation(Organisation org, User user) {
|
||||
|
||||
progressBar.setVisibility(View.GONE);
|
||||
|
||||
if (org != null && user != null) {
|
||||
|
||||
empty.setVisibility(View.GONE);
|
||||
recyclerView.setVisibility(View.VISIBLE);
|
||||
|
||||
} else {
|
||||
|
||||
empty.setVisibility(View.VISIBLE);
|
||||
recyclerView.setVisibility(View.GONE);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
getSupportActionBar().setTitle(org.getName());
|
||||
|
||||
List<StringPair> orgInfoEntries = new ArrayList<>();
|
||||
|
||||
orgInfoEntries.add(new StringPair("UUID", org.getUuid()));
|
||||
orgInfoEntries.add(new StringPair("Description", org.getDescription()));
|
||||
orgInfoEntries.add(new StringPair("Nationality", org.getNationality()));
|
||||
orgInfoEntries.add(new StringPair("Sector", org.getSector()));
|
||||
orgInfoEntries.add(new StringPair("User Count", "" + org.getUserCount()));
|
||||
|
||||
adapter.setList(orgInfoEntries);
|
||||
|
||||
}
|
||||
|
||||
private void enterCredentialsDialog() {
|
||||
|
||||
AlertDialog.Builder adb = new AlertDialog.Builder(this);
|
||||
LayoutInflater inflater = getLayoutInflater();
|
||||
|
||||
adb.setTitle("MISP Credentials");
|
||||
|
||||
View v = inflater.inflate(R.layout.dialog_enter_credentials, null);
|
||||
adb.setView(v);
|
||||
|
||||
final CheckBox saveAutomationKey = v.findViewById(R.id.check_save_authkey);
|
||||
final TextInputLayout serverUrlLayout = v.findViewById(R.id.input_layout_server_url);
|
||||
final TextInputLayout automationKeyLayout = v.findViewById(R.id.input_layout_automation_key);
|
||||
|
||||
saveAutomationKey.setChecked(preferenceManager.saveAuthKeyEnabled());
|
||||
serverUrlLayout.getEditText().setText(preferenceManager.getMyServerUrl());
|
||||
automationKeyLayout.getEditText().setText(preferenceManager.getMyServerAutomationKey());
|
||||
|
||||
adb.setPositiveButton("Download", null);
|
||||
adb.setNegativeButton(android.R.string.cancel, null);
|
||||
|
||||
final Dialog dialog = adb.create();
|
||||
dialog.show();
|
||||
|
||||
Button posButton = ((AlertDialog) dialog).getButton(AlertDialog.BUTTON_POSITIVE);
|
||||
|
||||
posButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
String url = serverUrlLayout.getEditText().getText().toString();
|
||||
String automationKey = automationKeyLayout.getEditText().getText().toString();
|
||||
|
||||
boolean validCredentials = true;
|
||||
|
||||
if (url.equals("")) {
|
||||
validCredentials = false;
|
||||
serverUrlLayout.setError(getString(R.string.error_url_required));
|
||||
}
|
||||
|
||||
if (automationKey.equals("")) {
|
||||
validCredentials = false;
|
||||
automationKeyLayout.setError(getString(R.string.error_automation_key));
|
||||
}
|
||||
|
||||
boolean save = saveAutomationKey.isChecked();
|
||||
preferenceManager.setSaveAuthKeyEnabled(save);
|
||||
|
||||
if (validCredentials) {
|
||||
dialog.dismiss();
|
||||
storeCredentials(url, automationKey, save);
|
||||
downloadOrganisationInformation(url, automationKey);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void deleteLocalDataDialog() {
|
||||
|
||||
AlertDialog.Builder adb = new AlertDialog.Builder(this);
|
||||
|
||||
adb.setTitle("Delete Local Data");
|
||||
|
||||
adb.setMessage(getString(R.string.delete_local_data_msg));
|
||||
|
||||
adb.setPositiveButton(getString(R.string.delete), new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
preferenceManager.clearCredentialPreferences();
|
||||
}
|
||||
});
|
||||
|
||||
adb.setNegativeButton(android.R.string.cancel, null);
|
||||
|
||||
adb.create().show();
|
||||
}
|
||||
|
||||
private void alert(String message) {
|
||||
Snackbar.make(findViewById(R.id.coordinator), message, Snackbar.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,445 @@
|
|||
package de.overview.wg.its.mispbump;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Point;
|
||||
import android.os.Bundle;
|
||||
import android.support.design.widget.FloatingActionButton;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v4.app.FragmentTransaction;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.*;
|
||||
import android.view.animation.DecelerateInterpolator;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
import com.google.gson.Gson;
|
||||
import de.overview.wg.its.mispbump.auxiliary.AESSecurity;
|
||||
import de.overview.wg.its.mispbump.auxiliary.PreferenceManager;
|
||||
import de.overview.wg.its.mispbump.auxiliary.RandomString;
|
||||
import de.overview.wg.its.mispbump.auxiliary.TempAuth;
|
||||
import de.overview.wg.its.mispbump.cam.CameraFragment;
|
||||
import de.overview.wg.its.mispbump.model.*;
|
||||
import net.glxn.qrgen.android.QRCode;
|
||||
import org.json.JSONException;
|
||||
|
||||
public class QrSyncActivity extends AppCompatActivity implements View.OnClickListener {
|
||||
|
||||
private enum ScanState {
|
||||
public_key,
|
||||
information
|
||||
}
|
||||
|
||||
private ScanState currentScanState;
|
||||
|
||||
private FloatingActionButton proceedToSyncInfoFab, proceedToSyncUploadFab;
|
||||
private PreferenceManager preferenceManager;
|
||||
private View qrBackground;
|
||||
private ImageView qrImage;
|
||||
private CameraFragment cameraFragment;
|
||||
private AESSecurity cryptography;
|
||||
|
||||
private SyncInformationQr receivedSyncInfo;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
|
||||
setContentView(R.layout.activity_qr_sync);
|
||||
|
||||
initializeContent();
|
||||
startPublicKeyExchange();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
|
||||
int id = v.getId();
|
||||
|
||||
switch (id) {
|
||||
|
||||
case R.id.fab_continue_sync_info:
|
||||
acceptProceedDialog(new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
startSyncInformationExchange();
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case R.id.fab_continue_sync_upload:
|
||||
|
||||
acceptProceedDialog(new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
startSyncUpload();
|
||||
}
|
||||
});
|
||||
|
||||
break;
|
||||
|
||||
case R.id.close:
|
||||
finish();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void initializeContent() {
|
||||
|
||||
proceedToSyncInfoFab = findViewById(R.id.fab_continue_sync_info);
|
||||
proceedToSyncInfoFab.hide();
|
||||
proceedToSyncInfoFab.setOnClickListener(this);
|
||||
|
||||
proceedToSyncUploadFab = findViewById(R.id.fab_continue_sync_upload);
|
||||
proceedToSyncUploadFab.hide();
|
||||
proceedToSyncUploadFab.setOnClickListener(this);
|
||||
|
||||
ImageButton close = findViewById(R.id.close);
|
||||
close.setOnClickListener(this);
|
||||
|
||||
qrBackground = findViewById(R.id.qr_background);
|
||||
qrBackground.setVisibility(View.INVISIBLE);
|
||||
qrImage = findViewById(R.id.qr_imageView);
|
||||
|
||||
preferenceManager = PreferenceManager.Instance(this);
|
||||
cryptography = AESSecurity.getInstance();
|
||||
|
||||
cameraFragment = new CameraFragment();
|
||||
FragmentManager manager = getSupportFragmentManager();
|
||||
FragmentTransaction transaction = manager.beginTransaction();
|
||||
String camTag = cameraFragment.getClass().getSimpleName();
|
||||
transaction.replace(R.id.fragment_container, cameraFragment, camTag);
|
||||
transaction.commit();
|
||||
|
||||
}
|
||||
|
||||
private void startPublicKeyExchange() {
|
||||
|
||||
currentScanState = ScanState.public_key;
|
||||
|
||||
User myUser = preferenceManager.getMyUser();
|
||||
Organisation myOrg = preferenceManager.getMyOrganisation();
|
||||
String pubKey = AESSecurity.publicKeyToString(cryptography.getPublicKey());
|
||||
|
||||
PublicKeyQr publicKeyQr = new PublicKeyQr(myOrg.getName(), myUser.getEmail(), pubKey);
|
||||
|
||||
showQr(publicKeyQr.toJSON().toString());
|
||||
|
||||
cameraFragment.setReadQrEnabled(true);
|
||||
}
|
||||
|
||||
private void receivedPublicKey(PublicKeyQr publicKeyQr) {
|
||||
cryptography.setForeignPublicKey(AESSecurity.publicKeyFromString(publicKeyQr.getKey()));
|
||||
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
proceedToSyncInfoFab.show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void startSyncInformationExchange() {
|
||||
|
||||
currentScanState = ScanState.information;
|
||||
|
||||
Organisation myOrg = preferenceManager.getMyOrganisation();
|
||||
|
||||
proceedToSyncInfoFab.setVisibility(View.GONE);
|
||||
cameraFragment.setReadQrEnabled(true);
|
||||
|
||||
TempAuth.TMP_AUTH_KEY = new RandomString(40).nextString();
|
||||
|
||||
Server serverForMeOnOtherInstance = new Server();
|
||||
serverForMeOnOtherInstance.setAuthkey(TempAuth.TMP_AUTH_KEY);
|
||||
serverForMeOnOtherInstance.setName("SyncServer for " + myOrg.getName());
|
||||
serverForMeOnOtherInstance.setUrl(preferenceManager.getMyServerUrl());
|
||||
|
||||
final SyncInformationQr siqr = new SyncInformationQr(
|
||||
preferenceManager.getMyOrganisation(),
|
||||
serverForMeOnOtherInstance,
|
||||
preferenceManager.getMyUser());
|
||||
|
||||
|
||||
showQr(cryptography.encrypt(siqr.toJSON().toString()));
|
||||
|
||||
cameraFragment.setReadQrEnabled(true);
|
||||
|
||||
}
|
||||
|
||||
private void receivedSyncInformation(SyncInformationQr syncInformationQr) {
|
||||
|
||||
receivedSyncInfo = syncInformationQr;
|
||||
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
proceedToSyncUploadFab.setVisibility(View.VISIBLE);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public void onReadQrCode(String qrData) {
|
||||
|
||||
switch (currentScanState) {
|
||||
case public_key:
|
||||
|
||||
try {
|
||||
|
||||
publicKeyReceivedDialog(new PublicKeyQr(qrData));
|
||||
|
||||
} catch (JSONException e) {
|
||||
notExpectedFormatDialog();
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case information:
|
||||
|
||||
try {
|
||||
|
||||
syncInformationReceivedDialog(new SyncInformationQr(qrData));
|
||||
|
||||
} catch (JSONException e) {
|
||||
|
||||
notExpectedFormatDialog();
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
cameraFragment.setReadQrEnabled(false);
|
||||
}
|
||||
|
||||
private void showQr(String qrData) {
|
||||
generateQr(qrData);
|
||||
|
||||
if (qrBackground.getVisibility() == View.VISIBLE) { // First close if visible
|
||||
circularReveal(qrBackground, false, 300, 0); // close directly
|
||||
circularReveal(qrBackground, true, 300, 350); // open 250ms later
|
||||
} else {
|
||||
circularReveal(qrBackground, true, 300, 0); // if not visible just open directly
|
||||
}
|
||||
}
|
||||
|
||||
private void hideQr() {
|
||||
if (qrBackground.getVisibility() == View.VISIBLE) {
|
||||
circularReveal(qrBackground, false, 200, 0);
|
||||
}
|
||||
}
|
||||
|
||||
private void generateQr(String data) {
|
||||
Display display = getWindowManager().getDefaultDisplay();
|
||||
Point size = new Point();
|
||||
display.getSize(size);
|
||||
|
||||
int width = (int) (size.x * 0.8f);
|
||||
|
||||
//noinspection SuspiciousNameCombination
|
||||
qrImage.setImageBitmap(QRCode.from(data)
|
||||
.withColor(0xFF000000, 0x00FFFFFF)
|
||||
.withSize(width, width)
|
||||
.bitmap());
|
||||
}
|
||||
|
||||
private void startSyncUpload() {
|
||||
Intent i = new Intent(this, SyncUploadActivity.class);
|
||||
i.putExtra(SyncUploadActivity.PARTNER_INFO_BUNDLE_KEY, new Gson().toJson(receivedSyncInfo));
|
||||
startActivity(i);
|
||||
finish();
|
||||
}
|
||||
|
||||
private void publicKeyReceivedDialog(final PublicKeyQr pkqr) {
|
||||
|
||||
cameraFragment.setReadQrEnabled(false);
|
||||
|
||||
AlertDialog.Builder adb = new AlertDialog.Builder(this);
|
||||
LayoutInflater inflater = getLayoutInflater();
|
||||
|
||||
@SuppressLint("InflateParams") View title = inflater.inflate(R.layout.dialog_public_key, null);
|
||||
adb.setCustomTitle(title);
|
||||
|
||||
adb.setMessage("\nOrganisation: " + pkqr.getOrganisation() + "\nEmail: " + pkqr.getEmail());
|
||||
|
||||
adb.setPositiveButton(getString(R.string.accept), new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
receivedPublicKey(pkqr);
|
||||
}
|
||||
});
|
||||
|
||||
adb.setNegativeButton(getString(R.string.reject), new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
cameraFragment.setReadQrEnabled(true);
|
||||
}
|
||||
});
|
||||
|
||||
adb.setCancelable(false);
|
||||
|
||||
Dialog d = adb.create();
|
||||
|
||||
//noinspection ConstantConditions
|
||||
d.getWindow().setWindowAnimations(R.style.DialogAnimation);
|
||||
d.getWindow().setDimAmount(0.8f);
|
||||
d.show();
|
||||
}
|
||||
|
||||
private void syncInformationReceivedDialog(final SyncInformationQr siqr) {
|
||||
|
||||
cameraFragment.setReadQrEnabled(false);
|
||||
|
||||
AlertDialog.Builder adb = new AlertDialog.Builder(this);
|
||||
LayoutInflater inflater = getLayoutInflater();
|
||||
|
||||
@SuppressLint("InflateParams") View title = inflater.inflate(R.layout.dialog_sync_info, null);
|
||||
adb.setCustomTitle(title);
|
||||
|
||||
@SuppressLint("InflateParams") View orgView = inflater.inflate(R.layout.view_organisation, null);
|
||||
|
||||
TextView orgTitle = orgView.findViewById(R.id.organisation_title);
|
||||
orgTitle.setText(siqr.getOrganisation().getName());
|
||||
|
||||
TextView orgUuid = orgView.findViewById(R.id.organisation_uuid);
|
||||
orgUuid.setText(siqr.getOrganisation().getUuid());
|
||||
|
||||
TextView orgDesc = orgView.findViewById(R.id.organisation_description);
|
||||
orgDesc.setText(siqr.getOrganisation().getDescription());
|
||||
|
||||
TextView orgNat = orgView.findViewById(R.id.organisation_nationality);
|
||||
orgNat.setText(siqr.getOrganisation().getNationality());
|
||||
|
||||
TextView orgSec = orgView.findViewById(R.id.organisation_sector);
|
||||
orgSec.setText(siqr.getOrganisation().getSector());
|
||||
|
||||
TextView orgUser = orgView.findViewById(R.id.organisation_user_count);
|
||||
orgUser.setText("" + siqr.getOrganisation().getUserCount());
|
||||
|
||||
adb.setView(orgView);
|
||||
|
||||
adb.setPositiveButton(getString(R.string.accept), new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
receivedSyncInformation(siqr);
|
||||
}
|
||||
});
|
||||
|
||||
adb.setNegativeButton(getString(R.string.reject), new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
cameraFragment.setReadQrEnabled(true);
|
||||
}
|
||||
});
|
||||
|
||||
Dialog d = adb.create();
|
||||
//noinspection ConstantConditions
|
||||
d.getWindow().setWindowAnimations(R.style.DialogAnimation);
|
||||
d.getWindow().setDimAmount(0.8f);
|
||||
|
||||
d.show();
|
||||
}
|
||||
|
||||
private void acceptProceedDialog(Dialog.OnClickListener posListener) {
|
||||
|
||||
AlertDialog.Builder adb = new AlertDialog.Builder(this);
|
||||
|
||||
adb.setTitle("Proceed");
|
||||
|
||||
if (currentScanState == ScanState.public_key) {
|
||||
adb.setMessage("Did your sync partner already scan your Public Key?");
|
||||
} else {
|
||||
adb.setMessage("Did your sync partner already scan your Sync Information?");
|
||||
}
|
||||
|
||||
adb.setPositiveButton("Yes", posListener);
|
||||
adb.setNegativeButton("No", null);
|
||||
|
||||
adb.create().show();
|
||||
}
|
||||
|
||||
private void notExpectedFormatDialog() {
|
||||
|
||||
AlertDialog.Builder adb = new AlertDialog.Builder(this);
|
||||
|
||||
switch (currentScanState) {
|
||||
case public_key:
|
||||
adb.setTitle("Public Key Expected");
|
||||
adb.setMessage("Please tell your Sync Partner to go back to the Public Key exchange");
|
||||
break;
|
||||
|
||||
case information:
|
||||
adb.setTitle("Sync Information Expected");
|
||||
adb.setMessage("Please tell your Sync Partner to proceed to the Sync Information exchange");
|
||||
break;
|
||||
}
|
||||
|
||||
adb.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
cameraFragment.setReadQrEnabled(true);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private void circularReveal(final View v, final boolean open, final long duration, final long startDelay) {
|
||||
|
||||
v.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
int cx = v.getWidth() / 2;
|
||||
int cy = v.getHeight() / 2;
|
||||
|
||||
float finalRadius = (float) Math.hypot(cx, cy);
|
||||
|
||||
Animator anim;
|
||||
|
||||
if (open) {
|
||||
anim = ViewAnimationUtils.createCircularReveal(v, cx, cy, 0, finalRadius);
|
||||
} else {
|
||||
anim = ViewAnimationUtils.createCircularReveal(v, cx, cy, finalRadius, 0);
|
||||
}
|
||||
|
||||
anim.setInterpolator(new DecelerateInterpolator());
|
||||
anim.setDuration(duration);
|
||||
|
||||
anim.addListener(new Animator.AnimatorListener() {
|
||||
@Override
|
||||
public void onAnimationStart(Animator animation) {
|
||||
qrBackground.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
if (!open) {
|
||||
qrBackground.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationCancel(Animator animation) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationRepeat(Animator animation) {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
anim.setStartDelay(startDelay);
|
||||
|
||||
anim.start();
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package de.overview.wg.its.mispauth;
|
||||
package de.overview.wg.its.mispbump;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.content.Intent;
|
||||
|
@ -15,14 +15,15 @@ import android.view.WindowManager;
|
|||
import android.view.animation.DecelerateInterpolator;
|
||||
import android.widget.*;
|
||||
import com.google.gson.Gson;
|
||||
import de.overview.wg.its.mispauth.auxiliary.AESSecurity;
|
||||
import de.overview.wg.its.mispauth.auxiliary.PreferenceManager;
|
||||
import de.overview.wg.its.mispauth.auxiliary.RandomString;
|
||||
import de.overview.wg.its.mispauth.auxiliary.TempAuth;
|
||||
import de.overview.wg.its.mispauth.cam.CameraFragment;
|
||||
import de.overview.wg.its.mispauth.model.*;
|
||||
import de.overview.wg.its.mispbump.auxiliary.AESSecurity;
|
||||
import de.overview.wg.its.mispbump.auxiliary.PreferenceManager;
|
||||
import de.overview.wg.its.mispbump.auxiliary.RandomString;
|
||||
import de.overview.wg.its.mispbump.auxiliary.TempAuth;
|
||||
import de.overview.wg.its.mispbump.cam.CameraFragment;
|
||||
import de.overview.wg.its.mispbump.model.*;
|
||||
import net.glxn.qrgen.android.QRCode;
|
||||
|
||||
@Deprecated
|
||||
public class SyncActivity extends AppCompatActivity implements View.OnClickListener {
|
||||
|
||||
private static final String SCAN_PUB_KEY_FRAG_TAG = "scan_public_key_fragment_tag";
|
||||
|
@ -33,7 +34,6 @@ public class SyncActivity extends AppCompatActivity implements View.OnClickListe
|
|||
private Fragment currentFragment;
|
||||
private String currentFragmentTag;
|
||||
|
||||
// Views for QR code
|
||||
private LinearLayout qrBackground;
|
||||
private ImageView qrImageView;
|
||||
private Button forwardButton;
|
||||
|
@ -99,7 +99,7 @@ public class SyncActivity extends AppCompatActivity implements View.OnClickListe
|
|||
|
||||
setQrContent(pkqr.toJSON().toString(), 0.6f);
|
||||
|
||||
currentFragment = CameraFragment.newInstance(CameraFragment.ScanMode.PUBLIC_KEY);
|
||||
// currentFragment = CameraFragment.newInstance(CameraFragment.ScanMode.PUBLIC_KEY);
|
||||
currentFragmentTag = SCAN_PUB_KEY_FRAG_TAG;
|
||||
|
||||
break;
|
||||
|
@ -122,7 +122,7 @@ public class SyncActivity extends AppCompatActivity implements View.OnClickListe
|
|||
|
||||
setQrContent(aesSecurity.encrypt(siqr.toJSON().toString()), 0.9f);
|
||||
|
||||
currentFragment = CameraFragment.newInstance(CameraFragment.ScanMode.INFO);
|
||||
// currentFragment = CameraFragment.newInstance(CameraFragment.ScanMode.INFO);
|
||||
currentFragmentTag = SCAN_INFO_FRAG_TAG;
|
||||
|
||||
break;
|
||||
|
@ -218,10 +218,8 @@ public class SyncActivity extends AppCompatActivity implements View.OnClickListe
|
|||
|
||||
private void startUploadActivity() {
|
||||
|
||||
Intent i = new Intent(this, UploadActivity.class);
|
||||
String partnerString = new Gson().toJson(partnerInformation);
|
||||
i.putExtra(UploadActivity.PARTNER_INFO_BUNDLE_KEY, partnerString);
|
||||
|
||||
Intent i = new Intent(this, SyncUploadActivity.class);
|
||||
i.putExtra(SyncUploadActivity.PARTNER_INFO_BUNDLE_KEY, new Gson().toJson(partnerInformation));
|
||||
startActivity(i);
|
||||
finish();
|
||||
|
|
@ -0,0 +1,345 @@
|
|||
package de.overview.wg.its.mispbump;
|
||||
|
||||
import android.support.design.widget.FloatingActionButton;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.widget.DefaultItemAnimator;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.view.View;
|
||||
import com.android.volley.VolleyError;
|
||||
import com.google.gson.Gson;
|
||||
import de.overview.wg.its.mispbump.adapter.UploadStateAdapter;
|
||||
import de.overview.wg.its.mispbump.auxiliary.ReadableError;
|
||||
import de.overview.wg.its.mispbump.auxiliary.TempAuth;
|
||||
import de.overview.wg.its.mispbump.model.*;
|
||||
import de.overview.wg.its.mispbump.network.MispRequest;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
public class SyncUploadActivity extends AppCompatActivity implements View.OnClickListener {
|
||||
|
||||
static final String PARTNER_INFO_BUNDLE_KEY = "partner_info";
|
||||
|
||||
private FloatingActionButton fabStart, fabFinish, fabRetry;
|
||||
|
||||
private MispRequest mispRequest;
|
||||
|
||||
private Organisation partnerOrganisation;
|
||||
private Server partnerServer;
|
||||
private User partnerSyncUser;
|
||||
|
||||
private UploadStateAdapter uploadStateAdapter;
|
||||
private UploadState[] uploadStates;
|
||||
private int currentTask = 0;
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
int id = v.getId();
|
||||
|
||||
if (id == R.id.fab_start) {
|
||||
startUpload();
|
||||
fabStart.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
if (id == R.id.fab_retry) {
|
||||
fabRetry.setVisibility(View.GONE);
|
||||
fabFinish.setVisibility(View.GONE);
|
||||
|
||||
//TODO retry implementation
|
||||
}
|
||||
|
||||
if (id == R.id.fab_finish) {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_upload);
|
||||
|
||||
initializeContent();
|
||||
}
|
||||
|
||||
|
||||
private void initializeContent() {
|
||||
|
||||
// Toolbar
|
||||
|
||||
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||
setSupportActionBar(toolbar);
|
||||
|
||||
getSupportActionBar().setDisplayShowHomeEnabled(false);
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(false);
|
||||
getSupportActionBar().setDisplayShowTitleEnabled(true);
|
||||
|
||||
// FABs
|
||||
|
||||
fabStart = findViewById(R.id.fab_start);
|
||||
fabStart.setVisibility(View.VISIBLE);
|
||||
fabFinish = findViewById(R.id.fab_finish);
|
||||
fabFinish.setVisibility(View.GONE);
|
||||
fabRetry = findViewById(R.id.fab_retry);
|
||||
fabRetry.setVisibility(View.GONE);
|
||||
|
||||
// RecyclerView
|
||||
|
||||
RecyclerView recyclerView = findViewById(R.id.recyclerView);
|
||||
uploadStateAdapter = new UploadStateAdapter();
|
||||
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(this);
|
||||
recyclerView.setLayoutManager(mLayoutManager);
|
||||
recyclerView.setItemAnimator(new DefaultItemAnimator());
|
||||
recyclerView.setAdapter(uploadStateAdapter);
|
||||
|
||||
// UploadStates
|
||||
|
||||
uploadStates = new UploadState[6];
|
||||
|
||||
uploadStates[0].setTitle("Validate upload information");
|
||||
uploadStates[1].setTitle("Check connection to server");
|
||||
uploadStates[2].setTitle("Create local organisation");
|
||||
uploadStates[3].setTitle("Create sync user & add to organisation");
|
||||
uploadStates[4].setTitle("Create external organisation");
|
||||
uploadStates[5].setTitle("Create sync server");
|
||||
|
||||
uploadStateAdapter.setStates(uploadStates);
|
||||
|
||||
// Request
|
||||
|
||||
mispRequest = MispRequest.Instance(this, true);
|
||||
}
|
||||
|
||||
private void startUpload() {
|
||||
currentTask = 0;
|
||||
executeTask(currentTask);
|
||||
}
|
||||
|
||||
private void undoTask(int index) {
|
||||
switch (index) {
|
||||
|
||||
case 2:
|
||||
createOrganisation(uploadStates[index], true);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
createSyncUser(uploadStates[index], true);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
createExternalOrganisation(uploadStates[index], true);
|
||||
break;
|
||||
|
||||
case 5:
|
||||
createSyncServer(uploadStates[index], true);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void executeTask(int index) {
|
||||
switch (index) {
|
||||
case 0:
|
||||
checkBundle(uploadStates[index]);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
checkConnection(uploadStates[index]);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
createOrganisation(uploadStates[index], false);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
createSyncUser(uploadStates[index], false);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
createExternalOrganisation(uploadStates[index], false);
|
||||
break;
|
||||
|
||||
case 5:
|
||||
createSyncServer(uploadStates[index], false);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
uploadStateAdapter.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
private void executeNextTask() {
|
||||
currentTask++;
|
||||
|
||||
if (currentTask > uploadStates.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
executeTask(currentTask);
|
||||
}
|
||||
|
||||
private void setApplicationError(boolean canRetry) {
|
||||
fabFinish.setVisibility(View.VISIBLE);
|
||||
|
||||
if (canRetry) {
|
||||
fabRetry.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
// Upload States
|
||||
|
||||
private void checkBundle(UploadState state) {
|
||||
state.setInProgress();
|
||||
|
||||
Bundle b = getIntent().getExtras();
|
||||
|
||||
if (b != null) {
|
||||
|
||||
String info = b.getString(PARTNER_INFO_BUNDLE_KEY);
|
||||
|
||||
SyncInformationQr partnerInformation = new Gson().fromJson(info, SyncInformationQr.class);
|
||||
|
||||
partnerOrganisation = partnerInformation.getOrganisation();
|
||||
partnerServer = partnerInformation.getServer();
|
||||
partnerSyncUser = partnerInformation.getUser();
|
||||
|
||||
state.setDone();
|
||||
executeNextTask();
|
||||
|
||||
} else {
|
||||
state.setError("Partners information format is incorrect");
|
||||
setApplicationError(false);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkConnection(final UploadState state) {
|
||||
state.setInProgress();
|
||||
|
||||
mispRequest.testConnection(new MispRequest.ConnectionCallback() {
|
||||
@Override
|
||||
public void onResult(boolean connected) {
|
||||
if (connected) {
|
||||
state.setDone();
|
||||
executeNextTask();
|
||||
} else {
|
||||
state.setError("Could not connect to server");
|
||||
setApplicationError(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void createOrganisation(final UploadState state, boolean undo) {
|
||||
state.setInProgress();
|
||||
|
||||
if (!undo) {
|
||||
mispRequest.addOrganisation(partnerOrganisation, new MispRequest.OrganisationCallback() {
|
||||
@Override
|
||||
public void onResult(JSONObject organisationInformation) {
|
||||
try {
|
||||
|
||||
int orgId = new Organisation(organisationInformation).getId();
|
||||
|
||||
partnerSyncUser.setOrgId(orgId);
|
||||
partnerSyncUser.setAuthkey(TempAuth.TMP_AUTH_KEY);
|
||||
partnerSyncUser.setRoleId(User.RoleId.SYNC_USER);
|
||||
|
||||
state.setDone();
|
||||
executeNextTask();
|
||||
|
||||
} catch (JSONException e) {
|
||||
state.setError("Unknown error: could not read server response");
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(VolleyError volleyError) {
|
||||
state.setError(ReadableError.toReadable(volleyError));
|
||||
setApplicationError(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void createSyncUser(final UploadState state, boolean undo) {
|
||||
state.setInProgress();
|
||||
|
||||
if (!undo) {
|
||||
mispRequest.addUser(partnerSyncUser, new MispRequest.UserCallback() {
|
||||
@Override
|
||||
public void onResult(JSONObject myUserInformation) {
|
||||
state.setDone();
|
||||
executeNextTask();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(VolleyError volleyError) {
|
||||
state.setError(ReadableError.toReadable(volleyError));
|
||||
setApplicationError(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void createExternalOrganisation(final UploadState state, boolean undo) {
|
||||
|
||||
final String originalOrgName = partnerOrganisation.getName();
|
||||
|
||||
state.setInProgress();
|
||||
|
||||
if (!undo) {
|
||||
partnerOrganisation.setName(partnerOrganisation.getName() + " (Remote)");
|
||||
partnerOrganisation.setLocal(false);
|
||||
|
||||
mispRequest.addOrganisation(partnerOrganisation, new MispRequest.OrganisationCallback() {
|
||||
|
||||
@Override
|
||||
public void onResult(JSONObject organisationInformation) {
|
||||
try {
|
||||
|
||||
int extOrgId = new Organisation(organisationInformation).getId();
|
||||
partnerServer.setRemoteOrgId(extOrgId);
|
||||
partnerServer.setPush(true);
|
||||
|
||||
// Reset partner organisation name TODO why?
|
||||
partnerOrganisation.setName(originalOrgName);
|
||||
|
||||
state.setDone();
|
||||
executeNextTask();
|
||||
|
||||
} catch (JSONException e) {
|
||||
state.setError("Could not interpret server response");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(VolleyError volleyError) {
|
||||
state.setError(ReadableError.toReadable(volleyError));
|
||||
setApplicationError(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void createSyncServer(final UploadState state, boolean undo) {
|
||||
state.setInProgress();
|
||||
|
||||
if (!undo) {
|
||||
mispRequest.addServer(partnerServer, new MispRequest.ServerCallback() {
|
||||
@Override
|
||||
public void onResult(JSONObject servers) {
|
||||
state.setDone();
|
||||
executeNextTask();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(VolleyError volleyError) {
|
||||
state.setError(ReadableError.toReadable(volleyError));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package de.overview.wg.its.mispauth;
|
||||
package de.overview.wg.its.mispbump;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.design.widget.FloatingActionButton;
|
||||
|
@ -10,18 +10,19 @@ import android.support.v7.widget.Toolbar;
|
|||
import android.view.View;
|
||||
import com.android.volley.VolleyError;
|
||||
import com.google.gson.Gson;
|
||||
import de.overview.wg.its.mispauth.adapter.UploadStateAdapter;
|
||||
import de.overview.wg.its.mispauth.auxiliary.PreferenceManager;
|
||||
import de.overview.wg.its.mispauth.auxiliary.ReadableError;
|
||||
import de.overview.wg.its.mispauth.auxiliary.TempAuth;
|
||||
import de.overview.wg.its.mispauth.model.*;
|
||||
import de.overview.wg.its.mispauth.network.MispRequest;
|
||||
import de.overview.wg.its.mispbump.adapter.UploadStateAdapter;
|
||||
import de.overview.wg.its.mispbump.auxiliary.PreferenceManager;
|
||||
import de.overview.wg.its.mispbump.auxiliary.ReadableError;
|
||||
import de.overview.wg.its.mispbump.auxiliary.TempAuth;
|
||||
import de.overview.wg.its.mispbump.model.*;
|
||||
import de.overview.wg.its.mispbump.network.MispRequest;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Deprecated
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
public class UploadActivity extends AppCompatActivity implements View.OnClickListener {
|
||||
|
||||
|
@ -35,6 +36,7 @@ public class UploadActivity extends AppCompatActivity implements View.OnClickLis
|
|||
private Server partnerServer;
|
||||
|
||||
private UploadStateAdapter uploadStateAdapter;
|
||||
private FloatingActionButton fab;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
|
@ -63,8 +65,9 @@ public class UploadActivity extends AppCompatActivity implements View.OnClickLis
|
|||
getSupportActionBar().setDisplayHomeAsUpEnabled(false);
|
||||
getSupportActionBar().setDisplayShowTitleEnabled(true);
|
||||
|
||||
FloatingActionButton fab = findViewById(R.id.fab);
|
||||
fab = findViewById(R.id.fab_continue_sync_info);
|
||||
fab.setOnClickListener(this);
|
||||
fab.setVisibility(View.GONE);
|
||||
|
||||
RecyclerView recyclerView = findViewById(R.id.recyclerView);
|
||||
uploadStateAdapter = new UploadStateAdapter();
|
||||
|
@ -80,14 +83,18 @@ public class UploadActivity extends AppCompatActivity implements View.OnClickLis
|
|||
int id = v.getId();
|
||||
|
||||
switch (id) {
|
||||
case R.id.fab:
|
||||
case R.id.fab_continue_sync_info:
|
||||
finish();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void setUploadSucces() {
|
||||
fab.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
private void setCurrentStateWrapper(int stateNumber, UploadState.State state) {
|
||||
syncUploadStates.get(stateNumber).setCurrentState(state);
|
||||
// syncUploadStates.get(stateNumber).setCurrentState(state);
|
||||
uploadStateAdapter.notifyItemChanged(stateNumber);
|
||||
}
|
||||
|
||||
|
@ -103,46 +110,45 @@ public class UploadActivity extends AppCompatActivity implements View.OnClickLis
|
|||
syncUploadStates.add(new UploadState("Create external organisation"));
|
||||
syncUploadStates.add(new UploadState("Create sync server"));
|
||||
|
||||
uploadStateAdapter.setStateList(syncUploadStates);
|
||||
// uploadStateAdapter.setStates(syncUploadStates);
|
||||
|
||||
uploadSyncOrganisation();
|
||||
|
||||
fab.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
private void uploadSyncOrganisation() {
|
||||
setCurrentStateWrapper(0, UploadState.State.IN_PROGRESS);
|
||||
// syncUploadStates.get(0).setCurrentState(UploadState.State.IN_PROGRESS);
|
||||
mispRequest.addOrganisation(partnerOrganisation, new MispRequest.OrganisationCallback() {
|
||||
@Override
|
||||
public void onResult(JSONObject organisationInformation) {
|
||||
try {
|
||||
|
||||
Organisation retOrg = new Organisation(organisationInformation);
|
||||
setCurrentStateWrapper(0, UploadState.State.DONE);
|
||||
// syncUploadStates.get(0).setCurrentState(UploadState.State.DONE);
|
||||
uploadSyncUser(retOrg.getId());
|
||||
setCurrentStateWrapper(0, UploadState.State.IN_PROGRESS);
|
||||
|
||||
} catch (JSONException e) {
|
||||
syncUploadStates.get(0).setError("Could not read server response");
|
||||
setCurrentStateWrapper(0, UploadState.State.ERROR);
|
||||
// syncUploadStates.get(0).setCurrentState(UploadState.State.ERROR);
|
||||
e.printStackTrace();
|
||||
}
|
||||
mispRequest.addOrganisation(partnerOrganisation, new MispRequest.OrganisationCallback() {
|
||||
@Override
|
||||
public void onResult(JSONObject organisationInformation) {
|
||||
try {
|
||||
|
||||
}
|
||||
Organisation retOrg = new Organisation(organisationInformation);
|
||||
setCurrentStateWrapper(0, UploadState.State.DONE);
|
||||
uploadSyncUser(retOrg.getId());
|
||||
|
||||
@Override
|
||||
public void onError(VolleyError volleyError) {
|
||||
syncUploadStates.get(0).setError(ReadableError.toReadable(volleyError));
|
||||
setCurrentStateWrapper(0, UploadState.State.ERROR);
|
||||
// syncUploadStates.get(0).setCurrentState(UploadState.State.ERROR);
|
||||
}
|
||||
});
|
||||
} catch (JSONException e) {
|
||||
syncUploadStates.get(0).setError("Unknown error: could not read server response");
|
||||
setCurrentStateWrapper(0, UploadState.State.ERROR);
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(VolleyError volleyError) {
|
||||
syncUploadStates.get(0).setError(ReadableError.toReadable(volleyError));
|
||||
setCurrentStateWrapper(0, UploadState.State.ERROR);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void uploadSyncUser(int orgID) {
|
||||
|
||||
setCurrentStateWrapper(1, UploadState.State.IN_PROGRESS);
|
||||
// syncUploadStates.get(1).setCurrentState(UploadState.State.IN_PROGRESS);
|
||||
|
||||
partnerSyncUser.setOrgId(orgID);
|
||||
partnerSyncUser.setAuthkey(TempAuth.TMP_AUTH_KEY);
|
||||
|
@ -152,7 +158,6 @@ public class UploadActivity extends AppCompatActivity implements View.OnClickLis
|
|||
@Override
|
||||
public void onResult(JSONObject myUserInformation) {
|
||||
setCurrentStateWrapper(1, UploadState.State.DONE);
|
||||
// syncUploadStates.get(1).setCurrentState(UploadState.State.DONE);
|
||||
uploadExternalSyncOrganisation();
|
||||
}
|
||||
|
||||
|
@ -160,7 +165,6 @@ public class UploadActivity extends AppCompatActivity implements View.OnClickLis
|
|||
public void onError(VolleyError volleyError) {
|
||||
syncUploadStates.get(1).setError(ReadableError.toReadable(volleyError));
|
||||
setCurrentStateWrapper(1, UploadState.State.ERROR);
|
||||
// syncUploadStates.get(1).setCurrentState(UploadState.State.ERROR);
|
||||
}
|
||||
});
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
package de.overview.wg.its.mispbump.adapter;
|
||||
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
import de.overview.wg.its.mispbump.model.StringPair;
|
||||
import de.overview.wg.its.mispbump.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class OrganisationInfoEntryAdapter extends RecyclerView.Adapter<OrganisationInfoEntryAdapter.MyViewHolder> {
|
||||
|
||||
private Context context;
|
||||
private List<StringPair> list = new ArrayList<>();
|
||||
|
||||
class MyViewHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
View container;
|
||||
TextView title, value;
|
||||
|
||||
private MyViewHolder(View view) {
|
||||
super(view);
|
||||
|
||||
this.title = view.findViewById(R.id.title);
|
||||
this.value = view.findViewById(R.id.value);
|
||||
this.container = view.findViewById(R.id.container);
|
||||
}
|
||||
}
|
||||
|
||||
public OrganisationInfoEntryAdapter(Context context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View row = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_org_info_entry, parent, false);
|
||||
return new OrganisationInfoEntryAdapter.MyViewHolder(row);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull MyViewHolder holder, final int position) {
|
||||
holder.title.setText(list.get(position).key);
|
||||
holder.value.setText(list.get(position).value);
|
||||
|
||||
holder.container.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
ClipData data = ClipData.newPlainText(list.get(position).key, list.get(position).value);
|
||||
ClipboardManager m = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
m.setPrimaryClip(data);
|
||||
|
||||
Toast.makeText(context, context.getText(R.string.copied_to_clipboard), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return list.size();
|
||||
}
|
||||
|
||||
public void setList(List<StringPair> list) {
|
||||
this.list = list;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
package de.overview.wg.its.mispbump.adapter;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v7.widget.CardView;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
import de.overview.wg.its.mispbump.R;
|
||||
import de.overview.wg.its.mispbump.model.SyncedPartner;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class SyncedPartnerAdapter extends RecyclerView.Adapter<SyncedPartnerAdapter.MyViewHolder> {
|
||||
|
||||
private List<SyncedPartner> syncedPartnerList;
|
||||
private Context context;
|
||||
|
||||
class MyViewHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
CardView cardView;
|
||||
TextView title, dateAdded, url;
|
||||
|
||||
MyViewHolder(View view) {
|
||||
super(view);
|
||||
|
||||
cardView = view.findViewById(R.id.card_synced_org);
|
||||
title = view.findViewById(R.id.title);
|
||||
dateAdded = view.findViewById(R.id.dateSynced);
|
||||
url = view.findViewById(R.id.url);
|
||||
}
|
||||
}
|
||||
|
||||
public SyncedPartnerAdapter(Context context, List<SyncedPartner> syncedPartnerList) {
|
||||
this.syncedPartnerList = syncedPartnerList;
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public void setSyncedPartnerList(List<SyncedPartner> syncedPartnerList) {
|
||||
this.syncedPartnerList = syncedPartnerList;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_synced_organisation, parent, false);
|
||||
return new MyViewHolder(itemView);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull final MyViewHolder holder, int position) {
|
||||
final SyncedPartner syncedPartner = syncedPartnerList.get(position);
|
||||
|
||||
holder.title.setText(syncedPartner.getName());
|
||||
holder.url.setText(syncedPartner.getUrl());
|
||||
holder.dateAdded.setText(syncedPartner.getSyncDate());
|
||||
|
||||
holder.cardView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
|
||||
AlertDialog.Builder adb = new AlertDialog.Builder(context);
|
||||
|
||||
adb.setTitle(context.getString(R.string.dialog_open_browser_title));
|
||||
adb.setMessage(context.getString(R.string.dialog_open_in_browser_msg, syncedPartner.getUrl()));
|
||||
|
||||
adb.setPositiveButton(context.getString(R.string.open), new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
Intent browser = new Intent(Intent.ACTION_VIEW, Uri.parse(syncedPartner.getUrl()));
|
||||
context.startActivity(browser);
|
||||
}
|
||||
});
|
||||
|
||||
adb.setNegativeButton(context.getString(android.R.string.cancel), null);
|
||||
adb.create().show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return syncedPartnerList.size();
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package de.overview.wg.its.mispauth.adapter;
|
||||
package de.overview.wg.its.mispbump.adapter;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
|
@ -7,15 +7,15 @@ import android.view.View;
|
|||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
import de.overview.wg.its.mispauth.R;
|
||||
import de.overview.wg.its.mispauth.model.UploadState;
|
||||
import de.overview.wg.its.mispbump.R;
|
||||
import de.overview.wg.its.mispbump.model.UploadState;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class UploadStateAdapter extends RecyclerView.Adapter<UploadStateAdapter.MyViewHolder> {
|
||||
|
||||
private List<UploadState> stateList = new ArrayList<>();
|
||||
private UploadState[] states;
|
||||
|
||||
class MyViewHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
|
@ -64,8 +64,8 @@ public class UploadStateAdapter extends RecyclerView.Adapter<UploadStateAdapter.
|
|||
}
|
||||
}
|
||||
|
||||
public void setStateList(List<UploadState> stateList) {
|
||||
this.stateList = stateList;
|
||||
public void setStates(UploadState[] states) {
|
||||
this.states = states;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
|
@ -78,16 +78,16 @@ public class UploadStateAdapter extends RecyclerView.Adapter<UploadStateAdapter.
|
|||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull UploadStateAdapter.MyViewHolder holder, int position) {
|
||||
UploadState state = stateList.get(position);
|
||||
UploadState state = states[position];
|
||||
|
||||
holder.title.setText(state.getTitle());
|
||||
holder.error.setText(state.getError());
|
||||
holder.setState(stateList.get(position).getCurrentState());
|
||||
holder.error.setText(state.getErrorMessage());
|
||||
holder.setState(states[position].getCurrentState());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return stateList.size();
|
||||
return states.length;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package de.overview.wg.its.mispauth.auxiliary;
|
||||
package de.overview.wg.its.mispbump.auxiliary;
|
||||
|
||||
import android.util.Base64;
|
||||
|
|
@ -1,12 +1,12 @@
|
|||
package de.overview.wg.its.mispauth.auxiliary;
|
||||
package de.overview.wg.its.mispbump.auxiliary;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import de.overview.wg.its.mispauth.model.Organisation;
|
||||
import de.overview.wg.its.mispauth.model.SyncedPartner;
|
||||
import de.overview.wg.its.mispauth.model.User;
|
||||
import de.overview.wg.its.mispbump.model.Organisation;
|
||||
import de.overview.wg.its.mispbump.model.SyncedPartner;
|
||||
import de.overview.wg.its.mispbump.model.User;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
|
@ -104,16 +104,16 @@ public class PreferenceManager {
|
|||
public String getMyServerUrl() {
|
||||
return credentialPreferences.getString(PREF_KEY_SERVER_URL, "");
|
||||
}
|
||||
public void setMyServerUrl(String serverUrl) {
|
||||
public void setServerUrl(String serverUrl) {
|
||||
SharedPreferences.Editor editor = credentialPreferences.edit();
|
||||
editor.putString(PREF_KEY_SERVER_URL, serverUrl);
|
||||
editor.apply();
|
||||
}
|
||||
|
||||
public String getMyServerApiKey() {
|
||||
public String getMyServerAutomationKey() {
|
||||
return credentialPreferences.getString(PREF_KEY_SERVER_API_KEY, "");
|
||||
}
|
||||
public void setMyServerApiKey(String apiKey) {
|
||||
public void setAutomationKey(String apiKey) {
|
||||
SharedPreferences.Editor editor = credentialPreferences.edit();
|
||||
editor.putString(PREF_KEY_SERVER_API_KEY, apiKey);
|
||||
editor.apply();
|
|
@ -1,4 +1,4 @@
|
|||
package de.overview.wg.its.mispauth.auxiliary;
|
||||
package de.overview.wg.its.mispbump.auxiliary;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Locale;
|
|
@ -1,4 +1,4 @@
|
|||
package de.overview.wg.its.mispauth.auxiliary;
|
||||
package de.overview.wg.its.mispbump.auxiliary;
|
||||
|
||||
import com.android.volley.*;
|
||||
import org.json.JSONException;
|
|
@ -1,4 +1,4 @@
|
|||
package de.overview.wg.its.mispauth.auxiliary;
|
||||
package de.overview.wg.its.mispbump.auxiliary;
|
||||
|
||||
public class TempAuth {
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package de.overview.wg.its.mispauth.cam;
|
||||
package de.overview.wg.its.mispbump.cam;
|
||||
|
||||
/*
|
||||
* Copyright 2014 The Android Open Source Project
|
|
@ -0,0 +1,778 @@
|
|||
package de.overview.wg.its.mispbump.cam;
|
||||
|
||||
import android.Manifest;
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.*;
|
||||
import android.hardware.camera2.CameraAccessException;
|
||||
import android.hardware.camera2.CameraCaptureSession;
|
||||
import android.hardware.camera2.CameraCharacteristics;
|
||||
import android.hardware.camera2.CameraDevice;
|
||||
import android.hardware.camera2.CameraManager;
|
||||
import android.hardware.camera2.CaptureRequest;
|
||||
import android.hardware.camera2.params.StreamConfigurationMap;
|
||||
import android.media.Image;
|
||||
import android.media.ImageReader;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.renderscript.*;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.app.ActivityCompat;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.util.Log;
|
||||
import android.util.Size;
|
||||
import android.util.SparseArray;
|
||||
import android.util.SparseIntArray;
|
||||
import android.view.*;
|
||||
import android.widget.Toast;
|
||||
import com.google.android.gms.vision.Frame;
|
||||
import com.google.android.gms.vision.barcode.Barcode;
|
||||
import com.google.android.gms.vision.barcode.BarcodeDetector;
|
||||
import de.overview.wg.its.mispbump.QrSyncActivity;
|
||||
import de.overview.wg.its.mispbump.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Semaphore;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class CameraFragment extends Fragment implements ActivityCompat.OnRequestPermissionsResultCallback {
|
||||
|
||||
private QrSyncActivity parentActivity;
|
||||
|
||||
@Override
|
||||
public void onAttach(Context context) {
|
||||
super.onAttach(context);
|
||||
parentActivity = (QrSyncActivity) context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Conversion from screen rotation to JPEG orientation.
|
||||
*/
|
||||
private static final SparseIntArray ORIENTATIONS = new SparseIntArray();
|
||||
private static final int REQUEST_CAMERA_PERMISSION = 1;
|
||||
private static final String FRAGMENT_DIALOG = "dialog";
|
||||
|
||||
static {
|
||||
ORIENTATIONS.append(Surface.ROTATION_0, 90);
|
||||
ORIENTATIONS.append(Surface.ROTATION_90, 0);
|
||||
ORIENTATIONS.append(Surface.ROTATION_180, 270);
|
||||
ORIENTATIONS.append(Surface.ROTATION_270, 180);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tag for the {@link Log}.
|
||||
*/
|
||||
private static final String TAG = "MISP_LOGGING";
|
||||
|
||||
/**
|
||||
* Max preview width that is guaranteed by Camera2 API
|
||||
*/
|
||||
private static final int MAX_PREVIEW_WIDTH = 1920;
|
||||
|
||||
/**
|
||||
* Max preview height that is guaranteed by Camera2 API
|
||||
*/
|
||||
private static final int MAX_PREVIEW_HEIGHT = 1080;
|
||||
|
||||
/**
|
||||
* {@link TextureView.SurfaceTextureListener} handles several lifecycle events on a
|
||||
* {@link TextureView}.
|
||||
*/
|
||||
private final TextureView.SurfaceTextureListener mSurfaceTextureListener = new TextureView.SurfaceTextureListener() {
|
||||
|
||||
@Override
|
||||
public void onSurfaceTextureAvailable(SurfaceTexture texture, int width, int height) {
|
||||
openCamera(width, height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSurfaceTextureSizeChanged(SurfaceTexture texture, int width, int height) {
|
||||
configureTransform(width, height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onSurfaceTextureDestroyed(SurfaceTexture texture) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSurfaceTextureUpdated(SurfaceTexture texture) {
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* ID of the current {@link CameraDevice}.
|
||||
*/
|
||||
private String mCameraId;
|
||||
|
||||
/**
|
||||
* An {@link AutoFitTextureView} for camera preview.
|
||||
*/
|
||||
private AutoFitTextureView mTextureView;
|
||||
|
||||
/**
|
||||
* A {@link CameraCaptureSession } for camera preview.
|
||||
*/
|
||||
private CameraCaptureSession mCaptureSession;
|
||||
|
||||
/**
|
||||
* A reference to the opened {@link CameraDevice}.
|
||||
*/
|
||||
private CameraDevice mCameraDevice;
|
||||
|
||||
/**
|
||||
* The {@link android.util.Size} of camera preview.
|
||||
*/
|
||||
private Size mPreviewSize;
|
||||
|
||||
/**
|
||||
* {@link CameraDevice.StateCallback} is called when {@link CameraDevice} changes its state.
|
||||
*/
|
||||
private final CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() {
|
||||
|
||||
@Override
|
||||
public void onOpened(@NonNull CameraDevice cameraDevice) {
|
||||
// This method is called when the camera is opened. We start camera preview here.
|
||||
mCameraOpenCloseLock.release();
|
||||
mCameraDevice = cameraDevice;
|
||||
createCameraPreviewSession();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisconnected(@NonNull CameraDevice cameraDevice) {
|
||||
mCameraOpenCloseLock.release();
|
||||
cameraDevice.close();
|
||||
mCameraDevice = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(@NonNull CameraDevice cameraDevice, int error) {
|
||||
mCameraOpenCloseLock.release();
|
||||
cameraDevice.close();
|
||||
mCameraDevice = null;
|
||||
Activity activity = getActivity();
|
||||
if (null != activity) {
|
||||
activity.finish();
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* An additional thread for running tasks that shouldn't block the UI.
|
||||
*/
|
||||
private HandlerThread mBackgroundThread;
|
||||
|
||||
/**
|
||||
* A {@link Handler} for running tasks in the background.
|
||||
*/
|
||||
private Handler mBackgroundHandler;
|
||||
|
||||
/**
|
||||
* An {@link ImageReader} that handles still image capture.
|
||||
*/
|
||||
private ImageReader mImageReader;
|
||||
|
||||
/**
|
||||
* This a callback object for the {@link ImageReader}. "onImageAvailable" will be called when a
|
||||
* still image is ready to be saved.
|
||||
*/
|
||||
private final ImageReader.OnImageAvailableListener mOnImageAvailableListener = new ImageReader.OnImageAvailableListener() {
|
||||
@Override
|
||||
public void onImageAvailable(ImageReader reader) {
|
||||
|
||||
Image image = reader.acquireNextImage();
|
||||
Bitmap bitmap = YUV2Bitmap(image);
|
||||
|
||||
if (bitmap != null && readQrEnabled) {
|
||||
|
||||
Frame frame = new Frame.Builder().setBitmap(bitmap).build();
|
||||
SparseArray<Barcode> barcodes = barcodeDetector.detect(frame);
|
||||
|
||||
if (barcodes.size() > 0) {
|
||||
parentActivity.onReadQrCode(barcodes.valueAt(0).rawValue);
|
||||
}
|
||||
}
|
||||
|
||||
if (image != null) {
|
||||
image.close();
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* {@link CaptureRequest.Builder} for the camera preview
|
||||
*/
|
||||
private CaptureRequest.Builder mPreviewRequestBuilder;
|
||||
|
||||
/**
|
||||
* {@link CaptureRequest} generated by {@link #mPreviewRequestBuilder}
|
||||
*/
|
||||
private CaptureRequest mPreviewRequest;
|
||||
|
||||
/**
|
||||
* A {@link Semaphore} to prevent the app from exiting before closing the camera.
|
||||
*/
|
||||
private Semaphore mCameraOpenCloseLock = new Semaphore(1);
|
||||
|
||||
/**
|
||||
* Shows a {@link Toast} on the UI thread.
|
||||
*
|
||||
* @param text The message to show
|
||||
*/
|
||||
private void showToast(final String text) {
|
||||
final Activity activity = getActivity();
|
||||
if (activity != null) {
|
||||
activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Toast.makeText(activity, text, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given {@code choices} of {@code Size}s supported by a camera, choose the smallest one that
|
||||
* is at least as large as the respective texture view size, and that is at most as large as the
|
||||
* respective max size, and whose aspect ratio matches with the specified value. If such size
|
||||
* doesn't exist, choose the largest one that is at most as large as the respective max size,
|
||||
* and whose aspect ratio matches with the specified value.
|
||||
*
|
||||
* @param choices The list of sizes that the camera supports for the intended output
|
||||
* class
|
||||
* @param textureViewWidth The width of the texture view relative to sensor coordinate
|
||||
* @param textureViewHeight The height of the texture view relative to sensor coordinate
|
||||
* @param maxWidth The maximum width that can be chosen
|
||||
* @param maxHeight The maximum height that can be chosen
|
||||
* @param aspectRatio The aspect ratio
|
||||
* @return The optimal {@code Size}, or an arbitrary one if none were big enough
|
||||
*/
|
||||
private static Size chooseOptimalSize(Size[] choices, int textureViewWidth, int textureViewHeight, int maxWidth, int maxHeight, Size aspectRatio) {
|
||||
|
||||
// Collect the supported resolutions that are at least as big as the preview Surface
|
||||
List<Size> bigEnough = new ArrayList<>();
|
||||
// Collect the supported resolutions that are smaller than the preview Surface
|
||||
List<Size> notBigEnough = new ArrayList<>();
|
||||
int w = aspectRatio.getWidth();
|
||||
int h = aspectRatio.getHeight();
|
||||
for (Size option : choices) {
|
||||
if (option.getWidth() <= maxWidth && option.getHeight() <= maxHeight && option.getHeight() == option.getWidth() * h / w) {
|
||||
if (option.getWidth() >= textureViewWidth && option.getHeight() >= textureViewHeight) {
|
||||
bigEnough.add(option);
|
||||
} else {
|
||||
notBigEnough.add(option);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Pick the smallest of those big enough. If there is no one big enough, pick the
|
||||
// largest of those not big enough.
|
||||
if (bigEnough.size() > 0) {
|
||||
return Collections.min(bigEnough, new CompareSizesByArea());
|
||||
} else if (notBigEnough.size() > 0) {
|
||||
return Collections.max(notBigEnough, new CompareSizesByArea());
|
||||
} else {
|
||||
Log.e(TAG, "Couldn't find any suitable preview size");
|
||||
return choices[0];
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
|
||||
View v = inflater.inflate(R.layout.fragment_camera, container, false);
|
||||
|
||||
initRenderScript();
|
||||
|
||||
setUpBarcodeDetector();
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(final View view, Bundle savedInstanceState) {
|
||||
mTextureView = view.findViewById(R.id.texture);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
startBackgroundThread();
|
||||
|
||||
// When the screen is turned off and turned back on, the SurfaceTexture is already
|
||||
// available, and "onSurfaceTextureAvailable" will not be called. In that case, we can open
|
||||
// a camera and start preview from here (otherwise, we wait until the surface is ready in
|
||||
// the SurfaceTextureListener).
|
||||
if (mTextureView.isAvailable()) {
|
||||
openCamera(mTextureView.getWidth(), mTextureView.getHeight());
|
||||
} else {
|
||||
mTextureView.setSurfaceTextureListener(mSurfaceTextureListener);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
closeCamera();
|
||||
stopBackgroundThread();
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
private void requestCameraPermission() {
|
||||
if (shouldShowRequestPermissionRationale(Manifest.permission.CAMERA)) {
|
||||
new ConfirmationDialog().show(getChildFragmentManager(), FRAGMENT_DIALOG);
|
||||
} else {
|
||||
requestPermissions(new String[]{Manifest.permission.CAMERA}, REQUEST_CAMERA_PERMISSION);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||
if (requestCode == REQUEST_CAMERA_PERMISSION) {
|
||||
if (grantResults.length != 1 || grantResults[0] != PackageManager.PERMISSION_GRANTED) {
|
||||
ErrorDialog.newInstance("REQUEST PERMISSION").show(getChildFragmentManager(), FRAGMENT_DIALOG);
|
||||
}
|
||||
} else {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up member variables related to camera.
|
||||
*
|
||||
* @param width The width of available size for camera preview
|
||||
* @param height The height of available size for camera preview
|
||||
*/
|
||||
@SuppressWarnings("SuspiciousNameCombination")
|
||||
private void setUpCameraOutputs(int width, int height) {
|
||||
Activity activity = getActivity();
|
||||
CameraManager manager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);
|
||||
|
||||
try {
|
||||
for (String cameraId : manager.getCameraIdList()) {
|
||||
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
|
||||
|
||||
// We don't use a front facing camera in this sample.
|
||||
Integer facing = characteristics.get(CameraCharacteristics.LENS_FACING);
|
||||
if (facing != null && facing == CameraCharacteristics.LENS_FACING_FRONT) {
|
||||
continue;
|
||||
}
|
||||
|
||||
StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
|
||||
if (map == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// For still image captures, we use the largest available size.
|
||||
Size largest = Collections.max(Arrays.asList(map.getOutputSizes(ImageFormat.YUV_420_888)), new CompareSizesByArea());
|
||||
|
||||
mImageReader = ImageReader.newInstance(largest.getWidth() / 16, largest.getHeight() / 16, ImageFormat.YUV_420_888, 2);
|
||||
mImageReader.setOnImageAvailableListener(mOnImageAvailableListener, mBackgroundHandler);
|
||||
|
||||
// Find out if we need to swap dimension to get the preview size relative to sensor coordinate.
|
||||
int displayRotation = activity.getWindowManager().getDefaultDisplay().getRotation();
|
||||
//noinspection ConstantConditions
|
||||
int mSensorOrientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
|
||||
boolean swappedDimensions = false;
|
||||
switch (displayRotation) {
|
||||
case Surface.ROTATION_0:
|
||||
case Surface.ROTATION_180:
|
||||
if (mSensorOrientation == 90 || mSensorOrientation == 270) {
|
||||
swappedDimensions = true;
|
||||
}
|
||||
break;
|
||||
case Surface.ROTATION_90:
|
||||
case Surface.ROTATION_270:
|
||||
if (mSensorOrientation == 0 || mSensorOrientation == 180) {
|
||||
swappedDimensions = true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Log.e(TAG, "Display rotation is invalid: " + displayRotation);
|
||||
}
|
||||
|
||||
Point displaySize = new Point();
|
||||
activity.getWindowManager().getDefaultDisplay().getSize(displaySize);
|
||||
|
||||
int rotatedPreviewWidth = width;
|
||||
int rotatedPreviewHeight = height;
|
||||
int maxPreviewWidth = displaySize.x;
|
||||
int maxPreviewHeight = displaySize.y;
|
||||
|
||||
if (swappedDimensions) {
|
||||
rotatedPreviewWidth = height;
|
||||
rotatedPreviewHeight = width;
|
||||
maxPreviewWidth = displaySize.y;
|
||||
maxPreviewHeight = displaySize.x;
|
||||
}
|
||||
|
||||
if (maxPreviewWidth > MAX_PREVIEW_WIDTH) {
|
||||
maxPreviewWidth = MAX_PREVIEW_WIDTH;
|
||||
}
|
||||
|
||||
if (maxPreviewHeight > MAX_PREVIEW_HEIGHT) {
|
||||
maxPreviewHeight = MAX_PREVIEW_HEIGHT;
|
||||
}
|
||||
|
||||
// Danger, W.R.! Attempting to use too large a preview size could exceed the camera
|
||||
// bus' bandwidth limitation, resulting in gorgeous previews but the storage of
|
||||
// garbage capture data.
|
||||
mPreviewSize = chooseOptimalSize(map.getOutputSizes(SurfaceTexture.class),
|
||||
rotatedPreviewWidth, rotatedPreviewHeight, maxPreviewWidth,
|
||||
maxPreviewHeight, largest);
|
||||
|
||||
// We fit the aspect ratio of TextureView to the size of preview we picked.
|
||||
int orientation = getResources().getConfiguration().orientation;
|
||||
if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
|
||||
mTextureView.setAspectRatio(mPreviewSize.getWidth(), mPreviewSize.getHeight());
|
||||
} else {
|
||||
mTextureView.setAspectRatio(mPreviewSize.getHeight(), mPreviewSize.getWidth());
|
||||
}
|
||||
|
||||
mCameraId = cameraId;
|
||||
return;
|
||||
}
|
||||
} catch (CameraAccessException e) {
|
||||
e.printStackTrace();
|
||||
} catch (NullPointerException e) {
|
||||
// Currently an NPE is thrown when the Camera2API is used but not supported on the
|
||||
// device this code runs.
|
||||
ErrorDialog.newInstance("CAMERA ERROR").show(getChildFragmentManager(), FRAGMENT_DIALOG);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the camera specified by {@link CameraFragment#mCameraId}.
|
||||
*/
|
||||
private void openCamera(int width, int height) {
|
||||
|
||||
if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
|
||||
requestCameraPermission();
|
||||
return;
|
||||
}
|
||||
|
||||
setUpCameraOutputs(width, height);
|
||||
configureTransform(width, height);
|
||||
|
||||
Activity activity = getActivity();
|
||||
CameraManager manager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);
|
||||
|
||||
try {
|
||||
|
||||
if (!mCameraOpenCloseLock.tryAcquire(2500, TimeUnit.MILLISECONDS)) {
|
||||
throw new RuntimeException("Time out waiting to lock camera opening.");
|
||||
}
|
||||
|
||||
manager.openCamera(mCameraId, mStateCallback, mBackgroundHandler);
|
||||
} catch (CameraAccessException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException("Interrupted while trying to lock camera opening.", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the current {@link CameraDevice}.
|
||||
*/
|
||||
private void closeCamera() {
|
||||
try {
|
||||
mCameraOpenCloseLock.acquire();
|
||||
|
||||
if (null != mCaptureSession) {
|
||||
mCaptureSession.close();
|
||||
mCaptureSession = null;
|
||||
}
|
||||
|
||||
if (null != mCameraDevice) {
|
||||
mCameraDevice.close();
|
||||
mCameraDevice = null;
|
||||
}
|
||||
|
||||
if (null != mImageReader) {
|
||||
mImageReader.close();
|
||||
mImageReader = null;
|
||||
}
|
||||
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException("Interrupted while trying to lock camera closing.", e);
|
||||
} finally {
|
||||
mCameraOpenCloseLock.release();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a background thread and its {@link Handler}.
|
||||
*/
|
||||
private void startBackgroundThread() {
|
||||
mBackgroundThread = new HandlerThread("CameraBackground");
|
||||
mBackgroundThread.start();
|
||||
mBackgroundHandler = new Handler(mBackgroundThread.getLooper());
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops the background thread and its {@link Handler}.
|
||||
*/
|
||||
private void stopBackgroundThread() {
|
||||
mBackgroundThread.quitSafely();
|
||||
try {
|
||||
mBackgroundThread.join();
|
||||
mBackgroundThread = null;
|
||||
mBackgroundHandler = null;
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link CameraCaptureSession} for camera preview.
|
||||
*/
|
||||
private void createCameraPreviewSession() {
|
||||
try {
|
||||
SurfaceTexture texture = mTextureView.getSurfaceTexture();
|
||||
assert texture != null;
|
||||
|
||||
// We configure the size of default buffer to be the size of camera preview we want.
|
||||
texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
|
||||
|
||||
// This is the output Surface we need to start preview.
|
||||
Surface surface = new Surface(texture);
|
||||
Surface mImageSurface = mImageReader.getSurface();
|
||||
|
||||
// We set up a CaptureRequest.Builder with the output Surface.
|
||||
mPreviewRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
|
||||
mPreviewRequestBuilder.addTarget(surface);
|
||||
mPreviewRequestBuilder.addTarget(mImageSurface);
|
||||
|
||||
// Here, we create a CameraCaptureSession for camera preview.
|
||||
mCameraDevice.createCaptureSession(Arrays.asList(surface, mImageReader.getSurface()),
|
||||
new CameraCaptureSession.StateCallback() {
|
||||
|
||||
@Override
|
||||
public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) {
|
||||
// The camera is already closed
|
||||
if (null == mCameraDevice) {
|
||||
return;
|
||||
}
|
||||
|
||||
// When the session is ready, we start displaying the preview.
|
||||
mCaptureSession = cameraCaptureSession;
|
||||
try {
|
||||
// Auto focus should be continuous for camera preview.
|
||||
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
|
||||
|
||||
// Finally, we start displaying the camera preview.
|
||||
mPreviewRequest = mPreviewRequestBuilder.build();
|
||||
mCaptureSession.setRepeatingRequest(mPreviewRequest, null, mBackgroundHandler);
|
||||
} catch (CameraAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) {
|
||||
showToast("Failed");
|
||||
}
|
||||
}, null
|
||||
);
|
||||
} catch (CameraAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the necessary {@link android.graphics.Matrix} transformation to `mTextureView`.
|
||||
* This method should be called after the camera preview size is determined in
|
||||
* setUpCameraOutputs and also the size of `mTextureView` is fixed.
|
||||
*
|
||||
* @param viewWidth The width of `mTextureView`
|
||||
* @param viewHeight The height of `mTextureView`
|
||||
*/
|
||||
private void configureTransform(int viewWidth, int viewHeight) {
|
||||
Activity activity = getActivity();
|
||||
|
||||
if (null == mTextureView || null == mPreviewSize || null == activity) {
|
||||
return;
|
||||
}
|
||||
|
||||
int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
|
||||
Matrix matrix = new Matrix();
|
||||
RectF viewRect = new RectF(0, 0, viewWidth, viewHeight);
|
||||
RectF bufferRect = new RectF(0, 0, mPreviewSize.getHeight(), mPreviewSize.getWidth());
|
||||
float centerX = viewRect.centerX();
|
||||
float centerY = viewRect.centerY();
|
||||
if (Surface.ROTATION_90 == rotation || Surface.ROTATION_270 == rotation) {
|
||||
bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY());
|
||||
matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL);
|
||||
float scale = Math.max(
|
||||
(float) viewHeight / mPreviewSize.getHeight(),
|
||||
(float) viewWidth / mPreviewSize.getWidth());
|
||||
matrix.postScale(scale, scale, centerX, centerY);
|
||||
matrix.postRotate(90 * (rotation - 2), centerX, centerY);
|
||||
} else if (Surface.ROTATION_180 == rotation) {
|
||||
matrix.postRotate(180, centerX, centerY);
|
||||
}
|
||||
mTextureView.setTransform(matrix);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two {@code Size}s based on their areas.
|
||||
*/
|
||||
static class CompareSizesByArea implements Comparator<Size> {
|
||||
|
||||
@Override
|
||||
public int compare(Size lhs, Size rhs) {
|
||||
// We cast here to ensure the multiplications won't overflow
|
||||
return Long.signum((long) lhs.getWidth() * lhs.getHeight() - (long) rhs.getWidth() * rhs.getHeight());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Shows an error message dialog.
|
||||
*/
|
||||
public static class ErrorDialog extends DialogFragment {
|
||||
|
||||
private static final String ARG_MESSAGE = "message";
|
||||
|
||||
public static ErrorDialog newInstance(String message) {
|
||||
ErrorDialog dialog = new ErrorDialog();
|
||||
Bundle args = new Bundle();
|
||||
args.putString(ARG_MESSAGE, message);
|
||||
dialog.setArguments(args);
|
||||
return dialog;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
final Activity activity = getActivity();
|
||||
return new AlertDialog.Builder(activity)
|
||||
.setMessage(getArguments().getString(ARG_MESSAGE))
|
||||
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialogInterface, int i) {
|
||||
activity.finish();
|
||||
}
|
||||
})
|
||||
.create();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows OK/Cancel confirmation dialog about camera permission.
|
||||
*/
|
||||
public static class ConfirmationDialog extends DialogFragment {
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
final Fragment parent = getParentFragment();
|
||||
return new AlertDialog.Builder(getActivity())
|
||||
.setMessage("REQUEST PERMISSION")
|
||||
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
parent.requestPermissions(new String[]{Manifest.permission.CAMERA}, REQUEST_CAMERA_PERMISSION);
|
||||
}
|
||||
})
|
||||
.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
Activity activity = parent.getActivity();
|
||||
if (activity != null) {
|
||||
activity.finish();
|
||||
}
|
||||
}
|
||||
})
|
||||
.create();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private boolean readQrEnabled = true;
|
||||
private BarcodeDetector barcodeDetector;
|
||||
private RenderScript renderScript;
|
||||
|
||||
private void initRenderScript() {
|
||||
renderScript = RenderScript.create(getActivity());
|
||||
}
|
||||
|
||||
private Bitmap YUV2Bitmap(Image image) {
|
||||
|
||||
if (image == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ScriptIntrinsicYuvToRGB yuvToRgbIntrinsic = ScriptIntrinsicYuvToRGB.create(renderScript, Element.U8_4(renderScript));
|
||||
|
||||
int W = image.getWidth();
|
||||
int H = image.getHeight();
|
||||
|
||||
Image.Plane Y = image.getPlanes()[0];
|
||||
Image.Plane U = image.getPlanes()[1];
|
||||
Image.Plane V = image.getPlanes()[2];
|
||||
|
||||
int Yb = Y.getBuffer().remaining();
|
||||
int Ub = U.getBuffer().remaining();
|
||||
int Vb = V.getBuffer().remaining();
|
||||
|
||||
byte[] data = new byte[Yb + Ub + Vb];
|
||||
|
||||
Y.getBuffer().get(data, 0, Yb);
|
||||
V.getBuffer().get(data, Yb, Vb);
|
||||
U.getBuffer().get(data, Yb + Vb, Ub);
|
||||
|
||||
Type.Builder yuvType = new Type.Builder(renderScript, Element.U8(renderScript)).setX(data.length);
|
||||
Allocation in = Allocation.createTyped(renderScript, yuvType.create(), Allocation.USAGE_SCRIPT);
|
||||
|
||||
Type.Builder rgbaType = new Type.Builder(renderScript, Element.RGBA_8888(renderScript)).setX(W).setY(H);
|
||||
Allocation out = Allocation.createTyped(renderScript, rgbaType.create(), Allocation.USAGE_SCRIPT);
|
||||
|
||||
final Bitmap bmpout = Bitmap.createBitmap(W, H, Bitmap.Config.ARGB_8888);
|
||||
|
||||
in.copyFromUnchecked(data);
|
||||
|
||||
yuvToRgbIntrinsic.setInput(in);
|
||||
yuvToRgbIntrinsic.forEach(out);
|
||||
|
||||
out.copyTo(bmpout);
|
||||
image.close();
|
||||
|
||||
return bmpout;
|
||||
}
|
||||
|
||||
public void setReadQrEnabled(boolean enabled) {
|
||||
readQrEnabled = enabled;
|
||||
}
|
||||
|
||||
private void setUpBarcodeDetector() {
|
||||
barcodeDetector = new BarcodeDetector.Builder(getActivity())
|
||||
.setBarcodeFormats(Barcode.QR_CODE)
|
||||
.build();
|
||||
|
||||
if (!barcodeDetector.isOperational()) {
|
||||
Toast.makeText(getActivity(), "Could not setup QR-Code scanner!", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package de.overview.wg.its.mispauth.model;
|
||||
package de.overview.wg.its.mispbump.model;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
|
@ -1,4 +1,4 @@
|
|||
package de.overview.wg.its.mispauth.model;
|
||||
package de.overview.wg.its.mispbump.model;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
|
@ -1,4 +1,4 @@
|
|||
package de.overview.wg.its.mispauth.model;
|
||||
package de.overview.wg.its.mispbump.model;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
|
@ -1,4 +1,4 @@
|
|||
package de.overview.wg.its.mispauth.model;
|
||||
package de.overview.wg.its.mispbump.model;
|
||||
|
||||
public class StringPair {
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package de.overview.wg.its.mispauth.model;
|
||||
package de.overview.wg.its.mispbump.model;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
|
@ -1,4 +1,4 @@
|
|||
package de.overview.wg.its.mispauth.model;
|
||||
package de.overview.wg.its.mispbump.model;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package de.overview.wg.its.mispauth.model;
|
||||
package de.overview.wg.its.mispbump.model;
|
||||
|
||||
public class UploadState {
|
||||
|
||||
|
@ -16,7 +16,6 @@ public class UploadState {
|
|||
this.title = title;
|
||||
}
|
||||
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
@ -24,18 +23,25 @@ public class UploadState {
|
|||
this.title = title;
|
||||
}
|
||||
|
||||
public String getError() {
|
||||
public String getErrorMessage() {
|
||||
return error;
|
||||
}
|
||||
public void setError(String error) {
|
||||
this.error = error;
|
||||
this.currentState = State.ERROR;
|
||||
}
|
||||
public void setDone() {
|
||||
this.currentState = State.DONE;
|
||||
}
|
||||
public void setInProgress() {
|
||||
this.currentState = State.IN_PROGRESS;
|
||||
}
|
||||
public void setPending() {
|
||||
this.currentState = State.PENDING;
|
||||
}
|
||||
|
||||
public State getCurrentState() {
|
||||
return currentState;
|
||||
}
|
||||
public void setCurrentState(State currentState) {
|
||||
this.currentState = currentState;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package de.overview.wg.its.mispauth.model;
|
||||
package de.overview.wg.its.mispbump.model;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
|
@ -1,4 +1,4 @@
|
|||
package de.overview.wg.its.mispauth.network;
|
||||
package de.overview.wg.its.mispbump.network;
|
||||
|
||||
import com.android.volley.NetworkResponse;
|
||||
import com.android.volley.ParseError;
|
|
@ -1,37 +1,21 @@
|
|||
package de.overview.wg.its.mispauth.network;
|
||||
package de.overview.wg.its.mispbump.network;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.Log;
|
||||
import com.android.volley.Request;
|
||||
import com.android.volley.RequestQueue;
|
||||
import com.android.volley.Response;
|
||||
import com.android.volley.VolleyError;
|
||||
import com.android.volley.toolbox.HurlStack;
|
||||
import com.android.volley.toolbox.JsonObjectRequest;
|
||||
import com.android.volley.toolbox.Volley;
|
||||
import de.overview.wg.its.mispauth.R;
|
||||
import de.overview.wg.its.mispauth.auxiliary.PreferenceManager;
|
||||
import de.overview.wg.its.mispauth.auxiliary.ReadableError;
|
||||
import de.overview.wg.its.mispauth.model.Organisation;
|
||||
import de.overview.wg.its.mispauth.model.Server;
|
||||
import de.overview.wg.its.mispauth.model.User;
|
||||
import de.overview.wg.its.mispbump.auxiliary.PreferenceManager;
|
||||
import de.overview.wg.its.mispbump.model.Organisation;
|
||||
import de.overview.wg.its.mispbump.model.Server;
|
||||
import de.overview.wg.its.mispbump.model.User;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import javax.net.ssl.*;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -44,7 +28,7 @@ public class MispRequest {
|
|||
|
||||
private RequestQueue requestQueue;
|
||||
private PreferenceManager preferenceManager;
|
||||
private String serverUrl, apiKey;
|
||||
private String serverUrl, automationKey;
|
||||
|
||||
/**
|
||||
* @param context for Volley and PreferenceManager
|
||||
|
@ -60,9 +44,33 @@ public class MispRequest {
|
|||
|
||||
private void loadSavedCredentials() {
|
||||
serverUrl = preferenceManager.getMyServerUrl();
|
||||
apiKey = preferenceManager.getMyServerApiKey();
|
||||
automationKey = preferenceManager.getMyServerAutomationKey();
|
||||
}
|
||||
|
||||
public void testConnection(final ConnectionCallback callback) {
|
||||
Response.Listener<JSONObject> listener = new Response.Listener<JSONObject>() {
|
||||
@Override
|
||||
public void onResponse(JSONObject response) {
|
||||
callback.onResult(true);
|
||||
}
|
||||
};
|
||||
|
||||
Response.ErrorListener errorListener = new Response.ErrorListener() {
|
||||
@Override
|
||||
public void onErrorResponse(VolleyError error) {
|
||||
callback.onResult(false);
|
||||
}
|
||||
};
|
||||
|
||||
Request r = objectRequest(Request.Method.GET,
|
||||
serverUrl + "/servers/getPyMISPVersion.json",
|
||||
null,
|
||||
listener,
|
||||
errorListener);
|
||||
|
||||
requestQueue.add(r);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param orgId organisation ID on the MISP-Instance
|
||||
* @param callback returns a single Organisation-JSON
|
||||
|
@ -126,7 +134,7 @@ public class MispRequest {
|
|||
}
|
||||
};
|
||||
|
||||
if (serverUrl.isEmpty() || apiKey.isEmpty()) {
|
||||
if (serverUrl.isEmpty() || automationKey.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -289,7 +297,7 @@ public class MispRequest {
|
|||
public Map<String, String> getHeaders() {
|
||||
Map<String, String> params = new HashMap<>();
|
||||
|
||||
params.put("Authorization", apiKey);
|
||||
params.put("Authorization", automationKey);
|
||||
params.put("Accept", "application/json");
|
||||
params.put("Content-Type", "application/json; utf-8");
|
||||
|
||||
|
@ -308,7 +316,7 @@ public class MispRequest {
|
|||
public Map<String, String> getHeaders() {
|
||||
Map<String, String> params = new HashMap<>();
|
||||
|
||||
params.put("Authorization", apiKey);
|
||||
params.put("Authorization", automationKey);
|
||||
params.put("Accept", "application/json");
|
||||
params.put("Content-Type", "application/json; utf-8");
|
||||
|
||||
|
@ -317,9 +325,9 @@ public class MispRequest {
|
|||
};
|
||||
}
|
||||
|
||||
public void setServerCredentials(String serverUrl, String apiKey) {
|
||||
public void setServerCredentials(String serverUrl, String automationKey) {
|
||||
this.serverUrl = serverUrl;
|
||||
this.apiKey = apiKey;
|
||||
this.automationKey = automationKey;
|
||||
}
|
||||
|
||||
public static MispRequest Instance(Context context, boolean loadSavedCredentials) {
|
||||
|
@ -331,6 +339,10 @@ public class MispRequest {
|
|||
return instance;
|
||||
}
|
||||
|
||||
|
||||
public interface ConnectionCallback {
|
||||
void onResult(boolean connected);
|
||||
}
|
||||
public interface OrganisationsCallback {
|
||||
void onResult(JSONArray organisations);
|
||||
void onError(VolleyError volleyError);
|
|
@ -0,0 +1,5 @@
|
|||
<vector android:height="24dp" android:tint="#FFFFFF"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#FF000000" android:pathData="M12,4l-1.41,1.41L16.17,11H4v2h12.17l-5.58,5.59L12,20l8,-8z"/>
|
||||
</vector>
|
|
@ -0,0 +1,5 @@
|
|||
<vector android:height="24dp" android:tint="#FFFFFF"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#FF000000" android:pathData="M19.35,10.04C18.67,6.59 15.64,4 12,4 9.11,4 6.6,5.64 5.35,8.04 2.34,8.36 0,10.91 0,14c0,3.31 2.69,6 6,6h13c2.76,0 5,-2.24 5,-5 0,-2.64 -2.05,-4.78 -4.65,-4.96z"/>
|
||||
</vector>
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M12,6v3l4,-4 -4,-4v3c-4.42,0 -8,3.58 -8,8 0,1.57 0.46,3.03 1.24,4.26L6.7,14.8c-0.45,-0.83 -0.7,-1.79 -0.7,-2.8 0,-3.31 2.69,-6 6,-6zM18.76,7.74L17.3,9.2c0.44,0.84 0.7,1.79 0.7,2.8 0,3.31 -2.69,6 -6,6v-3l-4,4 4,4v-3c4.42,0 8,-3.58 8,-8 0,-1.57 -0.46,-3.03 -1.24,-4.26z"/>
|
||||
</vector>
|
|
@ -4,6 +4,6 @@
|
|||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:fillColor="#FFFFFFFF"
|
||||
android:pathData="M19.43,12.98c0.04,-0.32 0.07,-0.64 0.07,-0.98s-0.03,-0.66 -0.07,-0.98l2.11,-1.65c0.19,-0.15 0.24,-0.42 0.12,-0.64l-2,-3.46c-0.12,-0.22 -0.39,-0.3 -0.61,-0.22l-2.49,1c-0.52,-0.4 -1.08,-0.73 -1.69,-0.98l-0.38,-2.65C14.46,2.18 14.25,2 14,2h-4c-0.25,0 -0.46,0.18 -0.49,0.42l-0.38,2.65c-0.61,0.25 -1.17,0.59 -1.69,0.98l-2.49,-1c-0.23,-0.09 -0.49,0 -0.61,0.22l-2,3.46c-0.13,0.22 -0.07,0.49 0.12,0.64l2.11,1.65c-0.04,0.32 -0.07,0.65 -0.07,0.98s0.03,0.66 0.07,0.98l-2.11,1.65c-0.19,0.15 -0.24,0.42 -0.12,0.64l2,3.46c0.12,0.22 0.39,0.3 0.61,0.22l2.49,-1c0.52,0.4 1.08,0.73 1.69,0.98l0.38,2.65c0.03,0.24 0.24,0.42 0.49,0.42h4c0.25,0 0.46,-0.18 0.49,-0.42l0.38,-2.65c0.61,-0.25 1.17,-0.59 1.69,-0.98l2.49,1c0.23,0.09 0.49,0 0.61,-0.22l2,-3.46c0.12,-0.22 0.07,-0.49 -0.12,-0.64l-2.11,-1.65zM12,15.5c-1.93,0 -3.5,-1.57 -3.5,-3.5s1.57,-3.5 3.5,-3.5 3.5,1.57 3.5,3.5 -1.57,3.5 -3.5,3.5z"/>
|
||||
</vector>
|
||||
|
|
|
@ -3,12 +3,8 @@
|
|||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
|
||||
<!--<stroke-->
|
||||
<!--android:color="#000"-->
|
||||
<!--android:width="4dp"/>-->
|
||||
|
||||
<solid
|
||||
android:color="@color/colorWhite"/>
|
||||
android:color="#80FFFFFF"/>
|
||||
|
||||
<corners
|
||||
android:radius="10dp"/>
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
|
||||
<android.support.design.widget.TextInputLayout
|
||||
android:background="@color/colorPrimary"
|
||||
android:id="@+id/input_layout_api_key"
|
||||
android:id="@+id/input_layout_automation_key"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingLeft="16dp"
|
||||
android:paddingRight="16dp"
|
||||
|
@ -70,41 +70,14 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<!--<include-->
|
||||
<!--android:layout_width="0dp"-->
|
||||
<!--android:layout_height="0dp"-->
|
||||
<!--layout="@layout/view_organisation"-->
|
||||
<!--app:layout_constraintStart_toStartOf="parent"-->
|
||||
<!--android:layout_marginStart="16dp"-->
|
||||
<!--app:layout_constraintTop_toTopOf="parent"-->
|
||||
<!--android:layout_marginTop="32dp"-->
|
||||
<!--app:layout_constraintEnd_toEndOf="parent"-->
|
||||
<!--android:layout_marginEnd="16dp"-->
|
||||
<!--app:layout_constraintBottom_toBottomOf="parent"-->
|
||||
<!--android:layout_marginBottom="16dp"/>-->
|
||||
|
||||
<!--<TextView-->
|
||||
<!--android:id="@+id/org_title"-->
|
||||
<!--android:layout_width="match_parent"-->
|
||||
<!--android:layout_height="wrap_content"-->
|
||||
<!--android:layout_marginTop="32dp"-->
|
||||
<!--app:layout_constraintStart_toStartOf="parent"-->
|
||||
<!--app:layout_constraintEnd_toEndOf="parent"-->
|
||||
<!--app:layout_constraintTop_toTopOf="parent"-->
|
||||
<!--tools:text="Organisation A"-->
|
||||
<!--android:textAppearance="@android:style/TextAppearance.Material.Title"-->
|
||||
<!--android:textAlignment="center"/>-->
|
||||
|
||||
<android.support.v7.widget.RecyclerView
|
||||
android:id="@+id/recyclerView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="parent"
|
||||
>
|
||||
|
||||
</android.support.v7.widget.RecyclerView>
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/empty"
|
||||
|
|
|
@ -40,7 +40,8 @@
|
|||
android:id="@+id/empty"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/empty_sync_list" app:layout_constraintEnd_toEndOf="parent"
|
||||
android:text="@string/empty_sync_list"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:layout_marginEnd="8dp" app:layout_constraintStart_toStartOf="parent"
|
||||
android:layout_marginStart="8dp" app:layout_constraintBottom_toBottomOf="parent"
|
||||
android:layout_marginBottom="8dp" app:layout_constraintTop_toTopOf="parent"
|
||||
|
@ -49,7 +50,7 @@
|
|||
</android.support.constraint.ConstraintLayout>
|
||||
|
||||
<android.support.design.widget.FloatingActionButton
|
||||
android:id="@+id/fab"
|
||||
android:id="@+id/fab_continue_sync_info"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:fabSize="normal"
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<android.support.design.widget.CoordinatorLayout
|
||||
android:id="@+id/coordinator"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".MyOrganisationActivity">
|
||||
|
||||
<android.support.design.widget.AppBarLayout
|
||||
android:id="@+id/appbar"
|
||||
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="?android:attr/actionBarSize"
|
||||
app:popupTheme="@style/AppTheme.PopupOverlay"/>
|
||||
|
||||
</android.support.design.widget.AppBarLayout>
|
||||
|
||||
<android.support.constraint.ConstraintLayout
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progressBar"
|
||||
android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintEnd_toEndOf="parent"
|
||||
android:layout_marginEnd="8dp" app:layout_constraintStart_toStartOf="parent" android:layout_marginStart="8dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent" android:layout_marginBottom="8dp"
|
||||
app:layout_constraintTop_toTopOf="parent" android:layout_marginTop="8dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/empty"
|
||||
android:layout_width="wrap_content" android:layout_height="wrap_content"
|
||||
android:text="@string/empty_my_org" app:layout_constraintEnd_toEndOf="parent" android:layout_marginEnd="8dp"
|
||||
app:layout_constraintStart_toStartOf="parent" android:layout_marginStart="8dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent" android:layout_marginBottom="8dp"
|
||||
app:layout_constraintTop_toTopOf="parent" android:layout_marginTop="8dp"/>
|
||||
|
||||
<android.support.v7.widget.RecyclerView
|
||||
android:id="@+id/recyclerView"
|
||||
android:layout_width="match_parent" android:layout_height="match_parent"
|
||||
app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintTop_toTopOf="parent"/>
|
||||
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
|
||||
<android.support.design.widget.FloatingActionButton
|
||||
android:id="@+id/fab_download"
|
||||
android:layout_width="wrap_content" android:layout_height="wrap_content"
|
||||
android:layout_margin="16dp"
|
||||
android:layout_gravity="bottom|end"
|
||||
app:fabSize="normal"
|
||||
android:tint="@color/colorWhite"
|
||||
android:src="@drawable/icon_cloud_download"/>
|
||||
|
||||
</android.support.design.widget.CoordinatorLayout>
|
|
@ -0,0 +1,69 @@
|
|||
<?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"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#000"
|
||||
android:fitsSystemWindows="false">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/fragment_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/qr_container"
|
||||
android:layout_width="match_parent" android:layout_height="match_parent"
|
||||
android:background="#96000000">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/qr_background"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="wrap_content" android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:background="@drawable/rounded_square">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/info"
|
||||
android:paddingTop="10dp"
|
||||
android:layout_marginBottom="-15dp"
|
||||
android:textColor="#000"
|
||||
android:text="Public Key"
|
||||
android:textStyle="normal"
|
||||
android:textSize="20sp"
|
||||
android:gravity="center_horizontal"
|
||||
android:layout_width="match_parent" android:layout_height="wrap_content"/>
|
||||
|
||||
<ImageView
|
||||
android:contentDescription="@string/qr_code"
|
||||
android:id="@+id/qr_imageView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
</LinearLayout>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/close"
|
||||
android:layout_width="wrap_content" android:layout_height="wrap_content"
|
||||
android:padding="16dp"
|
||||
android:tint="@color/colorWhite" android:src="@drawable/icon_close"
|
||||
android:background="?android:selectableItemBackgroundBorderless"/>
|
||||
|
||||
<android.support.design.widget.FloatingActionButton
|
||||
android:id="@+id/fab_continue_sync_info"
|
||||
android:layout_width="wrap_content" android:layout_height="wrap_content"
|
||||
android:layout_margin="16dp"
|
||||
android:layout_gravity="bottom|end"
|
||||
android:src="@drawable/icon_arrow_right"/>
|
||||
|
||||
<android.support.design.widget.FloatingActionButton
|
||||
android:id="@+id/fab_continue_sync_upload"
|
||||
android:layout_width="wrap_content" android:layout_height="wrap_content"
|
||||
android:layout_margin="16dp"
|
||||
android:layout_gravity="bottom|end"
|
||||
android:tint="@color/colorWhite"
|
||||
android:src="@drawable/icon_cloud_upload"/>
|
||||
|
||||
</android.support.design.widget.CoordinatorLayout>
|
|
@ -36,13 +36,35 @@
|
|||
</android.support.constraint.ConstraintLayout>
|
||||
|
||||
<android.support.design.widget.FloatingActionButton
|
||||
android:id="@+id/fab"
|
||||
android:id="@+id/fab_finish"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:fabSize="normal"
|
||||
android:tint="@color/colorWhite"
|
||||
android:src="@drawable/icon_check"
|
||||
android:layout_gravity="bottom|right|end"
|
||||
android:layout_gravity="bottom|end"
|
||||
android:layout_margin="16dp"/>
|
||||
|
||||
<android.support.design.widget.FloatingActionButton
|
||||
android:id="@+id/fab_retry"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:fabSize="normal"
|
||||
android:tint="@color/colorWhite"
|
||||
android:src="@drawable/icon_retry"
|
||||
app:layout_anchor="@id/fab_finish"
|
||||
app:layout_anchorGravity="start|center_vertical"
|
||||
android:layout_gravity="start|center_vertical"
|
||||
android:layout_margin="16dp"/>
|
||||
|
||||
<android.support.design.widget.FloatingActionButton
|
||||
android:id="@+id/fab_start"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:fabSize="normal"
|
||||
android:tint="@color/colorWhite"
|
||||
android:src="@drawable/icon_cloud_upload"
|
||||
android:layout_gravity="bottom|end"
|
||||
android:layout_margin="16dp"/>
|
||||
|
||||
</android.support.design.widget.CoordinatorLayout>
|
|
@ -0,0 +1,40 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent" android:layout_height="match_parent"
|
||||
android:padding="20dp">
|
||||
|
||||
<android.support.design.widget.TextInputLayout
|
||||
android:id="@+id/input_layout_server_url"
|
||||
android:layout_width="match_parent" android:layout_height="wrap_content"
|
||||
android:hint="@string/server_url">
|
||||
|
||||
<android.support.design.widget.TextInputEditText
|
||||
android:layout_width="match_parent" android:layout_height="match_parent"
|
||||
android:inputType="textUri"/>
|
||||
|
||||
</android.support.design.widget.TextInputLayout>
|
||||
|
||||
<android.support.design.widget.TextInputLayout
|
||||
android:id="@+id/input_layout_automation_key"
|
||||
android:layout_width="match_parent" android:layout_height="wrap_content"
|
||||
android:layout_below="@id/input_layout_server_url"
|
||||
android:layout_marginTop="8dp"
|
||||
android:hint="@string/authkey"
|
||||
app:passwordToggleEnabled="true">
|
||||
|
||||
<android.support.design.widget.TextInputEditText
|
||||
android:layout_width="match_parent" android:layout_height="match_parent"
|
||||
android:inputType="textPassword"/>
|
||||
|
||||
</android.support.design.widget.TextInputLayout>
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/check_save_authkey"
|
||||
android:layout_width="match_parent" android:layout_height="wrap_content"
|
||||
android:layout_below="@id/input_layout_automation_key"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="@string/save_authkey"/>
|
||||
|
||||
</RelativeLayout>
|
|
@ -6,7 +6,7 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<de.overview.wg.its.mispauth.cam.AutoFitTextureView
|
||||
<de.overview.wg.its.mispbump.cam.AutoFitTextureView
|
||||
android:id="@+id/texture"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/container"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent" android:layout_height="wrap_content">
|
||||
|
||||
|
|
|
@ -1,16 +1,17 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<android.support.v7.widget.CardView
|
||||
android:id="@+id/card_synced_org"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="match_parent" android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="16dp"
|
||||
app:cardBackgroundColor="@color/colorWhite"
|
||||
app:cardElevation="3dp"
|
||||
app:cardElevation="2dp"
|
||||
app:cardCornerRadius="0dp"
|
||||
app:cardPreventCornerOverlap="true"
|
||||
app:contentPadding="16dp">
|
||||
app:contentPadding="16dp"
|
||||
android:clickable="true" android:focusable="true">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
@ -6,10 +6,14 @@
|
|||
<item
|
||||
android:id="@+id/menu_item_credential_settings"
|
||||
android:title="@string/credential_settings"
|
||||
android:icon="@drawable/icon_settings"
|
||||
android:icon="@drawable/icon_cloud"
|
||||
app:showAsAction="always">
|
||||
</item>
|
||||
|
||||
<item android:id="@+id/main_menu_settings"
|
||||
android:title="@string/settings"
|
||||
android:icon="@drawable/icon_settings"/>
|
||||
|
||||
<item android:id="@+id/menu_item_delete_local_data"
|
||||
android:title="@string/delete_local_data"/>
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<!--<item android:title="@string/delete_local_data"-->
|
||||
<!--android:id="@+id/menu_item_deleteData"/>-->
|
||||
<item android:title="@string/delete_local_data"
|
||||
android:id="@+id/menu_delete_local_data"/>
|
||||
|
||||
<item android:title="Load config"
|
||||
android:id="@+id/load_config"/>
|
|
@ -37,6 +37,11 @@
|
|||
|
||||
<string name="sync_info_let_scan">Drücken Sie weiter, wenn dieser QR-Code gescannt wurde</string>
|
||||
|
||||
<string name="error_url_required">Url Ihrer MISP Instanz benötigt</string>
|
||||
<string name="error_api_required">Autorisierungsschlüssel Ihrer MISP Instanz benötigt</string>
|
||||
<string name="error_url_required">MISP Url benötigt</string>
|
||||
<string name="error_automation_key">MISP Automatisierungsschlüssel benötigt</string>
|
||||
<string name="copied_to_clipboard">In Zwischenablage kopiert</string>
|
||||
<string name="dialog_open_in_browser_msg">%1$s im Browser öffnen?</string>
|
||||
<string name="dialog_open_browser_title">Im Browser öffnen</string>
|
||||
<string name="open">öffnen</string>
|
||||
<string name="settings">Einstellungen</string>
|
||||
</resources>
|
|
@ -23,7 +23,10 @@
|
|||
<string name="str_continue">continue</string>
|
||||
<string name="delete">delete</string>
|
||||
<string name="delete_local_data">Delete local data</string>
|
||||
<string name="delete_local_data_msg">The URL, authentication key and your local data will be removed.\nThis information is needed for synchronisation.</string>
|
||||
<string name="delete_local_data_msg">
|
||||
This action will delete the <b>URL</b>, <b>automation key</b> and your downloaded <b>organisation information</b>.
|
||||
\n\nKeep in mind that the latter is required for synchronisation.
|
||||
</string>
|
||||
<string name="override">override</string>
|
||||
<string name="override_local_data">Override local data</string>
|
||||
<string name="override_local_data_msg">Do you really want to override the local information stored on this device?</string>
|
||||
|
@ -34,5 +37,12 @@
|
|||
<string name="sync_info_let_scan">Press continue if this QR-Code was scanned</string>
|
||||
|
||||
<string name="error_url_required">Enter MISP base url</string>
|
||||
<string name="error_api_required">Enter MISP api key</string>
|
||||
<string name="error_automation_key">Enter MISP automation key</string>
|
||||
<string name="copied_to_clipboard">Copied to clipboard</string>
|
||||
<string name="dialog_open_in_browser_msg">Open %1$s in browser?</string>
|
||||
<string name="dialog_open_browser_title">Open in browser</string>
|
||||
<string name="open">open</string>
|
||||
<string name="settings">Settings</string>
|
||||
|
||||
|
||||
</resources>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package de.overview.wg.its.mispauth;
|
||||
package de.overview.wg.its.mispbump;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
|
@ -10,8 +10,8 @@ import static org.junit.Assert.*;
|
|||
* @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);
|
||||
}
|
||||
@Test
|
||||
public void addition_isCorrect() {
|
||||
assertEquals(4, 2 + 2);
|
||||
}
|
||||
}
|
|
@ -6,9 +6,9 @@ buildscript {
|
|||
google()
|
||||
jcenter()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.1.3'
|
||||
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#Sun Jul 01 14:53:57 CEST 2018
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-bin.zip
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env bash
|
||||
#!/usr/bin/env sh
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
|
@ -6,42 +6,6 @@
|
|||
##
|
||||
##############################################################################
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS=""
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
|
||||
warn ( ) {
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
die ( ) {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
esac
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
|
@ -60,6 +24,46 @@ cd "`dirname \"$PRG\"`/" >/dev/null
|
|||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >/dev/null
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS=""
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
NONSTOP* )
|
||||
nonstop=true
|
||||
;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
|
@ -85,7 +89,7 @@ location of your Java installation."
|
|||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
|
@ -150,11 +154,19 @@ if $cygwin ; then
|
|||
esac
|
||||
fi
|
||||
|
||||
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
|
||||
function splitJvmOpts() {
|
||||
JVM_OPTS=("$@")
|
||||
# Escape application args
|
||||
save () {
|
||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||
echo " "
|
||||
}
|
||||
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
|
||||
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
|
||||
APP_ARGS=$(save "$@")
|
||||
|
||||
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
|
||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||
|
||||
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
||||
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
||||
cd "$(dirname "$0")"
|
||||
fi
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
|
|
|
@ -8,14 +8,14 @@
|
|||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS=
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS=
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
|
@ -46,10 +46,9 @@ echo location of your Java installation.
|
|||
goto fail
|
||||
|
||||
:init
|
||||
@rem Get command-line arguments, handling Windowz variants
|
||||
@rem Get command-line arguments, handling Windows variants
|
||||
|
||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||
if "%@eval[2+2]" == "4" goto 4NT_args
|
||||
|
||||
:win9xME_args
|
||||
@rem Slurp the command line arguments.
|
||||
|
@ -60,11 +59,6 @@ set _SKIP=2
|
|||
if "x%~1" == "x" goto execute
|
||||
|
||||
set CMD_LINE_ARGS=%*
|
||||
goto execute
|
||||
|
||||
:4NT_args
|
||||
@rem Get arguments from the 4NT Shell from JP Software
|
||||
set CMD_LINE_ARGS=%$
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
|
Before Width: | Height: | Size: 68 KiB |
Before Width: | Height: | Size: 343 KiB |
Before Width: | Height: | Size: 380 KiB |
Before Width: | Height: | Size: 1.6 MiB |
Before Width: | Height: | Size: 109 KiB |
Before Width: | Height: | Size: 86 KiB |
Before Width: | Height: | Size: 9.0 KiB |