first working version from Android Studio
6
.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
.gradle
|
||||
/local.properties
|
||||
/.idea/workspace.xml
|
||||
/.idea/libraries
|
||||
.DS_Store
|
||||
/build
|
1
.idea/.name
generated
Normal file
@ -0,0 +1 @@
|
||||
PointsPermis
|
23
.idea/compiler.xml
generated
Normal file
@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CompilerConfiguration">
|
||||
<option name="DEFAULT_COMPILER" value="Javac" />
|
||||
<resourceExtensions />
|
||||
<wildcardResourcePatterns>
|
||||
<entry name="!?*.java" />
|
||||
<entry name="!?*.form" />
|
||||
<entry name="!?*.class" />
|
||||
<entry name="!?*.groovy" />
|
||||
<entry name="!?*.scala" />
|
||||
<entry name="!?*.flex" />
|
||||
<entry name="!?*.kt" />
|
||||
<entry name="!?*.clj" />
|
||||
</wildcardResourcePatterns>
|
||||
<annotationProcessing>
|
||||
<profile default="true" name="Default" enabled="false">
|
||||
<processorPath useClasspath="true" />
|
||||
</profile>
|
||||
</annotationProcessing>
|
||||
</component>
|
||||
</project>
|
||||
|
3
.idea/copyright/profiles_settings.xml
generated
Normal file
@ -0,0 +1,3 @@
|
||||
<component name="CopyrightManager">
|
||||
<settings default="" />
|
||||
</component>
|
5
.idea/encodings.xml
generated
Normal file
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="false" />
|
||||
</project>
|
||||
|
20
.idea/gradle.xml
generated
Normal file
@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="GradleSettings">
|
||||
<option name="linkedExternalProjectsSettings">
|
||||
<GradleProjectSettings>
|
||||
<option name="distributionType" value="LOCAL" />
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
<option name="gradleHome" value="$APPLICATION_HOME_DIR$/gradle/gradle-2.2.1" />
|
||||
<option name="modules">
|
||||
<set>
|
||||
<option value="$PROJECT_DIR$" />
|
||||
<option value="$PROJECT_DIR$/app" />
|
||||
<option value="$PROJECT_DIR$/tesseract" />
|
||||
</set>
|
||||
</option>
|
||||
</GradleProjectSettings>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
|
12
.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
@ -0,0 +1,12 @@
|
||||
<component name="InspectionProjectProfileManager">
|
||||
<profile version="1.0" is_locked="false">
|
||||
<option name="myName" value="Project Default" />
|
||||
<option name="myLocal" value="false" />
|
||||
<inspection_tool class="AndroidLintInvalidId" enabled="false" level="ERROR" enabled_by_default="false" />
|
||||
<inspection_tool class="AndroidLintRtlHardcoded" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||
<inspection_tool class="LoggerInitializedWithForeignClass" enabled="false" level="WARNING" enabled_by_default="false">
|
||||
<option name="loggerClassName" value="org.apache.log4j.Logger,org.slf4j.LoggerFactory,org.apache.commons.logging.LogFactory,java.util.logging.Logger" />
|
||||
<option name="loggerFactoryMethodName" value="getLogger,getLogger,getLog,getLogger" />
|
||||
</inspection_tool>
|
||||
</profile>
|
||||
</component>
|
7
.idea/inspectionProfiles/profiles_settings.xml
generated
Normal file
@ -0,0 +1,7 @@
|
||||
<component name="InspectionProjectProfileManager">
|
||||
<settings>
|
||||
<option name="PROJECT_PROFILE" value="Project Default" />
|
||||
<option name="USE_PROJECT_PROFILE" value="true" />
|
||||
<version value="1.0" />
|
||||
</settings>
|
||||
</component>
|
10
.idea/misc.xml
generated
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="EntryPointsManager">
|
||||
<entry_points version="2.0" />
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||
</component>
|
||||
</project>
|
||||
|
11
.idea/modules.xml
generated
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/PointsPermis.iml" filepath="$PROJECT_DIR$/PointsPermis.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/app/app.iml" filepath="$PROJECT_DIR$/app/app.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/tesseract/tesseract.iml" filepath="$PROJECT_DIR$/tesseract/tesseract.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
|
5
.idea/scopes/scope_settings.xml
generated
Normal file
@ -0,0 +1,5 @@
|
||||
<component name="DependencyValidationManager">
|
||||
<state>
|
||||
<option name="SKIP_IMPORT_STATEMENTS" value="false" />
|
||||
</state>
|
||||
</component>
|
7
.idea/vcs.xml
generated
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="" />
|
||||
</component>
|
||||
</project>
|
||||
|
21
PointsPermis.iml
Normal file
@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" type="JAVA_MODULE" version="4">
|
||||
<component name="FacetManager">
|
||||
<facet type="java-gradle" name="Java-Gradle">
|
||||
<configuration>
|
||||
<option name="BUILD_FOLDER_PATH" value="$MODULE_DIR$/build" />
|
||||
</configuration>
|
||||
</facet>
|
||||
</component>
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="false">
|
||||
<output url="file://$MODULE_DIR$/build/classes/main" />
|
||||
<output-test url="file://$MODULE_DIR$/build/classes/test" />
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<excludeFolder url="file://$MODULE_DIR$/.gradle" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
|
1
app/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/build
|
92
app/app.iml
Normal file
@ -0,0 +1,92 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" type="JAVA_MODULE" version="4">
|
||||
<component name="FacetManager">
|
||||
<facet type="android-gradle" name="Android-Gradle">
|
||||
<configuration>
|
||||
<option name="GRADLE_PROJECT_PATH" value=":app" />
|
||||
</configuration>
|
||||
</facet>
|
||||
<facet type="android" name="Android">
|
||||
<configuration>
|
||||
<option name="SELECTED_BUILD_VARIANT" value="debug" />
|
||||
<option name="ASSEMBLE_TASK_NAME" value="assembleDebug" />
|
||||
<option name="COMPILE_JAVA_TASK_NAME" value="compileDebugSources" />
|
||||
<option name="ASSEMBLE_TEST_TASK_NAME" value="assembleDebugTest" />
|
||||
<option name="SOURCE_GEN_TASK_NAME" value="generateDebugSources" />
|
||||
<option name="TEST_SOURCE_GEN_TASK_NAME" value="generateDebugTestSources" />
|
||||
<option name="ALLOW_USER_CONFIGURATION" value="false" />
|
||||
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" />
|
||||
<option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" />
|
||||
<option name="RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/src/main/res" />
|
||||
<option name="ASSETS_FOLDER_RELATIVE_PATH" value="/src/main/assets" />
|
||||
</configuration>
|
||||
</facet>
|
||||
</component>
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="false">
|
||||
<output url="file://$MODULE_DIR$/build/intermediates/classes/debug" />
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/debug" isTestSource="false" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/debug" isTestSource="false" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/debug" isTestSource="false" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/debug" isTestSource="false" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/debug" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/generated/debug" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/test/debug" isTestSource="true" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/test/debug" isTestSource="true" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/test/debug" isTestSource="true" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/test/debug" isTestSource="true" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/test/debug" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/generated/test/debug" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/res" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/resources" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/assets" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/aidl" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/java" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/jni" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/rs" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/res" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/assets" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/aidl" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/jni" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/rs" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/aidl" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/jni" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/bundles" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/coverage-instrumented-classes" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dependency-cache" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex-cache" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/jacoco" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/javaResources" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/libs" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/lint" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/ndk" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/pre-dexed" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/proguard" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/outputs" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/tmp" />
|
||||
</content>
|
||||
<orderEntry type="jdk" jdkName="Android API 19 Platform" jdkType="Android SDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" exported="" name="jsoup-1.8.1" level="project" />
|
||||
<orderEntry type="library" exported="" name="support-v4-21.0.3" level="project" />
|
||||
<orderEntry type="library" exported="" name="support-annotations-21.0.3" level="project" />
|
||||
<orderEntry type="module" module-name="tesseract" exported="" />
|
||||
</component>
|
||||
</module>
|
||||
|
32
app/build.gradle
Normal file
@ -0,0 +1,32 @@
|
||||
apply plugin: 'com.android.application'
|
||||
|
||||
android {
|
||||
compileSdkVersion 19
|
||||
buildToolsVersion '21.1.2'
|
||||
defaultConfig {
|
||||
applicationId "fr.android.pointspermis"
|
||||
minSdkVersion 14
|
||||
targetSdkVersion 19
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_7
|
||||
targetCompatibility JavaVersion.VERSION_1_7
|
||||
}
|
||||
productFlavors {
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile fileTree(include: ['*.jar'], dir: 'libs')
|
||||
compile 'com.android.support:support-v4:21.0.3'
|
||||
compile project(':tesseract')
|
||||
compile files('libs/jsoup-1.8.1.jar')
|
||||
}
|
BIN
app/libs/jsoup-1.8.1.jar
Normal file
17
app/proguard-rules.pro
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# By default, the flags in this file are appended to flags specified
|
||||
# in /opt/android/sdk/tools/proguard/proguard-android.txt
|
||||
# You can edit the include path and order by changing the proguardFiles
|
||||
# directive in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# Add any project specific keep options here:
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
@ -0,0 +1,13 @@
|
||||
package fr.android.pointspermis;
|
||||
|
||||
import android.app.Application;
|
||||
import android.test.ApplicationTestCase;
|
||||
|
||||
/**
|
||||
* <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
|
||||
*/
|
||||
public class ApplicationTest extends ApplicationTestCase<Application> {
|
||||
public ApplicationTest() {
|
||||
super(Application.class);
|
||||
}
|
||||
}
|
33
app/src/main/AndroidManifest.xml
Normal file
@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="fr.android.pointspermis" >
|
||||
|
||||
<!-- permissions -->
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:icon="@drawable/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@style/AppTheme" >
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:label="@string/app_name"
|
||||
android:launchMode="singleTop" >
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".settings.SettingsActivity"
|
||||
android:label="@string/title_activity_settings"
|
||||
android:parentActivityName=".MainActivity" >
|
||||
<!-- The meta-data element is needed for versions lower than 4.1 -->
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value=".MainActivity" />
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
</manifest>
|
BIN
app/src/main/assets/tele7.interieur.gouv.fr.cert
Normal file
BIN
app/src/main/assets/tesseract/tessdata/dan-frak.traineddata
Normal file
BIN
app/src/main/assets/tesseract/tessdata/deu-frak.traineddata
Normal file
9767
app/src/main/assets/tesseract/tessdata/fra.cube.bigrams
Normal file
16
app/src/main/assets/tesseract/tessdata/fra.cube.fold
Normal file
@ -0,0 +1,16 @@
|
||||
0oO
|
||||
lI1
|
||||
cCG
|
||||
kK
|
||||
pP
|
||||
sS
|
||||
uU
|
||||
vV
|
||||
wW
|
||||
xX
|
||||
yY
|
||||
zZ
|
||||
Ôó
|
||||
Ùù
|
||||
Ûû
|
||||
Üü
|
7
app/src/main/assets/tesseract/tessdata/fra.cube.lm
Normal file
@ -0,0 +1,7 @@
|
||||
LeadPunc="'([{¡«¿’“
|
||||
TrailPunc=!"'),-.:;?]_}©®»‘”
|
||||
NumLeadPunc=#(@[{.-<=>€
|
||||
NumTrailPunc=!%),.:;]_}°<=>
|
||||
Operators=*+-/.:,()[]{}<>=
|
||||
Digits=0123456789
|
||||
Alphas=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzÀÂÄÆÇÈÉÊËÎÏÔÙÛÜàâäæçèéêëîïñòóôùûüŒœŸfifl
|
BIN
app/src/main/assets/tesseract/tessdata/fra.cube.nn
Normal file
13
app/src/main/assets/tesseract/tessdata/fra.cube.params
Normal file
@ -0,0 +1,13 @@
|
||||
RecoWgt=0.7662
|
||||
SizeWgt=0.0898
|
||||
OODWgt=0.0400
|
||||
NumWgt=0.0513
|
||||
CharBigramsWgt=0.0464
|
||||
MaxSegPerChar=8
|
||||
BeamWidth=10
|
||||
ConvGridSize=48
|
||||
WordUnigramsWgt=0.005
|
||||
MaxWordAspectRatio=20.0000
|
||||
MinSpaceHeightRatio=0.5000
|
||||
MaxSpaceHeightRatio=0.6000
|
||||
HistWindWid=2
|
277440
app/src/main/assets/tesseract/tessdata/fra.cube.size
Normal file
200229
app/src/main/assets/tesseract/tessdata/fra.cube.word-freq
Normal file
BIN
app/src/main/assets/tesseract/tessdata/fra.tesseract_cube.nn
Normal file
BIN
app/src/main/assets/tesseract/tessdata/fra.traineddata
Normal file
BIN
app/src/main/assets/tesseract/tessdata/slk-frak.traineddata
Normal file
308
app/src/main/java/fr/android/pointspermis/MainActivity.java
Normal file
@ -0,0 +1,308 @@
|
||||
package fr.android.pointspermis;
|
||||
|
||||
import android.app.Activity;
|
||||
|
||||
import android.app.ActionBar;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Fragment;
|
||||
import android.app.FragmentManager;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.os.StrictMode;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.support.v4.widget.DrawerLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
import fr.android.pointspermis.captcha.Captcha;
|
||||
import fr.android.pointspermis.settings.SettingsActivity;
|
||||
import fr.android.pointspermis.tools.AssetsTools;
|
||||
import fr.android.pointspermis.web.WebTask;
|
||||
|
||||
|
||||
public class MainActivity extends Activity
|
||||
implements NavigationDrawerFragment.NavigationDrawerCallbacks {
|
||||
|
||||
private final Context context = this;
|
||||
|
||||
private WebTask webform;
|
||||
|
||||
private SharedPreferences prefs;
|
||||
private SharedPreferences.Editor editor;
|
||||
|
||||
private String solde;
|
||||
private String username;
|
||||
private String birthday;
|
||||
|
||||
/**
|
||||
* Fragment managing the behaviors, interactions and presentation of the navigation drawer.
|
||||
*/
|
||||
private NavigationDrawerFragment mNavigationDrawerFragment;
|
||||
|
||||
private PlaceholderFragment mPlaceholderFrament;
|
||||
|
||||
/**
|
||||
* Used to store the last screen title. For use in {@link #restoreActionBar()}.
|
||||
*/
|
||||
private CharSequence mTitle;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
|
||||
// Routines
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_main);
|
||||
|
||||
// Strict thread mode
|
||||
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
|
||||
StrictMode.setThreadPolicy(policy);
|
||||
|
||||
// Copy tesseract data to app-specific internal storage (language stuff)
|
||||
copyTesseractData();
|
||||
|
||||
mNavigationDrawerFragment = (NavigationDrawerFragment)
|
||||
getFragmentManager().findFragmentById(R.id.navigation_drawer);
|
||||
mTitle = getTitle();
|
||||
|
||||
// Set up the drawer.
|
||||
mNavigationDrawerFragment.setUp(
|
||||
R.id.navigation_drawer,
|
||||
(DrawerLayout) findViewById(R.id.drawer_layout));
|
||||
|
||||
// Load prefs
|
||||
prefs = getSharedPreferences("fr.android.pointspermis", MODE_PRIVATE);
|
||||
editor = prefs.edit();
|
||||
|
||||
// Try to get saved values
|
||||
solde = prefs.getString("solde", "");
|
||||
username = prefs.getString("username", "");
|
||||
birthday = prefs.getString("birthday", "");
|
||||
}
|
||||
|
||||
public void copyTesseractData() {
|
||||
|
||||
// Copy tesseract data to app-specific internal storage (language stuff)
|
||||
File filesDir = getFilesDir();
|
||||
if (!getFilesDir().canRead()) { getFilesDir().setReadable(true); }
|
||||
if (!getFilesDir().canWrite()) { getFilesDir().setWritable(true); }
|
||||
if (!getFilesDir().exists()) { getFilesDir().mkdir(); }
|
||||
boolean dirExists = false;
|
||||
for (String fod : getFilesDir().list()) { if (fod.contains(Captcha.TESSBASE_DIR)) { dirExists = true; break; } }
|
||||
if (!dirExists && getFilesDir().getFreeSpace() < (31 * 1024 * 1024)) {
|
||||
new AlertDialog.Builder(this)
|
||||
.setTitle("Erreur fatale !")
|
||||
.setMessage("Impossible de copier les données nécessaires au fonctionnement de l'application, "+
|
||||
"veuillez vous assurer de disposer d'au moins 30Mo d'espace de stockage interne disponible.")
|
||||
.setCancelable(false)
|
||||
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
MainActivity.this.finish();
|
||||
}
|
||||
})
|
||||
.show();
|
||||
}
|
||||
AssetsTools.copyFileOrDir(Captcha.TESSBASE_DIR, filesDir.getPath() + '/', getAssets());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNavigationDrawerItemSelected(int position) {
|
||||
// update the main content by replacing fragments
|
||||
FragmentManager fragmentManager = getFragmentManager();
|
||||
|
||||
mPlaceholderFrament = PlaceholderFragment.newInstance(position + 1);
|
||||
|
||||
fragmentManager.beginTransaction().replace(R.id.container, mPlaceholderFrament).commit();
|
||||
}
|
||||
|
||||
public void onSectionAttached(int number) {
|
||||
switch (number) {
|
||||
case 1:
|
||||
mTitle = getString(R.string.title_home);
|
||||
break;
|
||||
case 2:
|
||||
mTitle = getString(R.string.title_settings);
|
||||
Intent i = new Intent(this, SettingsActivity.class);
|
||||
startActivity(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void restoreActionBar() {
|
||||
ActionBar actionBar = getActionBar();
|
||||
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
|
||||
actionBar.setDisplayShowTitleEnabled(true);
|
||||
actionBar.setTitle(mTitle);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
if (!mNavigationDrawerFragment.isDrawerOpen()) {
|
||||
// Only show items in the action bar relevant to this screen
|
||||
// if the drawer is not showing. Otherwise, let the drawer
|
||||
// decide what to show in the action bar.
|
||||
getMenuInflater().inflate(R.menu.main, menu);
|
||||
restoreActionBar();
|
||||
return true;
|
||||
}
|
||||
return super.onCreateOptionsMenu(menu);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
// Handle action bar item clicks here. The action bar will
|
||||
// automatically handle clicks on the Home/Up button, so long
|
||||
// as you specify a parent activity in AndroidManifest.xml.
|
||||
int id = item.getItemId();
|
||||
|
||||
//noinspection SimplifiableIfStatement
|
||||
if (id == R.id.action_settings) {
|
||||
Intent i = new Intent(this, SettingsActivity.class);
|
||||
startActivity(i);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (item.getItemId() == R.id.action_refresh) {
|
||||
|
||||
// Initialize and execute the WebForm async task
|
||||
webform = new WebTask(context, MainActivity.this);
|
||||
webform.execute(prefs.getString(SettingsActivity.DOSSIER1_KEY, ""),
|
||||
prefs.getString(SettingsActivity.DOSSIER2_KEY, ""),
|
||||
prefs.getString(SettingsActivity.DOSSIER3_KEY, ""),
|
||||
prefs.getString(SettingsActivity.CODE_KEY, "")
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (item.getItemId() == R.id.action_quit) {
|
||||
quit();
|
||||
}
|
||||
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
/**
|
||||
* A placeholder fragment containing a simple view.
|
||||
*/
|
||||
public static class PlaceholderFragment extends Fragment {
|
||||
/**
|
||||
* The fragment argument representing the section number for this
|
||||
* fragment.
|
||||
*/
|
||||
private static final String ARG_SECTION_NUMBER = "section_number";
|
||||
|
||||
private TextView textViewSolde;
|
||||
private TextView textViewUserName;
|
||||
private TextView textViewBirthday;
|
||||
|
||||
/**
|
||||
* Returns a new instance of this fragment for the given section
|
||||
* number.
|
||||
*/
|
||||
public static PlaceholderFragment newInstance(int sectionNumber) {
|
||||
PlaceholderFragment fragment = new PlaceholderFragment();
|
||||
Bundle args = new Bundle();
|
||||
args.putInt(ARG_SECTION_NUMBER, sectionNumber);
|
||||
fragment.setArguments(args);
|
||||
return fragment;
|
||||
}
|
||||
|
||||
public PlaceholderFragment() {
|
||||
}
|
||||
|
||||
public void setInfos(List<String> infos) {
|
||||
|
||||
// Show values
|
||||
textViewSolde.setText(infos.get(0));
|
||||
textViewSolde.invalidate();
|
||||
textViewUserName.setText(infos.get(1));
|
||||
textViewUserName.invalidate();
|
||||
textViewBirthday.setText(infos.get(2));
|
||||
textViewBirthday.invalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
|
||||
|
||||
textViewSolde = (TextView) rootView.findViewById(R.id.textViewSolde);
|
||||
textViewUserName = (TextView) rootView.findViewById(R.id.textViewUserName);
|
||||
textViewBirthday = (TextView) rootView.findViewById(R.id.textViewBirthday);
|
||||
|
||||
return rootView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(Activity activity) {
|
||||
super.onAttach(activity);
|
||||
((MainActivity) activity).onSectionAttached(
|
||||
getArguments().getInt(ARG_SECTION_NUMBER));
|
||||
}
|
||||
}
|
||||
|
||||
public void setInfos(List<String> infos) {
|
||||
|
||||
// Set infos to the fragment
|
||||
mPlaceholderFrament.setInfos(infos);
|
||||
}
|
||||
|
||||
private void saveUserData() {
|
||||
|
||||
editor.putString("solde", solde);
|
||||
editor.putString("username", username);
|
||||
editor.putString("birthday", birthday);
|
||||
editor.commit();
|
||||
}
|
||||
|
||||
public void quit() {
|
||||
new AlertDialog.Builder(this)
|
||||
.setMessage("Quitter ?")
|
||||
.setCancelable(false)
|
||||
.setPositiveButton("Oui", new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
|
||||
// Save user data
|
||||
saveUserData();
|
||||
|
||||
// Terminate activity
|
||||
MainActivity.this.finish();
|
||||
}
|
||||
})
|
||||
.setNegativeButton("Non", new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
dialog.dismiss();
|
||||
}
|
||||
})
|
||||
.show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
quit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
super.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
}
|
||||
}
|
@ -0,0 +1,281 @@
|
||||
package fr.android.pointspermis;
|
||||
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.ActionBar;
|
||||
import android.app.Fragment;
|
||||
import android.support.v4.app.ActionBarDrawerToggle;
|
||||
import android.support.v4.view.GravityCompat;
|
||||
import android.support.v4.widget.DrawerLayout;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.res.Configuration;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.ListView;
|
||||
import android.widget.Toast;
|
||||
|
||||
/**
|
||||
* Fragment used for managing interactions for and presentation of a navigation drawer.
|
||||
* See the <a href="https://developer.android.com/design/patterns/navigation-drawer.html#Interaction">
|
||||
* design guidelines</a> for a complete explanation of the behaviors implemented here.
|
||||
*/
|
||||
public class NavigationDrawerFragment extends Fragment {
|
||||
|
||||
/**
|
||||
* Remember the position of the selected item.
|
||||
*/
|
||||
private static final String STATE_SELECTED_POSITION = "selected_navigation_drawer_position";
|
||||
|
||||
/**
|
||||
* Per the design guidelines, you should show the drawer on launch until the user manually
|
||||
* expands it. This shared preference tracks this.
|
||||
*/
|
||||
private static final String PREF_USER_LEARNED_DRAWER = "navigation_drawer_learned";
|
||||
|
||||
/**
|
||||
* A pointer to the current callbacks instance (the Activity).
|
||||
*/
|
||||
private NavigationDrawerCallbacks mCallbacks;
|
||||
|
||||
/**
|
||||
* Helper component that ties the action bar to the navigation drawer.
|
||||
*/
|
||||
private ActionBarDrawerToggle mDrawerToggle;
|
||||
|
||||
private DrawerLayout mDrawerLayout;
|
||||
private ListView mDrawerListView;
|
||||
private View mFragmentContainerView;
|
||||
|
||||
private int mCurrentSelectedPosition = 0;
|
||||
private boolean mFromSavedInstanceState;
|
||||
private boolean mUserLearnedDrawer;
|
||||
|
||||
public NavigationDrawerFragment() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
// Read in the flag indicating whether or not the user has demonstrated awareness of the
|
||||
// drawer. See PREF_USER_LEARNED_DRAWER for details.
|
||||
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getActivity());
|
||||
mUserLearnedDrawer = sp.getBoolean(PREF_USER_LEARNED_DRAWER, false);
|
||||
|
||||
if (savedInstanceState != null) {
|
||||
mCurrentSelectedPosition = savedInstanceState.getInt(STATE_SELECTED_POSITION);
|
||||
mFromSavedInstanceState = true;
|
||||
}
|
||||
|
||||
// Select either the default item (0) or the last selected item.
|
||||
selectItem(mCurrentSelectedPosition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
// Indicate that this fragment would like to influence the set of actions in the action bar.
|
||||
setHasOptionsMenu(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
mDrawerListView = (ListView) inflater.inflate(
|
||||
R.layout.fragment_navigation_drawer, container, false);
|
||||
mDrawerListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
selectItem(position);
|
||||
}
|
||||
});
|
||||
mDrawerListView.setAdapter(new ArrayAdapter<String>(
|
||||
getActionBar().getThemedContext(),
|
||||
android.R.layout.simple_list_item_activated_1,
|
||||
android.R.id.text1,
|
||||
new String[]{
|
||||
getString(R.string.title_home),
|
||||
getString(R.string.title_settings),
|
||||
}));
|
||||
mDrawerListView.setItemChecked(mCurrentSelectedPosition, true);
|
||||
return mDrawerListView;
|
||||
}
|
||||
|
||||
public boolean isDrawerOpen() {
|
||||
return mDrawerLayout != null && mDrawerLayout.isDrawerOpen(mFragmentContainerView);
|
||||
}
|
||||
|
||||
/**
|
||||
* Users of this fragment must call this method to set up the navigation drawer interactions.
|
||||
*
|
||||
* @param fragmentId The android:id of this fragment in its activity's layout.
|
||||
* @param drawerLayout The DrawerLayout containing this fragment's UI.
|
||||
*/
|
||||
public void setUp(int fragmentId, DrawerLayout drawerLayout) {
|
||||
mFragmentContainerView = getActivity().findViewById(fragmentId);
|
||||
mDrawerLayout = drawerLayout;
|
||||
|
||||
// set a custom shadow that overlays the main content when the drawer opens
|
||||
mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);
|
||||
// set up the drawer's list view with items and click listener
|
||||
|
||||
ActionBar actionBar = getActionBar();
|
||||
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||
actionBar.setHomeButtonEnabled(true);
|
||||
|
||||
// ActionBarDrawerToggle ties together the the proper interactions
|
||||
// between the navigation drawer and the action bar app icon.
|
||||
mDrawerToggle = new ActionBarDrawerToggle(
|
||||
getActivity(), /* host Activity */
|
||||
mDrawerLayout, /* DrawerLayout object */
|
||||
R.drawable.ic_drawer, /* nav drawer image to replace 'Up' caret */
|
||||
R.string.navigation_drawer_open, /* "open drawer" description for accessibility */
|
||||
R.string.navigation_drawer_close /* "close drawer" description for accessibility */
|
||||
) {
|
||||
@Override
|
||||
public void onDrawerClosed(View drawerView) {
|
||||
super.onDrawerClosed(drawerView);
|
||||
if (!isAdded()) {
|
||||
return;
|
||||
}
|
||||
|
||||
getActivity().invalidateOptionsMenu(); // calls onPrepareOptionsMenu()
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDrawerOpened(View drawerView) {
|
||||
super.onDrawerOpened(drawerView);
|
||||
if (!isAdded()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mUserLearnedDrawer) {
|
||||
// The user manually opened the drawer; store this flag to prevent auto-showing
|
||||
// the navigation drawer automatically in the future.
|
||||
mUserLearnedDrawer = true;
|
||||
SharedPreferences sp = PreferenceManager
|
||||
.getDefaultSharedPreferences(getActivity());
|
||||
sp.edit().putBoolean(PREF_USER_LEARNED_DRAWER, true).apply();
|
||||
}
|
||||
|
||||
getActivity().invalidateOptionsMenu(); // calls onPrepareOptionsMenu()
|
||||
}
|
||||
};
|
||||
|
||||
// If the user hasn't 'learned' about the drawer, open it to introduce them to the drawer,
|
||||
// per the navigation drawer design guidelines.
|
||||
if (!mUserLearnedDrawer && !mFromSavedInstanceState) {
|
||||
mDrawerLayout.openDrawer(mFragmentContainerView);
|
||||
}
|
||||
|
||||
// Defer code dependent on restoration of previous instance state.
|
||||
mDrawerLayout.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mDrawerToggle.syncState();
|
||||
}
|
||||
});
|
||||
|
||||
mDrawerLayout.setDrawerListener(mDrawerToggle);
|
||||
}
|
||||
|
||||
private void selectItem(int position) {
|
||||
mCurrentSelectedPosition = position;
|
||||
if (mDrawerListView != null) {
|
||||
mDrawerListView.setItemChecked(position, true);
|
||||
}
|
||||
if (mDrawerLayout != null) {
|
||||
mDrawerLayout.closeDrawer(mFragmentContainerView);
|
||||
}
|
||||
if (mCallbacks != null) {
|
||||
mCallbacks.onNavigationDrawerItemSelected(position);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(Activity activity) {
|
||||
super.onAttach(activity);
|
||||
try {
|
||||
mCallbacks = (NavigationDrawerCallbacks) activity;
|
||||
} catch (ClassCastException e) {
|
||||
throw new ClassCastException("Activity must implement NavigationDrawerCallbacks.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDetach() {
|
||||
super.onDetach();
|
||||
mCallbacks = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putInt(STATE_SELECTED_POSITION, mCurrentSelectedPosition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigurationChanged(Configuration newConfig) {
|
||||
super.onConfigurationChanged(newConfig);
|
||||
// Forward the new configuration the drawer toggle component.
|
||||
mDrawerToggle.onConfigurationChanged(newConfig);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
// If the drawer is open, show the global app actions in the action bar. See also
|
||||
// showGlobalContextActionBar, which controls the top-left area of the action bar.
|
||||
if (mDrawerLayout != null && isDrawerOpen()) {
|
||||
inflater.inflate(R.menu.global, menu);
|
||||
showGlobalContextActionBar();
|
||||
}
|
||||
super.onCreateOptionsMenu(menu, inflater);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
if (mDrawerToggle.onOptionsItemSelected(item)) {
|
||||
return true;
|
||||
}
|
||||
/*
|
||||
if (item.getItemId() == R.id.action_refresh) {
|
||||
Toast.makeText(getActivity(), "Actualisation..", Toast.LENGTH_SHORT).show();
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
/**
|
||||
* Per the navigation drawer design guidelines, updates the action bar to show the global app
|
||||
* 'context', rather than just what's in the current screen.
|
||||
*/
|
||||
private void showGlobalContextActionBar() {
|
||||
ActionBar actionBar = getActionBar();
|
||||
actionBar.setDisplayShowTitleEnabled(true);
|
||||
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
|
||||
actionBar.setTitle(R.string.app_name);
|
||||
}
|
||||
|
||||
private ActionBar getActionBar() {
|
||||
return getActivity().getActionBar();
|
||||
}
|
||||
|
||||
/**
|
||||
* Callbacks interface that all activities using this fragment must implement.
|
||||
*/
|
||||
public static interface NavigationDrawerCallbacks {
|
||||
/**
|
||||
* Called when an item in the navigation drawer is selected.
|
||||
*/
|
||||
void onNavigationDrawerItemSelected(int position);
|
||||
}
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
package fr.android.pointspermis.captcha;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.util.Log;
|
||||
|
||||
import com.googlecode.tesseract.android.TessBaseAPI;
|
||||
|
||||
/**
|
||||
* Created by vins on 07/01/15.
|
||||
*/
|
||||
public class Captcha {
|
||||
|
||||
public static final String TESSBASE_DIR = "tesseract";
|
||||
public static final String DEFAULT_LANGUAGE = "fra";
|
||||
|
||||
private String dataDir;
|
||||
|
||||
public Captcha(String dataDir) {
|
||||
this.dataDir = dataDir;
|
||||
}
|
||||
|
||||
public String getCode(Bitmap img) {
|
||||
|
||||
String code = null;
|
||||
TessBaseAPI baseApi = null;
|
||||
|
||||
try {
|
||||
// Attempt to initialize the API.
|
||||
baseApi = new TessBaseAPI();
|
||||
|
||||
// Init the API
|
||||
baseApi.init(dataDir + "/" + TESSBASE_DIR, DEFAULT_LANGUAGE);
|
||||
baseApi.setPageSegMode(TessBaseAPI.PageSegMode.PSM_SINGLE_LINE);
|
||||
baseApi.setImage(img);
|
||||
|
||||
// Get UTF8 decoding
|
||||
code = baseApi.getUTF8Text().replace(" ", "");
|
||||
//Log.d("DEBUG", "Code: " + code);
|
||||
|
||||
// Attempt to shut down the API.
|
||||
baseApi.end();
|
||||
} catch (Exception e) {
|
||||
Log.e("ERROR", "Error during the captcha recognition process:" + e.getMessage());
|
||||
}
|
||||
finally {
|
||||
// Attempt to shut down the API and return the code.
|
||||
try {baseApi.end();}catch(Exception e){}finally{return code;}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,188 @@
|
||||
package fr.android.pointspermis.settings;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.SharedPreferences;
|
||||
import android.preference.DialogPreference;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.EditText;
|
||||
|
||||
import fr.android.pointspermis.R;
|
||||
|
||||
/**
|
||||
* Created by vins on 27/01/15.
|
||||
*/
|
||||
public class DossierDialogPreference extends DialogPreference {
|
||||
|
||||
private final DossierDialogPreference me = this;
|
||||
private final Context context;
|
||||
|
||||
private SharedPreferences prefs;
|
||||
private SharedPreferences.Editor editor;
|
||||
|
||||
private String dossier1, dossier2, dossier3;
|
||||
private EditText editTextDossier1, editTextDossier2, editTextDossier3;
|
||||
|
||||
|
||||
public DossierDialogPreference(Context context, AttributeSet attrs) {
|
||||
|
||||
super(context,attrs);
|
||||
this.context = context;
|
||||
|
||||
prefs = context.getSharedPreferences("fr.android.pointspermis", Context.MODE_PRIVATE);
|
||||
editor = prefs.edit();
|
||||
|
||||
// Try to get old saved values
|
||||
dossier1 = prefs.getString(context.getString(R.string.pref_key_dossier1), "");
|
||||
dossier2 = prefs.getString(context.getString(R.string.pref_key_dossier2), "");
|
||||
dossier3 = prefs.getString(context.getString(R.string.pref_key_dossier3), "");
|
||||
|
||||
// Update summary
|
||||
updateSummary();
|
||||
|
||||
// Default saving behaviour => useless
|
||||
//setPersistent(true);
|
||||
|
||||
// Set the custom layout
|
||||
setDialogLayoutResource(R.layout.dossier_dialog);
|
||||
}
|
||||
|
||||
public void updateSummary() {
|
||||
setSummary(dossier1 + " " + dossier2 + " " + dossier3);
|
||||
}
|
||||
|
||||
public String getDossier1() {
|
||||
return dossier1;
|
||||
}
|
||||
|
||||
public String getDossier2() {
|
||||
return dossier2;
|
||||
}
|
||||
|
||||
public String getDossier3() {
|
||||
return dossier3;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
|
||||
|
||||
builder.setTitle(R.string.pref_title_dossier);
|
||||
builder.setPositiveButton(R.string.action_valid, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface di, int i) {
|
||||
|
||||
// Get parameters
|
||||
dossier1 = editTextDossier1.getText().toString();
|
||||
dossier2 = editTextDossier2.getText().toString();
|
||||
dossier3 = editTextDossier3.getText().toString();
|
||||
|
||||
// Update summary
|
||||
updateSummary();
|
||||
|
||||
// Save parameters
|
||||
editor.putString(context.getString(R.string.pref_key_dossier1), dossier1);
|
||||
editor.putString(context.getString(R.string.pref_key_dossier2), dossier2);
|
||||
editor.putString(context.getString(R.string.pref_key_dossier3), dossier3);
|
||||
editor.putString(context.getString(R.string.pref_key_dossier),
|
||||
dossier1 + " " + dossier2 + " " + dossier3);
|
||||
editor.commit();
|
||||
|
||||
// Trigger the onPreferenceChange event
|
||||
getOnPreferenceChangeListener().onPreferenceChange(me, "");
|
||||
|
||||
di.dismiss();
|
||||
}
|
||||
});
|
||||
builder.setNegativeButton(R.string.action_cancel, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface di, int i) {
|
||||
di.cancel();
|
||||
}
|
||||
});
|
||||
|
||||
super.onPrepareDialogBuilder(builder);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBindDialogView(View view) {
|
||||
|
||||
// Trigger the onPreferenceChange event
|
||||
getOnPreferenceChangeListener().onPreferenceChange(me, "");
|
||||
|
||||
/** Set fixed EditText width, keyboard behaviour on focus and previous values ! **/
|
||||
|
||||
editTextDossier1 = (EditText)view.findViewById(R.id.editTextDossier1);
|
||||
editTextDossier1.setMinWidth(editTextDossier1.getWidth());
|
||||
editTextDossier1.setMaxWidth(editTextDossier1.getWidth());
|
||||
editTextDossier1.setOnFocusChangeListener(new View.OnFocusChangeListener() {
|
||||
public void onFocusChange(View v, boolean hasFocus) {
|
||||
if (hasFocus) {
|
||||
setImeVisibility(v, editTextDossier1, true);
|
||||
}/* else {
|
||||
setImeVisibility(v, editTextDossier1, false);
|
||||
}*/
|
||||
}
|
||||
});
|
||||
editTextDossier1.setText(dossier1);
|
||||
|
||||
editTextDossier2 = (EditText)view.findViewById(R.id.editTextDossier2);
|
||||
editTextDossier2.setMinWidth(editTextDossier2.getWidth());
|
||||
editTextDossier2.setMaxWidth(editTextDossier2.getWidth());
|
||||
editTextDossier2.setOnFocusChangeListener(new View.OnFocusChangeListener() {
|
||||
public void onFocusChange(View v, boolean hasFocus) {
|
||||
if (hasFocus) {
|
||||
setImeVisibility(v, editTextDossier2, true);
|
||||
}/* else {
|
||||
setImeVisibility(v, editTextDossier2, false);
|
||||
}*/
|
||||
}
|
||||
});
|
||||
editTextDossier2.setText(dossier2);
|
||||
|
||||
editTextDossier3 = (EditText)view.findViewById(R.id.editTextDossier3);
|
||||
editTextDossier3.setMinWidth(editTextDossier3.getWidth());
|
||||
editTextDossier3.setMaxWidth(editTextDossier3.getWidth());
|
||||
editTextDossier3.setOnFocusChangeListener(new View.OnFocusChangeListener() {
|
||||
public void onFocusChange(View v, boolean hasFocus) {
|
||||
if (hasFocus) {
|
||||
setImeVisibility(v, editTextDossier3, true);
|
||||
}/* else {
|
||||
setImeVisibility(v, editTextDossier3, false);
|
||||
}*/
|
||||
}
|
||||
});
|
||||
editTextDossier3.setText(dossier3);
|
||||
|
||||
super.onBindDialogView(view);
|
||||
}
|
||||
|
||||
// Nice method to show/hide the virtual keyboard, extracted from the Google's 4.1 source code
|
||||
private void setImeVisibility(View v, final EditText editText, final boolean visible) {
|
||||
|
||||
Runnable mShowImeRunnable = new Runnable() {
|
||||
public void run() {
|
||||
InputMethodManager imm = (InputMethodManager) getContext()
|
||||
.getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
|
||||
if (imm != null) {
|
||||
imm.showSoftInput(editText, 0);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (visible) {
|
||||
v.post(mShowImeRunnable);
|
||||
} else {
|
||||
v.removeCallbacks(mShowImeRunnable);
|
||||
InputMethodManager imm = (InputMethodManager) getContext()
|
||||
.getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
|
||||
if (imm != null) {
|
||||
imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,362 @@
|
||||
package fr.android.pointspermis.settings;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.res.Configuration;
|
||||
import android.media.Ringtone;
|
||||
import android.media.RingtoneManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.preference.ListPreference;
|
||||
import android.preference.Preference;
|
||||
import android.preference.PreferenceActivity;
|
||||
import android.preference.PreferenceFragment;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.v4.app.NavUtils;
|
||||
import android.text.TextUtils;
|
||||
import android.view.MenuItem;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import fr.android.pointspermis.R;
|
||||
|
||||
/**
|
||||
* A {@link PreferenceActivity} that presents a set of application settings. On
|
||||
* handset devices, settings are presented as a single list. On tablets,
|
||||
* settings are split by category, with category headers shown to the left of
|
||||
* the list of settings.
|
||||
* <p/>
|
||||
* See <a href="http://developer.android.com/design/patterns/settings.html">
|
||||
* Android Design: Settings</a> for design guidelines and the <a
|
||||
* href="http://developer.android.com/guide/topics/ui/settings.html">Settings
|
||||
* API Guide</a> for more information on developing a Settings UI.
|
||||
*/
|
||||
public class SettingsActivity extends PreferenceActivity {
|
||||
|
||||
public static String DOSSIER_KEY;
|
||||
public static String DOSSIER1_KEY;
|
||||
public static String DOSSIER2_KEY;
|
||||
public static String DOSSIER3_KEY;
|
||||
public static String CODE_KEY;
|
||||
public static String NOTIFICATION_KEY;
|
||||
public static String FREQUENCY_KEY;
|
||||
public static String RINGTONE_KEY;
|
||||
public static String VIBRATE_KEY;
|
||||
|
||||
/**
|
||||
* Determines whether to always show the simplified settings UI, where
|
||||
* settings are presented in a single list. When false, settings are shown
|
||||
* as a master/detail two-pane view on tablets. When true, a single pane is
|
||||
* shown on tablets.
|
||||
*/
|
||||
private static final boolean ALWAYS_SIMPLE_PREFS = false;
|
||||
|
||||
// Shared Prefs
|
||||
private SharedPreferences prefs;
|
||||
private static SharedPreferences.Editor editor;
|
||||
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
// Shared prefs
|
||||
prefs = getSharedPreferences("fr.android.pointspermis", MODE_PRIVATE);
|
||||
editor = prefs.edit();
|
||||
|
||||
// Get the key name of settings elements
|
||||
DOSSIER_KEY = getString(R.string.pref_key_dossier);
|
||||
DOSSIER1_KEY = getString(R.string.pref_key_dossier1);
|
||||
DOSSIER2_KEY = getString(R.string.pref_key_dossier2);
|
||||
DOSSIER3_KEY = getString(R.string.pref_key_dossier3);
|
||||
CODE_KEY = getString(R.string.pref_key_code);
|
||||
NOTIFICATION_KEY = getString(R.string.pref_key_enable_notifications);
|
||||
FREQUENCY_KEY = getString(R.string.pref_key_sync_frequency);
|
||||
RINGTONE_KEY = getString(R.string.pref_key_ringtone);
|
||||
VIBRATE_KEY = getString(R.string.pref_key_vibrate);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostCreate(Bundle savedInstanceState) {
|
||||
super.onPostCreate(savedInstanceState);
|
||||
|
||||
// Add the 'go back' navigation button (top left)
|
||||
getActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
|
||||
// Show the settings
|
||||
setupSimplePreferencesScreen();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
// Respond to the action bar's Up/Home button
|
||||
case android.R.id.home:
|
||||
NavUtils.navigateUpFromSameTask(this);
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the simplified settings UI if the device configuration if the
|
||||
* device configuration dictates that a simplified, single-pane UI should be
|
||||
* shown.
|
||||
*/
|
||||
private void setupSimplePreferencesScreen() {
|
||||
|
||||
if (!isSimplePreferences(this)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// In the simplified UI, fragments are not used at all and we instead
|
||||
// use the older PreferenceActivity APIs.
|
||||
|
||||
// Add 'connection' preferences.
|
||||
addPreferencesFromResource(R.xml.pref_connection);
|
||||
|
||||
// Add 'notifications' preferences, and a corresponding header.
|
||||
addPreferencesFromResource(R.xml.pref_notification);
|
||||
|
||||
// Bind the summaries of EditText/List/Dialog/Ringtone preferences to
|
||||
// their values. When their values change, their summaries are updated
|
||||
// to reflect the new value, per the Android Design guidelines.
|
||||
manageValueAndSummary(findPreference(DOSSIER_KEY));
|
||||
manageValueAndSummary(findPreference(CODE_KEY));
|
||||
manageValueAndSummary(findPreference(NOTIFICATION_KEY));
|
||||
manageValueAndSummary(findPreference(FREQUENCY_KEY));
|
||||
manageValueAndSummary(findPreference(RINGTONE_KEY));
|
||||
manageValueAndSummary(findPreference(VIBRATE_KEY));
|
||||
}
|
||||
|
||||
/**
|
||||
* A preference value change listener that updates the preference's summary
|
||||
* to reflect its new value.
|
||||
*/
|
||||
private static Preference.OnPreferenceChangeListener changeListener = new Preference.OnPreferenceChangeListener() {
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object value) {
|
||||
|
||||
if (preference.hasKey()) {
|
||||
|
||||
String key = preference.getKey();
|
||||
|
||||
if (key.equals(DOSSIER_KEY)) {
|
||||
|
||||
/* No need to save values or update the summary as this is already done in
|
||||
* custom dialogPreference, but anyway we still do it ..
|
||||
*/
|
||||
|
||||
// Update the summary
|
||||
((DossierDialogPreference) preference).updateSummary();
|
||||
|
||||
// Get and save the dossier number
|
||||
String dossier1 = ((DossierDialogPreference) preference).getDossier1();
|
||||
String dossier2 = ((DossierDialogPreference) preference).getDossier2();
|
||||
String dossier3 = ((DossierDialogPreference) preference).getDossier3();
|
||||
editor.putString(DOSSIER1_KEY, dossier1);
|
||||
editor.putString(DOSSIER2_KEY, dossier2);
|
||||
editor.putString(DOSSIER3_KEY, dossier3);
|
||||
editor.putString(DOSSIER_KEY, dossier1 + " " + dossier2 + " " + dossier3);
|
||||
}
|
||||
if (key.equals(CODE_KEY)) {
|
||||
|
||||
/* Do not change summary: code is private ! */
|
||||
|
||||
// Save the value
|
||||
editor.putString(key, value.toString());
|
||||
}
|
||||
if (key.equals(NOTIFICATION_KEY)) {
|
||||
|
||||
// For checkbox, just save the value
|
||||
editor.putBoolean(key, ((Boolean)value).booleanValue());
|
||||
}
|
||||
if (key.equals(RINGTONE_KEY)) {
|
||||
|
||||
// For ringtone preferences, look up the correct display value
|
||||
// using RingtoneManager.
|
||||
if (TextUtils.isEmpty(value.toString())) {
|
||||
|
||||
// Empty values correspond to 'silent' (no ringtone).
|
||||
preference.setSummary(R.string.pref_ringtone_silent);
|
||||
|
||||
// Save the empty value
|
||||
editor.putString(key, "");
|
||||
|
||||
} else {
|
||||
Ringtone ringtone = RingtoneManager.getRingtone(
|
||||
preference.getContext(), Uri.parse(value.toString()));
|
||||
|
||||
if (ringtone == null) {
|
||||
// Clear the summary if there was a lookup error.
|
||||
preference.setSummary(null);
|
||||
} else {
|
||||
// Set the summary to reflect the new ringtone display
|
||||
// name.
|
||||
String name = ringtone.getTitle(preference.getContext());
|
||||
preference.setSummary(name);
|
||||
|
||||
// Save the value
|
||||
editor.putString(key, name);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (key.equals(FREQUENCY_KEY)) {
|
||||
|
||||
// For list preferences, look up the correct display value in
|
||||
// the preference's 'entries' list.
|
||||
ListPreference listPreference = (ListPreference) preference;
|
||||
int index = listPreference.findIndexOfValue(value.toString());
|
||||
|
||||
// Set the summary to reflect the new value.
|
||||
preference.setSummary(listPreference.getEntries()[index]);
|
||||
|
||||
// Save the value
|
||||
editor.putString(key, listPreference.getEntries()[index].toString());
|
||||
}
|
||||
if (key.equals(VIBRATE_KEY)) {
|
||||
|
||||
// For checkbox, just save the value
|
||||
editor.putBoolean(key, ((Boolean)value).booleanValue());
|
||||
}
|
||||
|
||||
editor.commit();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Binds a preference's summary to its value. More specifically, when the
|
||||
* preference's value is changed, its summary (line of text below the
|
||||
* preference title) is updated to reflect the value. The summary is also
|
||||
* immediately updated upon calling this method. The exact display format is
|
||||
* dependent on the type of preference.
|
||||
*
|
||||
* @see #changeListener
|
||||
*/
|
||||
private static void manageValueAndSummary(Preference preference) {
|
||||
|
||||
// Set the listener to watch for value changes.
|
||||
preference.setOnPreferenceChangeListener(changeListener);
|
||||
|
||||
String key = preference.getKey();
|
||||
|
||||
// Trigger the listener immediately with the preference's current value to
|
||||
// update summary on element we want
|
||||
|
||||
// /!\ not for dossier as it is self-managed neither code: not secure /!\
|
||||
|
||||
// Text parameters
|
||||
if (key.equals(RINGTONE_KEY) || key.equals(FREQUENCY_KEY)) {
|
||||
|
||||
// Safe list default changes
|
||||
if (!PreferenceManager
|
||||
.getDefaultSharedPreferences(preference.getContext())
|
||||
.getString(preference.getKey(), "").equals("") ) {
|
||||
|
||||
changeListener.onPreferenceChange(preference,
|
||||
PreferenceManager
|
||||
.getDefaultSharedPreferences(preference.getContext())
|
||||
.getString(preference.getKey(), "")
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Boolean parameters
|
||||
if (key.equals(NOTIFICATION_KEY) || (key.equals(VIBRATE_KEY))) {
|
||||
changeListener.onPreferenceChange(preference,
|
||||
PreferenceManager
|
||||
.getDefaultSharedPreferences(preference.getContext())
|
||||
.getBoolean(preference.getKey(), false)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This fragment shows general preferences only. It is used when the
|
||||
* activity is showing a two-pane settings UI.
|
||||
*/
|
||||
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
|
||||
public static class ConnectionPreferenceFragment extends PreferenceFragment {
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
addPreferencesFromResource(R.xml.pref_connection);
|
||||
|
||||
// Bind the summaries of EditText/List/Dialog/Ringtone preferences
|
||||
// to their values. When their values change, their summaries are
|
||||
// updated to reflect the new value, per the Android Design
|
||||
// guidelines.
|
||||
manageValueAndSummary(findPreference(DOSSIER_KEY));
|
||||
manageValueAndSummary(findPreference(CODE_KEY));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This fragment shows notification preferences only. It is used when the
|
||||
* activity is showing a two-pane settings UI.
|
||||
*/
|
||||
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
|
||||
public static class NotificationPreferenceFragment extends PreferenceFragment {
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
addPreferencesFromResource(R.xml.pref_notification);
|
||||
|
||||
// Bind the summaries of EditText/List/Dialog/Ringtone preferences
|
||||
// to their values. When their values change, their summaries are
|
||||
// updated to reflect the new value, per the Android Design
|
||||
// guidelines.
|
||||
manageValueAndSummary(findPreference(NOTIFICATION_KEY));
|
||||
manageValueAndSummary(findPreference(FREQUENCY_KEY));
|
||||
manageValueAndSummary(findPreference(RINGTONE_KEY));
|
||||
manageValueAndSummary(findPreference(VIBRATE_KEY));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public boolean onIsMultiPane() {
|
||||
return isXLargeTablet(this) && !isSimplePreferences(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to determine if the device has an extra-large screen. For
|
||||
* example, 10" tablets are extra-large.
|
||||
*/
|
||||
private static boolean isXLargeTablet(Context context) {
|
||||
return (context.getResources().getConfiguration().screenLayout
|
||||
& Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_XLARGE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the simplified settings UI should be shown. This is
|
||||
* true if this is forced via {@link #ALWAYS_SIMPLE_PREFS}, or the device
|
||||
* doesn't have newer APIs like {@link PreferenceFragment}, or the device
|
||||
* doesn't have an extra-large screen. In these cases, a single-pane
|
||||
* "simplified" settings UI should be shown.
|
||||
*/
|
||||
private static boolean isSimplePreferences(Context context) {
|
||||
return ALWAYS_SIMPLE_PREFS
|
||||
|| Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB
|
||||
|| !isXLargeTablet(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
|
||||
public void onBuildHeaders(List<Header> target) {
|
||||
if (!isSimplePreferences(this)) {
|
||||
loadHeadersFromResource(R.xml.pref_headers, target);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
package fr.android.pointspermis.tools;
|
||||
|
||||
import android.content.res.AssetManager;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
* Created by vins on 08/01/15.
|
||||
*/
|
||||
public class AssetsTools {
|
||||
|
||||
public static void copyFileOrDir(String path, String dest, AssetManager assetManager) {
|
||||
|
||||
String assets[] = null;
|
||||
try {
|
||||
Log.i("INFO", "copyFileOrDir() " + path);
|
||||
assets = assetManager.list(path);
|
||||
if (assets.length == 0) {
|
||||
copyFile(path, dest, assetManager);
|
||||
} else {
|
||||
String fullPath = dest + path;
|
||||
File dir = new File(fullPath);
|
||||
if (!dir.exists() && !path.startsWith("images") && !path.startsWith("sounds") && !path.startsWith("webkit"))
|
||||
if (!dir.mkdirs())
|
||||
Log.i("INFO", "could not create dir "+fullPath);
|
||||
for (int i = 0; i < assets.length; ++i) {
|
||||
String p;
|
||||
if (path.equals(""))
|
||||
p = "";
|
||||
else
|
||||
p = path + "/";
|
||||
|
||||
if (!path.startsWith("images") && !path.startsWith("sounds") && !path.startsWith("webkit"))
|
||||
copyFileOrDir(p + assets[i], dest, assetManager);
|
||||
}
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
Log.e("ERROR", "I/O Exception", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static void copyFile(String filename, String dest, AssetManager assetManager) {
|
||||
|
||||
InputStream in = null;
|
||||
OutputStream out = null;
|
||||
String newFileName = null;
|
||||
try {
|
||||
in = assetManager.open(filename);
|
||||
if (filename.endsWith(".jpg")) // extension was added to avoid compression on APK file
|
||||
newFileName = dest + filename.substring(0, filename.length()-4);
|
||||
else
|
||||
newFileName = dest + filename;
|
||||
|
||||
if (!new File(newFileName).exists()) {
|
||||
Log.i("INFO", "copyFile() "+filename);
|
||||
out = new FileOutputStream(newFileName);
|
||||
byte[] buffer = new byte[1024];
|
||||
int read;
|
||||
while ((read = in.read(buffer)) != -1) {
|
||||
out.write(buffer, 0, read);
|
||||
}
|
||||
in.close();
|
||||
in = null;
|
||||
out.flush();
|
||||
out.close();
|
||||
out = null;
|
||||
}
|
||||
else {
|
||||
Log.i("INFO", filename + " already exists, skipping..");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e("ERROR", "Exception in copyFile() of "+newFileName);
|
||||
Log.e("ERROR", "Exception in copyFile() "+e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
public static Bitmap getBitmapFromAsset(String filePath, AssetManager assetManager) {
|
||||
|
||||
InputStream istr;
|
||||
Bitmap bitmap = null;
|
||||
try {
|
||||
istr = assetManager.open(filePath);
|
||||
bitmap = BitmapFactory.decodeStream(istr);
|
||||
} catch (IOException e) {
|
||||
Log.e("ERROR", "Unable to get bitmap '" + filePath + "' from assets");
|
||||
}
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
}
|
99
app/src/main/java/fr/android/pointspermis/web/CustomSSL.java
Normal file
@ -0,0 +1,99 @@
|
||||
package fr.android.pointspermis.web;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.Socket;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLSocket;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
|
||||
/**
|
||||
* Created by vins on 15/01/15.
|
||||
*/
|
||||
public class CustomSSL {
|
||||
|
||||
private static class CustomSSLSocket extends DelegateSSLSocket {
|
||||
|
||||
private CustomSSLSocket(SSLSocket delegate) {
|
||||
super(delegate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEnabledProtocols(String[] protocols) {
|
||||
if (protocols != null && protocols.length == 1 && "SSLv3".equals(protocols[0])) {
|
||||
List<String> enabledProtocols = new ArrayList<>(Arrays.asList(delegate.getEnabledProtocols()));
|
||||
if (enabledProtocols.size() > 1) {
|
||||
enabledProtocols.remove("SSLv3");
|
||||
Log.d("DEBUG", "Removed SSLv3 from enabled protocols");
|
||||
} else {
|
||||
Log.d("DEBUG", "SSL stuck with protocol available for " + String.valueOf(enabledProtocols));
|
||||
}
|
||||
protocols = enabledProtocols.toArray(new String[enabledProtocols.size()]);
|
||||
}
|
||||
|
||||
super.setEnabledProtocols(protocols);
|
||||
}
|
||||
}
|
||||
|
||||
public static class CustomSSLSocketFactory extends SSLSocketFactory {
|
||||
|
||||
private final SSLSocketFactory delegate;
|
||||
|
||||
public CustomSSLSocketFactory() {
|
||||
this.delegate = HttpsURLConnection.getDefaultSSLSocketFactory();
|
||||
}
|
||||
|
||||
public CustomSSLSocketFactory(SSLContext context) { this.delegate = context.getSocketFactory(); }
|
||||
|
||||
@Override
|
||||
public String[] getDefaultCipherSuites() {
|
||||
return delegate.getDefaultCipherSuites();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getSupportedCipherSuites() {
|
||||
return delegate.getSupportedCipherSuites();
|
||||
}
|
||||
|
||||
private static Socket makeSocketSafe(Socket socket) {
|
||||
if (socket instanceof SSLSocket) {
|
||||
socket = new CustomSSLSocket((SSLSocket) socket);
|
||||
// Enable all supported cipher
|
||||
((SSLSocket) socket).setEnabledCipherSuites(((SSLSocket) socket).getSupportedCipherSuites());
|
||||
}
|
||||
return socket;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
|
||||
return makeSocketSafe(delegate.createSocket(s, host, port, autoClose));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(String host, int port) throws IOException {
|
||||
return makeSocketSafe(delegate.createSocket(host, port));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException {
|
||||
return makeSocketSafe(delegate.createSocket(host, port, localHost, localPort));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(InetAddress host, int port) throws IOException {
|
||||
return makeSocketSafe(delegate.createSocket(host, port));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
|
||||
return makeSocketSafe(delegate.createSocket(address, port, localAddress, localPort));
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,331 @@
|
||||
package fr.android.pointspermis.web;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.InetAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.SocketException;
|
||||
import java.nio.channels.SocketChannel;
|
||||
|
||||
import javax.net.ssl.HandshakeCompletedListener;
|
||||
import javax.net.ssl.SSLParameters;
|
||||
import javax.net.ssl.SSLSession;
|
||||
import javax.net.ssl.SSLSocket;
|
||||
|
||||
/**
|
||||
* Created by vins on 15/01/15.
|
||||
*/
|
||||
public class DelegateSSLSocket extends SSLSocket {
|
||||
|
||||
protected final SSLSocket delegate;
|
||||
|
||||
DelegateSSLSocket(SSLSocket delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getSupportedCipherSuites() {
|
||||
return delegate.getSupportedCipherSuites();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getEnabledCipherSuites() {
|
||||
return delegate.getEnabledCipherSuites();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEnabledCipherSuites(String[] suites) {
|
||||
delegate.setEnabledCipherSuites(suites);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getSupportedProtocols() {
|
||||
return delegate.getSupportedProtocols();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getEnabledProtocols() {
|
||||
return delegate.getEnabledProtocols();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEnabledProtocols(String[] protocols) {
|
||||
delegate.setEnabledProtocols(protocols);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SSLSession getSession() {
|
||||
return delegate.getSession();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addHandshakeCompletedListener(HandshakeCompletedListener listener) {
|
||||
delegate.addHandshakeCompletedListener(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeHandshakeCompletedListener(HandshakeCompletedListener listener) {
|
||||
delegate.removeHandshakeCompletedListener(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startHandshake() throws IOException {
|
||||
delegate.startHandshake();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUseClientMode(boolean mode) {
|
||||
delegate.setUseClientMode(mode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getUseClientMode() {
|
||||
return delegate.getUseClientMode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNeedClientAuth(boolean need) {
|
||||
delegate.setNeedClientAuth(need);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setWantClientAuth(boolean want) {
|
||||
delegate.setWantClientAuth(want);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getNeedClientAuth() {
|
||||
return delegate.getNeedClientAuth();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getWantClientAuth() {
|
||||
return delegate.getWantClientAuth();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEnableSessionCreation(boolean flag) {
|
||||
delegate.setEnableSessionCreation(flag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getEnableSessionCreation() {
|
||||
return delegate.getEnableSessionCreation();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bind(SocketAddress localAddr) throws IOException {
|
||||
delegate.bind(localAddr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void close() throws IOException {
|
||||
delegate.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connect(SocketAddress remoteAddr) throws IOException {
|
||||
delegate.connect(remoteAddr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connect(SocketAddress remoteAddr, int timeout) throws IOException {
|
||||
delegate.connect(remoteAddr, timeout);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SocketChannel getChannel() {
|
||||
return delegate.getChannel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InetAddress getInetAddress() {
|
||||
return delegate.getInetAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getInputStream() throws IOException {
|
||||
return delegate.getInputStream();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getKeepAlive() throws SocketException {
|
||||
return delegate.getKeepAlive();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InetAddress getLocalAddress() {
|
||||
return delegate.getLocalAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLocalPort() {
|
||||
return delegate.getLocalPort();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SocketAddress getLocalSocketAddress() {
|
||||
return delegate.getLocalSocketAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getOOBInline() throws SocketException {
|
||||
return delegate.getOOBInline();
|
||||
}
|
||||
|
||||
@Override
|
||||
public OutputStream getOutputStream() throws IOException {
|
||||
return delegate.getOutputStream();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPort() {
|
||||
return delegate.getPort();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized int getReceiveBufferSize() throws SocketException {
|
||||
return delegate.getReceiveBufferSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SocketAddress getRemoteSocketAddress() {
|
||||
return delegate.getRemoteSocketAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getReuseAddress() throws SocketException {
|
||||
return delegate.getReuseAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized int getSendBufferSize() throws SocketException {
|
||||
return delegate.getSendBufferSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSoLinger() throws SocketException {
|
||||
return delegate.getSoLinger();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized int getSoTimeout() throws SocketException {
|
||||
return delegate.getSoTimeout();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getTcpNoDelay() throws SocketException {
|
||||
return delegate.getTcpNoDelay();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTrafficClass() throws SocketException {
|
||||
return delegate.getTrafficClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBound() {
|
||||
return delegate.isBound();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isClosed() {
|
||||
return delegate.isClosed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConnected() {
|
||||
return delegate.isConnected();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInputShutdown() {
|
||||
return delegate.isInputShutdown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOutputShutdown() {
|
||||
return delegate.isOutputShutdown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendUrgentData(int value) throws IOException {
|
||||
delegate.sendUrgentData(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setKeepAlive(boolean keepAlive) throws SocketException {
|
||||
delegate.setKeepAlive(keepAlive);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOOBInline(boolean oobinline) throws SocketException {
|
||||
delegate.setOOBInline(oobinline);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPerformancePreferences(int connectionTime, int latency, int bandwidth) {
|
||||
delegate.setPerformancePreferences(connectionTime, latency, bandwidth);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void setReceiveBufferSize(int size) throws SocketException {
|
||||
delegate.setReceiveBufferSize(size);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setReuseAddress(boolean reuse) throws SocketException {
|
||||
delegate.setReuseAddress(reuse);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void setSendBufferSize(int size) throws SocketException {
|
||||
delegate.setSendBufferSize(size);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSoLinger(boolean on, int timeout) throws SocketException {
|
||||
delegate.setSoLinger(on, timeout);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void setSoTimeout(int timeout) throws SocketException {
|
||||
delegate.setSoTimeout(timeout);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSSLParameters(SSLParameters p) {
|
||||
delegate.setSSLParameters(p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTcpNoDelay(boolean on) throws SocketException {
|
||||
delegate.setTcpNoDelay(on);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTrafficClass(int value) throws SocketException {
|
||||
delegate.setTrafficClass(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdownInput() throws IOException {
|
||||
delegate.shutdownInput();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdownOutput() throws IOException {
|
||||
delegate.shutdownOutput();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return delegate.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return delegate.equals(o);
|
||||
}
|
||||
}
|
310
app/src/main/java/fr/android/pointspermis/web/HTTPSConnect.java
Normal file
@ -0,0 +1,310 @@
|
||||
package fr.android.pointspermis.web;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.util.Log;
|
||||
import org.apache.http.util.ByteArrayBuffer;
|
||||
import org.jsoup.Jsoup;
|
||||
import org.jsoup.nodes.Document;
|
||||
|
||||
import javax.net.ssl.*;
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
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.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Created by vins on 08/01/15.
|
||||
*/
|
||||
public class HTTPSConnect {
|
||||
|
||||
private Certificate ca;
|
||||
private HttpsURLConnection urlConnection;
|
||||
private List<String> cookies;
|
||||
|
||||
private static final int READ_TIMEOUT = 10000;
|
||||
private static final int CONNECT_TIMEOUT = 15000;
|
||||
private static final char PARAMETER_DELIMITER = '&';
|
||||
private static final char PARAMETER_EQUALS_CHAR = '=';
|
||||
|
||||
public HTTPSConnect(InputStream certificate) throws Exception {
|
||||
|
||||
// Init a list of cookies
|
||||
cookies = new ArrayList<String>();
|
||||
|
||||
// Load certificate
|
||||
try {
|
||||
ca = loadCA(certificate);
|
||||
} catch (Exception e) {
|
||||
throw new Exception("Unable to load CA certificate: " + e.getMessage());
|
||||
}
|
||||
|
||||
// Create and set custom SSLSocketFactory (which trust the ca) as the default one
|
||||
try {
|
||||
HttpsURLConnection.setDefaultSSLSocketFactory(createSSLSocketFactory(ca));
|
||||
} catch (Exception e) {
|
||||
throw new Exception("Unable to create custom SSLSocketFactory: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private HttpsURLConnection openConnection(String u) throws Exception {
|
||||
|
||||
URL url;
|
||||
HttpsURLConnection urlConnection;
|
||||
|
||||
url = new URL(u);
|
||||
urlConnection = (HttpsURLConnection) url.openConnection();
|
||||
|
||||
// Get cookies
|
||||
if(cookies.isEmpty()) {
|
||||
cookies = urlConnection.getHeaderFields().get("Set-Cookie");
|
||||
}
|
||||
else {
|
||||
// Reuse all previous cookies
|
||||
for (String cookie : cookies) {
|
||||
urlConnection.addRequestProperty("Cookie", cookie.split(";", 2)[0]);
|
||||
}
|
||||
}
|
||||
|
||||
// Set a custom SSL socket factory
|
||||
//urlConnection.setSSLSocketFactory(socketFactory);
|
||||
|
||||
/* Specify a custom hostname verifier
|
||||
HostnameVerifier hostnameVerifier = new HostnameVerifier() {
|
||||
@Override
|
||||
public boolean verify(String hostname, SSLSession session) {
|
||||
HostnameVerifier hv =
|
||||
HttpsURLConnection.getDefaultHostnameVerifier();
|
||||
return hv.verify("tele7.interieur.gouv.fr", session);
|
||||
}
|
||||
};
|
||||
urlConnection.setHostnameVerifier(hostnameVerifier);
|
||||
*/
|
||||
|
||||
// Set timeouts
|
||||
urlConnection.setReadTimeout(READ_TIMEOUT);
|
||||
urlConnection.setConnectTimeout(CONNECT_TIMEOUT);
|
||||
|
||||
return urlConnection;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
if (urlConnection != null) {
|
||||
urlConnection.disconnect();
|
||||
}
|
||||
cookies = new ArrayList<String>();
|
||||
}
|
||||
|
||||
public Certificate getCertificate() {
|
||||
return ca;
|
||||
}
|
||||
|
||||
private InputStream getPage(String u) throws Exception {
|
||||
|
||||
InputStream in;
|
||||
urlConnection = openConnection(u);
|
||||
|
||||
try {
|
||||
in = urlConnection.getInputStream();
|
||||
} catch (IOException e) {
|
||||
throw new Exception("Unable to get remote input stream from SSL connection: " + e.getMessage());
|
||||
}
|
||||
|
||||
return in;
|
||||
}
|
||||
|
||||
public Document getHTML(String u) throws Exception {
|
||||
|
||||
Document doc = null;
|
||||
InputStream in = getPage(u);
|
||||
|
||||
try {
|
||||
doc = Jsoup.parse(in, null, "");
|
||||
} catch (IOException e) {
|
||||
throw new Exception("Unable to parse InputStream html to create the JSoup Document: " + e.getMessage());
|
||||
}
|
||||
|
||||
return doc;
|
||||
}
|
||||
|
||||
public Bitmap getImage(String u) throws Exception {
|
||||
|
||||
Bitmap img = null;
|
||||
InputStream in = getPage(u);
|
||||
|
||||
BufferedInputStream bis = new BufferedInputStream(in, 8190);
|
||||
|
||||
ByteArrayBuffer baf = new ByteArrayBuffer(50);
|
||||
int current = 0;
|
||||
while ((current = bis.read()) != -1) {
|
||||
baf.append((byte)current);
|
||||
}
|
||||
byte[] imageData = baf.toByteArray();
|
||||
|
||||
img = BitmapFactory.decodeByteArray(imageData, 0, imageData.length);
|
||||
|
||||
return img;
|
||||
}
|
||||
|
||||
public Document postData(String u, Map<String, String> urlParams) throws Exception {
|
||||
|
||||
Document doc = null;
|
||||
HttpsURLConnection urlConnection = openConnection(u);
|
||||
String urlParameters = createQueryStringForParameters(urlParams);
|
||||
//Log.d("DEBUG", "POST Request params: " + urlParameters);
|
||||
|
||||
try {
|
||||
urlConnection.setRequestMethod("POST");
|
||||
urlConnection.setRequestProperty("Content-Type",
|
||||
"application/x-www-form-urlencoded");
|
||||
|
||||
urlConnection.setRequestProperty("Content-Length", "" +
|
||||
Integer.toString(urlParameters.getBytes().length));
|
||||
urlConnection.setRequestProperty("Content-Language", "fr-FR");
|
||||
|
||||
urlConnection.setUseCaches(false);
|
||||
urlConnection.setDoInput(true);
|
||||
urlConnection.setDoOutput(true);
|
||||
} catch (Exception e) {
|
||||
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
|
||||
//Send request
|
||||
try {
|
||||
DataOutputStream wr = new DataOutputStream(urlConnection.getOutputStream());
|
||||
wr.writeBytes(urlParameters);
|
||||
wr.flush();
|
||||
wr.close();
|
||||
} catch (Exception e) {
|
||||
throw new Exception("Unable to send the POST request: " + e.getMessage());
|
||||
}
|
||||
|
||||
//Get Response
|
||||
InputStream in = urlConnection.getInputStream();
|
||||
try {
|
||||
doc = Jsoup.parse(in, null, "");
|
||||
} catch (IOException e) {
|
||||
throw new Exception("Unable to parse InputStream html to create the JSoup Document: " + e.getMessage());
|
||||
}
|
||||
|
||||
return doc;
|
||||
}
|
||||
|
||||
private Certificate loadCA(InputStream crt) throws Exception {
|
||||
|
||||
Certificate ca;
|
||||
CertificateFactory cf;
|
||||
|
||||
// Create certificateFactory instance
|
||||
try {
|
||||
cf = CertificateFactory.getInstance("X.509");
|
||||
} catch (CertificateException e) {
|
||||
throw new Exception("Can not get a X.509 certificate instance: " + e.getMessage());
|
||||
}
|
||||
|
||||
// Read and load the certificate
|
||||
InputStream caInput = new BufferedInputStream(crt);
|
||||
try {
|
||||
ca = cf.generateCertificate(caInput);
|
||||
//Log.d("DEBUG", "ca=" + ((X509Certificate) ca).getSubjectDN());
|
||||
} catch (CertificateException e) {
|
||||
throw new Exception("Unable to read the certificate X509: " + e.getMessage());
|
||||
} finally {
|
||||
try {
|
||||
caInput.close();
|
||||
} catch (IOException e) {
|
||||
throw new Exception("Can not close the certificate file: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
return ca;
|
||||
}
|
||||
|
||||
private SSLSocketFactory createSSLSocketFactory(Certificate ca) throws Exception {
|
||||
|
||||
SSLContext sslContext;
|
||||
CustomSSL.CustomSSLSocketFactory socketFactory;
|
||||
KeyStore keyStore;
|
||||
TrustManagerFactory tmf;
|
||||
|
||||
// Create a KeyStore containing our trusted CAs
|
||||
String keyStoreType = KeyStore.getDefaultType();
|
||||
|
||||
try {
|
||||
keyStore = KeyStore.getInstance(keyStoreType);
|
||||
} catch (KeyStoreException e) {
|
||||
throw new Exception("Can not get KeyStore instance: " + e.getMessage());
|
||||
}
|
||||
try {
|
||||
keyStore.load(null, null);
|
||||
} catch (Exception e) {
|
||||
throw new Exception("Error during keystore loading: " + e.getMessage());
|
||||
}
|
||||
try {
|
||||
keyStore.setCertificateEntry("ca", ca);
|
||||
} catch (KeyStoreException e) {
|
||||
throw new Exception("Unable to read certificate entry 'ca': " + e.getMessage());
|
||||
}
|
||||
|
||||
// Create a TrustManager that trusts the CAs in our KeyStore
|
||||
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
|
||||
try {
|
||||
tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new Exception("Can not get TrustManager instance: " + e.getMessage());
|
||||
}
|
||||
try {
|
||||
tmf.init(keyStore);
|
||||
} catch (KeyStoreException e) {
|
||||
throw new Exception("Unable to openConnection keystore from trustmanager: " + e.getMessage());
|
||||
}
|
||||
|
||||
// Init a new SSLContext (TLS)
|
||||
sslContext = SSLContext.getInstance("TLS");
|
||||
sslContext.init(null, tmf.getTrustManagers(), null);
|
||||
|
||||
// Create the custom SSLSocketFactory
|
||||
socketFactory = new CustomSSL.CustomSSLSocketFactory(sslContext);
|
||||
|
||||
return socketFactory;
|
||||
}
|
||||
|
||||
private String createQueryStringForParameters(Map<String, String> parameters) throws Exception {
|
||||
|
||||
StringBuilder parametersAsQueryString = new StringBuilder();
|
||||
|
||||
if (parameters != null) {
|
||||
boolean firstParameter = true;
|
||||
|
||||
for (String parameterName : parameters.keySet()) {
|
||||
|
||||
if (!firstParameter) {
|
||||
parametersAsQueryString.append(PARAMETER_DELIMITER);
|
||||
}
|
||||
|
||||
try {
|
||||
parametersAsQueryString
|
||||
.append(URLEncoder.encode(parameterName, "UTF-8"))
|
||||
.append(PARAMETER_EQUALS_CHAR)
|
||||
.append(URLEncoder.encode(parameters.get(parameterName), "UTF-8"));
|
||||
} catch (Exception e) {
|
||||
throw new Exception("Error during parameters encoding: " + e.getMessage());
|
||||
}
|
||||
|
||||
firstParameter = false;
|
||||
}
|
||||
}
|
||||
|
||||
return parametersAsQueryString.toString();
|
||||
}
|
||||
}
|
286
app/src/main/java/fr/android/pointspermis/web/WebTask.java
Normal file
@ -0,0 +1,286 @@
|
||||
package fr.android.pointspermis.web;
|
||||
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.os.AsyncTask;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
import fr.android.pointspermis.MainActivity;
|
||||
import fr.android.pointspermis.captcha.Captcha;
|
||||
import fr.android.pointspermis.web.HTTPSConnect;
|
||||
import org.jsoup.nodes.Document;
|
||||
import org.jsoup.select.Elements;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Created by vins on 07/01/15.
|
||||
*/
|
||||
public class WebTask extends AsyncTask<String, String, String> {
|
||||
|
||||
private final int RETRY = 3;
|
||||
private final int RETRY_CAPTCHA = 15;
|
||||
|
||||
private final String IDENTIFICATION_URL = "https://tele7.interieur.gouv.fr/telepoints/identification.do";
|
||||
private final String CONSULTATION_URL = "https://tele7.interieur.gouv.fr/telepoints/consultation.do";
|
||||
private final String CAPTCHA_URL = "https://tele7.interieur.gouv.fr/telepoints/jcaptcha?id=n&rnd=";
|
||||
private final String TOKEN_NAME = "org.apache.struts.taglib.html.TOKEN";
|
||||
private final String CERTIFICATE = "tele7.interieur.gouv.fr.cert";
|
||||
|
||||
private final Context context;
|
||||
private MainActivity main;
|
||||
private ProgressDialog pDialog;
|
||||
private List<String> result;
|
||||
|
||||
public WebTask(Context context, MainActivity main) {
|
||||
this.context = context;
|
||||
this.main = main;
|
||||
|
||||
result = new ArrayList<>();
|
||||
|
||||
System.setProperty("https.protocols", "TLSv1");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String doInBackground(String... inputs) {
|
||||
|
||||
int count = 0, captcha = 0;
|
||||
List<String> infos = null;
|
||||
|
||||
while (count < RETRY && captcha < RETRY_CAPTCHA) {
|
||||
infos = getInfos(inputs[0], inputs[1], inputs[2], inputs[3]);
|
||||
if (infos == null) {
|
||||
// Return null only if a big problem happened
|
||||
return null;
|
||||
}
|
||||
if (infos.isEmpty()) {
|
||||
// Same as previous
|
||||
return null;
|
||||
}
|
||||
if (infos.size() == 1) {
|
||||
if (infos.get(infos.size()-1).equals("RETRY")) {
|
||||
captcha++; count = 0;
|
||||
continue;
|
||||
}
|
||||
if (infos.get(infos.size()-1).contains("ERROR")) {
|
||||
count++; captcha = 0;
|
||||
continue;
|
||||
}
|
||||
// Also a big problem (should never happen)
|
||||
return null;
|
||||
}
|
||||
if (infos.size() == 3) {
|
||||
result.addAll(infos);
|
||||
return "OK";
|
||||
}
|
||||
}
|
||||
|
||||
// Return the original error
|
||||
return infos.get(0);
|
||||
}
|
||||
|
||||
public List<String> getInfos(String code1, String code2, String code3, String pwd) {
|
||||
|
||||
List<String> infos = new ArrayList<>();
|
||||
result.clear();
|
||||
|
||||
// Create and init a new connection
|
||||
HTTPSConnect connection;
|
||||
try {
|
||||
connection = new HTTPSConnect(main.getAssets().open(CERTIFICATE));
|
||||
} catch (Exception e) {
|
||||
Log.e("ERROR", "Cannot Init HTTPSConnect: " + e.getMessage());
|
||||
return Collections.singletonList("ERROR INIT");
|
||||
}
|
||||
|
||||
// Get the identification html page
|
||||
Document docId = null;
|
||||
try {
|
||||
docId = connection.getHTML(IDENTIFICATION_URL);
|
||||
} catch (Exception e) {
|
||||
Log.e("ERROR", "Document initialisation error: " + e.getMessage());
|
||||
return Collections.singletonList("ERROR GET");
|
||||
}
|
||||
|
||||
// Parse HTML page and retrieve all needed infos
|
||||
String token = docId.body().getElementsByAttributeValue("name", TOKEN_NAME).attr("value");
|
||||
String dossier1_name = docId.body().getElementById("dossier1").attr("name");
|
||||
String dossier2_name = docId.body().getElementById("dossier2").attr("name");
|
||||
String dossier3_name = docId.body().getElementById("dossier3").attr("name");
|
||||
String code_name = docId.body().getElementsByAttributeValue("type", "password").attr("name");
|
||||
String captcha_name = docId.body().getElementsByAttributeValueContaining("name", "captcha_response").attr("name");
|
||||
|
||||
// Generate a random click position over the send button
|
||||
int xMin = 5, xMax = 138;
|
||||
int yMin = 5, yMax = 21;
|
||||
int x = new Random().nextInt((xMax - xMin) + 1) + xMin;
|
||||
int y = new Random().nextInt((yMax - yMin) + 1) + yMin;
|
||||
|
||||
// Get the captcha img
|
||||
Bitmap img = null;
|
||||
try {
|
||||
img = connection.getImage(CAPTCHA_URL + code_name.replace("value(", "").replace("code)", ""));
|
||||
} catch (Exception e) {
|
||||
Log.e("ERROR", "Image downloading error: " + e.getMessage());
|
||||
return Collections.singletonList("ERROR CAPTCHA");
|
||||
}
|
||||
|
||||
// Decoding captcha
|
||||
Captcha captcha = new Captcha(context.getFilesDir().getPath());
|
||||
String code_captcha = captcha.getCode(img);
|
||||
if (code_captcha == null) {
|
||||
Log.e("ERROR", "Error while decoding captcha");
|
||||
return Collections.singletonList("ERROR OCR");
|
||||
}
|
||||
|
||||
// Set request parameters
|
||||
Map<String, String> urlParams = new HashMap<>();
|
||||
urlParams.put("y", Integer.toString(y));
|
||||
urlParams.put("x", Integer.toString(x));
|
||||
urlParams.put(captcha_name, code_captcha);
|
||||
urlParams.put(code_name, pwd);
|
||||
urlParams.put(dossier3_name, code3);
|
||||
urlParams.put(dossier2_name, code2);
|
||||
urlParams.put(dossier1_name, code1);
|
||||
urlParams.put(TOKEN_NAME, token);
|
||||
|
||||
// Send the post request
|
||||
Document docCons = null;
|
||||
try {
|
||||
docCons = connection.postData(CONSULTATION_URL, urlParams);
|
||||
} catch (Exception e) {
|
||||
Log.e("ERROR", "POST request error: " + e.getMessage());
|
||||
return Collections.singletonList("ERROR POST");
|
||||
}
|
||||
|
||||
// Clean connection cookies
|
||||
connection.clear();
|
||||
|
||||
// Get the solde
|
||||
Elements elts = docCons.getElementsContainingText("SUR UN CAPITAL DE");
|
||||
if (elts != null && !elts.isEmpty()) {
|
||||
String solde = elts.get(elts.size()-1).html();
|
||||
solde = solde.substring(0, solde.indexOf(' ')) + " / " +
|
||||
solde.substring(solde.lastIndexOf(" ")+1, solde.length()-1);
|
||||
Log.i("INFO", "Solde: " + solde);
|
||||
infos.add(solde);
|
||||
|
||||
// Get the name
|
||||
elts = docCons.getElementsContainingText("Bonjour");
|
||||
if (elts != null && !elts.isEmpty()) {
|
||||
String name = elts.get(elts.size()-1).html();
|
||||
name = name.replace("Bonjour, ", "");
|
||||
Log.i("INFO", "Name: " + name);
|
||||
infos.add(name);
|
||||
|
||||
// Get the birthday
|
||||
elts = docCons.getElementsContainingText("Date de Naissance");
|
||||
if (elts != null && !elts.isEmpty()) {
|
||||
String birthday = elts.get(elts.size()-1).html();
|
||||
birthday = birthday.replace("Date de Naissance", "").replace(" ", "").replace(" ", "");
|
||||
Log.i("INFO", "Birthday: " + birthday);
|
||||
infos.add(birthday);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (infos.size() < 3) {
|
||||
elts = docCons.getElementsByClass("rouge12b");
|
||||
if (!elts.isEmpty()) {
|
||||
// CAPTCHA ERROR
|
||||
if (elts.get(elts.size()-1).html().contains("Le code de s")) {
|
||||
Log.e("ERROR", "Wrong captcha !");
|
||||
return Collections.singletonList("RETRY");
|
||||
} else { // USER ERROR
|
||||
if (elts.get(elts.size()-1).html().contains("Ce dossier n'existe pas")) {
|
||||
Log.e("ERROR", "Dossier num is unknown !");
|
||||
return Collections.singletonList("ERROR DOSSIER");
|
||||
}
|
||||
if (elts.get(elts.size()-1).html().contains("ro de dossier est incorrect")) {
|
||||
Log.e("ERROR", "Dossier num is invalid !");
|
||||
return Collections.singletonList("ERROR DOSSIER");
|
||||
}
|
||||
if (elts.get(elts.size()-1).html().contains("Le code confidentiel est incorrect")) {
|
||||
Log.e("ERROR", "Personal code is wrong !");
|
||||
return Collections.singletonList("ERROR CODE");
|
||||
}
|
||||
Log.e("ERROR", "Unknown error when parsing the result page !");
|
||||
return Collections.singletonList("ERROR UNKNOWN");
|
||||
}
|
||||
}
|
||||
else {
|
||||
Log.e("ERROR", "Unable to parse the result webpage as expected, something has changed !");
|
||||
return Collections.singletonList("ERROR PAGE");
|
||||
}
|
||||
}
|
||||
else {
|
||||
return infos;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
pDialog = ProgressDialog.show(context, null, "Connection..", true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(String s) {
|
||||
if(pDialog != null ){
|
||||
if(pDialog.isShowing()) {
|
||||
pDialog.dismiss();
|
||||
pDialog = null;
|
||||
}
|
||||
}
|
||||
|
||||
if(s != null) {
|
||||
if (s.equals("OK")) {
|
||||
main.setInfos(result);
|
||||
}
|
||||
if (s.equals("RETRY")) {
|
||||
Toast.makeText(context, "Erreur: Une mise à jour de sécurité empêche la récupération des informations" +
|
||||
", veuillez vérifier que l'application est à jour.", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
if (s.contains("ERROR")) {
|
||||
if (s.contains("DOSSIER")) {
|
||||
Toast.makeText(context, "Erreur: Votre numéro de dossier n'existe pas.", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
if (s.contains("CODE")) {
|
||||
Toast.makeText(context, "Erreur: Votre code personnel est incorrect.", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
if (s.contains("INIT")) {
|
||||
Toast.makeText(context, "Erreur: Un problème est survenu lors de la préparation de la connexion " +
|
||||
"sécurisée au serveur.", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
if (s.contains("GET")) {
|
||||
Toast.makeText(context, "Erreur: Impossible d'établir de connection, veuillez vérifier votre " +
|
||||
"connectivité Internet.", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
if (s.contains("CAPTCHA")) {
|
||||
Toast.makeText(context, "Erreur: Impossible de récupérer certains éléments, veuillez mettre à " +
|
||||
"jour l'application.", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
if (s.contains("POST")) {
|
||||
Toast.makeText(context, "Erreur: Un problème est survenu lors de l'envoi de la requête au " +
|
||||
"serveur, veuillez mettre à jour l'application.", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
if (s.contains("OCR")) {
|
||||
Toast.makeText(context, "Erreur: Un problème interne est survenu. Essayez de réinstaller " +
|
||||
"l'application.", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
if (s.contains("PAGE")) {
|
||||
Toast.makeText(context, "Erreur: Impossible de récupérer les données, veuillez mettre à jour " +
|
||||
"l'application.", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
if (s.contains("UNKNOWN")) {
|
||||
Toast.makeText(context, "Erreur: Une erreur inconnue est survenue, veuillez mettre à jour " +
|
||||
"l'application.", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
Log.e("ERROR", "Unable to get result (onPostExecute) from WebForm");
|
||||
Toast.makeText(context, "Erreur: Une erreur fatale est survenue durant la récupération du solde, veuillez " +
|
||||
"vérifier que l'application est à jour ou essayez de la réinstaller.", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
3
app/src/main/jniLibs/armeabi-v7a/gdb.setup
Normal file
@ -0,0 +1,3 @@
|
||||
set solib-search-path /home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/obj/local/armeabi-v7a
|
||||
source /opt/android/android-ndk-r10d/prebuilt/common/gdb/common.setup
|
||||
directory /opt/android/android-ndk-r10d/platforms/android-8/arch-arm/usr/include /opt/android/android-ndk-r10d/sources/cxx-stl/gnu-libstdc++ /home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/jni/com_googlecode_leptonica_android /home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/jni/com_googlecode_leptonica_android/src/src /opt/android/android-ndk-r10d/sources/cxx-stl/gnu-libstdc++/4.8/include /opt/android/android-ndk-r10d/sources/cxx-stl/gnu-libstdc++/4.8/libs/armeabi-v7a/include /opt/android/android-ndk-r10d/sources/cxx-stl/gnu-libstdc++/4.8/include/backward /home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/jni/com_googlecode_tesseract_android/src/api /home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/jni/com_googlecode_tesseract_android/src/ccmain /home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/jni/com_googlecode_tesseract_android/src/ccstruct /home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/jni/com_googlecode_tesseract_android/src/ccutil /home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/jni/com_googlecode_tesseract_android/src/classify /home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/jni/com_googlecode_tesseract_android/src/cube /home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/jni/com_googlecode_tesseract_android/src/cutil /home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/jni/com_googlecode_tesseract_android/src/dict /home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/jni/com_googlecode_tesseract_android/src/opencl /home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/jni/com_googlecode_tesseract_android/src/neural_networks/runtime /home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/jni/com_googlecode_tesseract_android/src/textord /home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/jni/com_googlecode_tesseract_android/src/viewer /home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/jni/com_googlecode_tesseract_android/src/wordrec
|
BIN
app/src/main/jniLibs/armeabi-v7a/gdbserver
Executable file
BIN
app/src/main/jniLibs/armeabi-v7a/liblept.so
Executable file
BIN
app/src/main/jniLibs/armeabi-v7a/libtess.so
Executable file
3
app/src/main/jniLibs/armeabi/gdb.setup
Normal file
@ -0,0 +1,3 @@
|
||||
set solib-search-path /home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/obj/local/armeabi
|
||||
source /opt/android/android-ndk-r10d/prebuilt/common/gdb/common.setup
|
||||
directory /opt/android/android-ndk-r10d/platforms/android-8/arch-arm/usr/include /opt/android/android-ndk-r10d/sources/cxx-stl/gnu-libstdc++ /home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/jni/com_googlecode_leptonica_android /home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/jni/com_googlecode_leptonica_android/src/src /opt/android/android-ndk-r10d/sources/cxx-stl/gnu-libstdc++/4.8/include /opt/android/android-ndk-r10d/sources/cxx-stl/gnu-libstdc++/4.8/libs/armeabi/include /opt/android/android-ndk-r10d/sources/cxx-stl/gnu-libstdc++/4.8/include/backward /home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/jni/com_googlecode_tesseract_android/src/api /home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/jni/com_googlecode_tesseract_android/src/ccmain /home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/jni/com_googlecode_tesseract_android/src/ccstruct /home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/jni/com_googlecode_tesseract_android/src/ccutil /home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/jni/com_googlecode_tesseract_android/src/classify /home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/jni/com_googlecode_tesseract_android/src/cube /home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/jni/com_googlecode_tesseract_android/src/cutil /home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/jni/com_googlecode_tesseract_android/src/dict /home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/jni/com_googlecode_tesseract_android/src/opencl /home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/jni/com_googlecode_tesseract_android/src/neural_networks/runtime /home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/jni/com_googlecode_tesseract_android/src/textord /home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/jni/com_googlecode_tesseract_android/src/viewer /home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/jni/com_googlecode_tesseract_android/src/wordrec
|
BIN
app/src/main/jniLibs/armeabi/gdbserver
Executable file
BIN
app/src/main/jniLibs/armeabi/liblept.so
Executable file
BIN
app/src/main/jniLibs/armeabi/libtess.so
Executable file
3
app/src/main/jniLibs/mips/gdb.setup
Normal file
@ -0,0 +1,3 @@
|
||||
set solib-search-path /home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/obj/local/mips
|
||||
source /opt/android/android-ndk-r10d/prebuilt/common/gdb/common.setup
|
||||
directory /opt/android/android-ndk-r10d/platforms/android-9/arch-mips/usr/include /opt/android/android-ndk-r10d/sources/cxx-stl/gnu-libstdc++ /home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/jni/com_googlecode_leptonica_android /home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/jni/com_googlecode_leptonica_android/src/src /opt/android/android-ndk-r10d/sources/cxx-stl/gnu-libstdc++/4.8/include /opt/android/android-ndk-r10d/sources/cxx-stl/gnu-libstdc++/4.8/libs/mips/include /opt/android/android-ndk-r10d/sources/cxx-stl/gnu-libstdc++/4.8/include/backward /home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/jni/com_googlecode_tesseract_android/src/api /home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/jni/com_googlecode_tesseract_android/src/ccmain /home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/jni/com_googlecode_tesseract_android/src/ccstruct /home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/jni/com_googlecode_tesseract_android/src/ccutil /home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/jni/com_googlecode_tesseract_android/src/classify /home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/jni/com_googlecode_tesseract_android/src/cube /home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/jni/com_googlecode_tesseract_android/src/cutil /home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/jni/com_googlecode_tesseract_android/src/dict /home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/jni/com_googlecode_tesseract_android/src/opencl /home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/jni/com_googlecode_tesseract_android/src/neural_networks/runtime /home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/jni/com_googlecode_tesseract_android/src/textord /home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/jni/com_googlecode_tesseract_android/src/viewer /home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/jni/com_googlecode_tesseract_android/src/wordrec
|
BIN
app/src/main/jniLibs/mips/gdbserver
Executable file
BIN
app/src/main/jniLibs/mips/liblept.so
Executable file
BIN
app/src/main/jniLibs/mips/libtess.so
Executable file
3
app/src/main/jniLibs/x86/gdb.setup
Normal file
@ -0,0 +1,3 @@
|
||||
set solib-search-path /home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/obj/local/x86
|
||||
source /opt/android/android-ndk-r10d/prebuilt/common/gdb/common.setup
|
||||
directory /opt/android/android-ndk-r10d/platforms/android-9/arch-x86/usr/include /opt/android/android-ndk-r10d/sources/cxx-stl/gnu-libstdc++ /home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/jni/com_googlecode_leptonica_android /home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/jni/com_googlecode_leptonica_android/src/src /opt/android/android-ndk-r10d/sources/cxx-stl/gnu-libstdc++/4.8/include /opt/android/android-ndk-r10d/sources/cxx-stl/gnu-libstdc++/4.8/libs/x86/include /opt/android/android-ndk-r10d/sources/cxx-stl/gnu-libstdc++/4.8/include/backward /home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/jni/com_googlecode_tesseract_android/src/api /home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/jni/com_googlecode_tesseract_android/src/ccmain /home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/jni/com_googlecode_tesseract_android/src/ccstruct /home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/jni/com_googlecode_tesseract_android/src/ccutil /home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/jni/com_googlecode_tesseract_android/src/classify /home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/jni/com_googlecode_tesseract_android/src/cube /home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/jni/com_googlecode_tesseract_android/src/cutil /home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/jni/com_googlecode_tesseract_android/src/dict /home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/jni/com_googlecode_tesseract_android/src/opencl /home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/jni/com_googlecode_tesseract_android/src/neural_networks/runtime /home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/jni/com_googlecode_tesseract_android/src/textord /home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/jni/com_googlecode_tesseract_android/src/viewer /home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/jni/com_googlecode_tesseract_android/src/wordrec
|
BIN
app/src/main/jniLibs/x86/gdbserver
Executable file
BIN
app/src/main/jniLibs/x86/liblept.so
Executable file
BIN
app/src/main/jniLibs/x86/libtess.so
Executable file
BIN
app/src/main/res/drawable-hdpi/drawer_shadow.9.png
Normal file
After Width: | Height: | Size: 114 B |
BIN
app/src/main/res/drawable-hdpi/ic_action_refresh.png
Normal file
After Width: | Height: | Size: 663 B |
BIN
app/src/main/res/drawable-hdpi/ic_drawer.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
app/src/main/res/drawable-hdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 9.2 KiB |
BIN
app/src/main/res/drawable-mdpi/drawer_shadow.9.png
Normal file
After Width: | Height: | Size: 142 B |
BIN
app/src/main/res/drawable-mdpi/ic_action_refresh.png
Normal file
After Width: | Height: | Size: 508 B |
BIN
app/src/main/res/drawable-mdpi/ic_drawer.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
app/src/main/res/drawable-mdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 5.1 KiB |
BIN
app/src/main/res/drawable-xhdpi/drawer_shadow.9.png
Normal file
After Width: | Height: | Size: 174 B |
BIN
app/src/main/res/drawable-xhdpi/ic_action_refresh.png
Normal file
After Width: | Height: | Size: 895 B |
BIN
app/src/main/res/drawable-xhdpi/ic_drawer.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
app/src/main/res/drawable-xhdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
app/src/main/res/drawable-xxhdpi/drawer_shadow.9.png
Normal file
After Width: | Height: | Size: 208 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_action_refresh.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
app/src/main/res/drawable-xxhdpi/ic_drawer.png
Normal file
After Width: | Height: | Size: 202 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 15 KiB |
25
app/src/main/res/layout/activity_main.xml
Normal file
@ -0,0 +1,25 @@
|
||||
<!-- A DrawerLayout is intended to be used as the top-level content view using match_parent for both width and height to consume the full space available. -->
|
||||
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools" android:id="@+id/drawer_layout"
|
||||
android:layout_width="match_parent" android:layout_height="match_parent"
|
||||
tools:context=".MainActivity">
|
||||
|
||||
<!-- As the main content view, the view below consumes the entire
|
||||
space available using match_parent in both dimensions. -->
|
||||
<FrameLayout android:id="@+id/container" android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<!-- android:layout_gravity="start" tells DrawerLayout to treat
|
||||
this as a sliding drawer on the left side for left-to-right
|
||||
languages and on the right side for right-to-left languages.
|
||||
If you're not building against API 17 or higher, use
|
||||
android:layout_gravity="left" instead. -->
|
||||
<!-- The drawer is given a fixed width in dp and extends the full height of
|
||||
the container. -->
|
||||
<fragment android:id="@+id/navigation_drawer"
|
||||
android:layout_width="@dimen/navigation_drawer_width" android:layout_height="match_parent"
|
||||
android:layout_gravity="start"
|
||||
android:name="fr.android.pointspermis.NavigationDrawerFragment"
|
||||
tools:layout="@layout/fragment_navigation_drawer" />
|
||||
|
||||
</android.support.v4.widget.DrawerLayout>
|
63
app/src/main/res/layout/dossier_dialog.xml
Normal file
@ -0,0 +1,63 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent" android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentTop="true"
|
||||
android:id="@+id/linearLayout">
|
||||
|
||||
<EditText
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/editTextDossier1"
|
||||
android:layout_weight="3.89"
|
||||
android:paddingLeft="10dp"
|
||||
android:editable="true"
|
||||
android:capitalize="characters"
|
||||
android:clickable="true"
|
||||
android:singleLine="true"
|
||||
android:enabled="true"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true"
|
||||
android:windowSoftInputMode="stateAlwaysVisible"
|
||||
android:autoText="true"
|
||||
android:lines="1" />
|
||||
|
||||
<EditText
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/editTextDossier2"
|
||||
android:layout_weight="1"
|
||||
android:editable="true"
|
||||
android:capitalize="characters"
|
||||
android:clickable="true"
|
||||
android:enabled="true"
|
||||
android:singleLine="true"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true"
|
||||
android:windowSoftInputMode="stateAlwaysVisible"
|
||||
android:autoText="true"
|
||||
android:lines="1" />
|
||||
|
||||
<EditText
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/editTextDossier3"
|
||||
android:layout_weight="1"
|
||||
android:paddingRight="10dp"
|
||||
android:editable="true"
|
||||
android:capitalize="characters"
|
||||
android:clickable="true"
|
||||
android:enabled="true"
|
||||
android:singleLine="true"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true"
|
||||
android:windowSoftInputMode="stateAlwaysVisible"
|
||||
android:autoText="true"
|
||||
android:lines="1" />
|
||||
</LinearLayout>
|
||||
|
||||
</RelativeLayout>
|
37
app/src/main/res/layout/fragment_main.xml
Normal file
@ -0,0 +1,37 @@
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
|
||||
android:paddingRight="@dimen/activity_horizontal_margin"
|
||||
android:paddingTop="@dimen/activity_vertical_margin"
|
||||
android:paddingBottom="@dimen/activity_vertical_margin"
|
||||
tools:context=".MainActivity$PlaceholderFragment"
|
||||
android:id="@+id/layout_fragment_main">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/textViewBirthday"
|
||||
android:layout_marginTop="110dp"
|
||||
android:layout_below="@+id/textViewUserName"
|
||||
android:layout_centerHorizontal="true" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||
android:id="@+id/textViewSolde"
|
||||
android:layout_below="@+id/textViewBirthday"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_marginTop="99dp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:id="@+id/textViewUserName"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_alignLeft="@+id/textViewSolde"
|
||||
android:layout_alignStart="@+id/textViewSolde"
|
||||
android:layout_marginTop="34dp" />
|
||||
|
||||
</RelativeLayout>
|
5
app/src/main/res/layout/fragment_navigation_drawer.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" android:choiceMode="singleChoice"
|
||||
android:divider="@android:color/transparent" android:dividerHeight="0dp"
|
||||
android:background="#cccc" tools:context=".NavigationDrawerFragment" />
|
4
app/src/main/res/menu/global.xml
Normal file
@ -0,0 +1,4 @@
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:id="@+id/action_settings" android:title="@string/action_settings"
|
||||
android:orderInCategory="100" android:showAsAction="never" />
|
||||
</menu>
|
15
app/src/main/res/menu/main.xml
Normal file
@ -0,0 +1,15 @@
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools" tools:context=".MainActivity">
|
||||
<item
|
||||
android:id="@+id/action_refresh"
|
||||
android:orderInCategory="100"
|
||||
android:icon="@drawable/ic_action_refresh"
|
||||
android:showAsAction="withText|ifRoom"
|
||||
android:title="@string/action_example"/>
|
||||
|
||||
<item android:id="@+id/action_settings" android:title="@string/action_settings"
|
||||
android:orderInCategory="100" android:showAsAction="never" />
|
||||
|
||||
<item android:id="@+id/action_quit" android:title="@string/action_quit"
|
||||
android:orderInCategory="100" android:showAsAction="never" />
|
||||
</menu>
|
6
app/src/main/res/values-w820dp/dimens.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<resources>
|
||||
<!-- Example customization of dimensions originally defined in res/values/dimens.xml
|
||||
(such as screen margins) for screens with more than 820dp of available width. This
|
||||
would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively). -->
|
||||
<dimen name="activity_horizontal_margin">64dp</dimen>
|
||||
</resources>
|
9
app/src/main/res/values/dimens.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<resources>
|
||||
<!-- Default screen margins, per the Android Design guidelines. -->
|
||||
<dimen name="activity_horizontal_margin">16dp</dimen>
|
||||
<dimen name="activity_vertical_margin">16dp</dimen>
|
||||
|
||||
<!-- Per the design guidelines, navigation drawers should be between 240dp and 320dp:
|
||||
https://developer.android.com/design/patterns/navigation-drawer.html -->
|
||||
<dimen name="navigation_drawer_width">240dp</dimen>
|
||||
</resources>
|
18
app/src/main/res/values/strings.xml
Normal file
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<string name="app_name">PointsPermis</string>
|
||||
<string name="title_home">Accueil</string>
|
||||
<string name="title_settings">Paramètres</string>
|
||||
<string name="title_section3">Section 3</string>
|
||||
<string name="navigation_drawer_open">Ouvrir le volet de navigation</string>
|
||||
<string name="navigation_drawer_close">Fermer le volet de navigation</string>
|
||||
<string name="action_example">Actualiser</string>
|
||||
<string name="action_settings">Paramètres</string>
|
||||
<string name="action_valid">Valider</string>
|
||||
<string name="action_quit">Quitter</string>
|
||||
<string name="action_cancel">Annuler</string>
|
||||
<string name="action_yes">Oui</string>
|
||||
<string name="action_no">Non</string>
|
||||
|
||||
</resources>
|
44
app/src/main/res/values/strings_activity_settings.xml
Normal file
@ -0,0 +1,44 @@
|
||||
<resources>
|
||||
|
||||
<!-- Strings related to Settings -->
|
||||
|
||||
|
||||
<string name="title_activity_settings">Paramètres</string>
|
||||
|
||||
<!-- Connection settings -->
|
||||
<string name="pref_header_connection">Connexion</string>
|
||||
<string name="pref_descr_connection">Configuration de la connexion</string>
|
||||
<string name="pref_title_dossier">Numéro de dossier</string>
|
||||
<string name="pref_key_dossier">dossier</string>
|
||||
<string name="pref_key_dossier1">dossier1</string>
|
||||
<string name="pref_key_dossier2">dossier2</string>
|
||||
<string name="pref_key_dossier3">dossier3</string>
|
||||
<string name="pref_title_code">Code confidentiel</string>
|
||||
<string name="pref_key_code">code</string>
|
||||
|
||||
<!-- Settings for Notification & Sync -->
|
||||
<string name="pref_header_notifications">Notifications</string>
|
||||
<string name="pref_descr_notifications">Configuration des notifications</string>
|
||||
<string name="pref_title_enable_notifications">Activer les notifications</string>
|
||||
<string name="pref_key_enable_notifications">notifications</string>
|
||||
<string name="pref_title_sync_frequency">Fréquence de synchronisation</string>
|
||||
<string name="pref_key_sync_frequency">sync_frequency</string>
|
||||
<string-array name="pref_sync_frequency_titles">
|
||||
<item>Mensuelle</item>
|
||||
<item>Bimensuelle</item>
|
||||
<item>Hebdomadaire</item>
|
||||
<item>Journalière</item>
|
||||
</string-array>
|
||||
<string-array name="pref_sync_frequency_values">
|
||||
<item>30</item>
|
||||
<item>15</item>
|
||||
<item>7</item>
|
||||
<item>1</item>
|
||||
</string-array>
|
||||
<string name="pref_title_ringtone">Sonnerie</string>
|
||||
<string name="pref_key_ringtone">notifications_ringtone</string>
|
||||
<string name="pref_ringtone_silent">Silencieuse</string>
|
||||
<string name="pref_title_vibrate">Vibrer</string>
|
||||
<string name="pref_key_vibrate">notifications_vibrate</string>
|
||||
|
||||
</resources>
|
8
app/src/main/res/values/styles.xml
Normal file
@ -0,0 +1,8 @@
|
||||
<resources>
|
||||
|
||||
<!-- Base application theme. -->
|
||||
<style name="AppTheme" parent="android:Theme.Holo.Light.DarkActionBar">
|
||||
<!-- Customize your theme here. -->
|
||||
</style>
|
||||
|
||||
</resources>
|
38
app/src/main/res/xml/pref_connection.xml
Normal file
@ -0,0 +1,38 @@
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<PreferenceCategory
|
||||
android:summary="@string/pref_header_connection"
|
||||
android:title="@string/pref_header_connection" >
|
||||
|
||||
<!-- NOTE: EditTextPreference accepts EditText attributes. -->
|
||||
<!-- NOTE: EditTextPreference's summary should be set to its value by the activity code. -->
|
||||
<fr.android.pointspermis.settings.DossierDialogPreference
|
||||
android:key="dossier"
|
||||
android:title="@string/pref_title_dossier"
|
||||
android:summary="Soit un champ, soit les trois !" />
|
||||
<!--
|
||||
<EditTextPreference
|
||||
android:key="dossier"
|
||||
android:title="@string/pref_title_dossier"
|
||||
android:defaultValue=""
|
||||
android:selectAllOnFocus="true"
|
||||
android:inputType="textCapWords"
|
||||
android:capitalize="words"
|
||||
android:singleLine="true"
|
||||
android:maxLines="1" />
|
||||
-->
|
||||
|
||||
<EditTextPreference
|
||||
android:key="code"
|
||||
android:title="@string/pref_title_code"
|
||||
android:defaultValue=""
|
||||
android:selectAllOnFocus="true"
|
||||
android:capitalize="words"
|
||||
android:singleLine="true"
|
||||
android:maxLines="1"
|
||||
android:inputType="textCapWords"
|
||||
android:password="true" />
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
</PreferenceScreen>
|
12
app/src/main/res/xml/pref_headers.xml
Normal file
@ -0,0 +1,12 @@
|
||||
<preference-headers xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<!-- These settings headers are only used on tablets. -->
|
||||
|
||||
<header android:fragment="fr.android.pointspermis.settings.SettingsActivity$ConnectionPreferenceFragment"
|
||||
android:title="@string/pref_header_connection" />
|
||||
|
||||
<header
|
||||
android:fragment="fr.android.pointspermis.settings.SettingsActivity$NotificationPreferenceFragment"
|
||||
android:title="@string/pref_header_notifications" />
|
||||
|
||||
</preference-headers>
|
46
app/src/main/res/xml/pref_notification.xml
Normal file
@ -0,0 +1,46 @@
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<PreferenceCategory
|
||||
android:summary="@string/pref_descr_notifications"
|
||||
android:title="@string/pref_header_notifications" >
|
||||
|
||||
<!-- A 'parent' preference, which enables/disables child preferences (below)
|
||||
when checked/unchecked. -->
|
||||
<CheckBoxPreference
|
||||
android:key="notifications"
|
||||
android:title="@string/pref_title_enable_notifications"
|
||||
android:defaultValue="false" />
|
||||
|
||||
<!-- NOTE: Hide buttons to simplify the UI. Users can touch outside the dialog to
|
||||
dismiss it. -->
|
||||
<!-- NOTE: ListPreference's summary should be set to its value by the activity code. -->
|
||||
<ListPreference
|
||||
android:dependency="notifications"
|
||||
android:key="sync_frequency"
|
||||
android:title="@string/pref_title_sync_frequency"
|
||||
android:entries="@array/pref_sync_frequency_titles"
|
||||
android:entryValues="@array/pref_sync_frequency_values"
|
||||
android:defaultValue="30"
|
||||
android:negativeButtonText="@null"
|
||||
android:positiveButtonText="@null" />
|
||||
|
||||
<!-- Allows the user to choose a ringtone in the 'notification' category. -->
|
||||
<!-- NOTE: This preference will be enabled only when the checkbox above is checked. -->
|
||||
<!-- NOTE: RingtonePreference's summary should be set to its value by the activity code. -->
|
||||
<RingtonePreference
|
||||
android:dependency="notifications"
|
||||
android:key="notifications_ringtone"
|
||||
android:title="@string/pref_title_ringtone"
|
||||
android:ringtoneType="notification"
|
||||
android:defaultValue="content://settings/system/notification_sound" />
|
||||
|
||||
<!-- NOTE: This preference will be enabled only when the checkbox above is checked. -->
|
||||
<CheckBoxPreference
|
||||
android:dependency="notifications"
|
||||
android:key="notifications_vibrate"
|
||||
android:title="@string/pref_title_vibrate"
|
||||
android:defaultValue="false" />
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
</PreferenceScreen>
|
19
build.gradle
Normal file
@ -0,0 +1,19 @@
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:1.0.0'
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
jcenter()
|
||||
}
|
||||
}
|
18
gradle.properties
Normal file
@ -0,0 +1,18 @@
|
||||
# Project-wide Gradle settings.
|
||||
|
||||
# IDE (e.g. Android Studio) users:
|
||||
# Gradle settings configured through the IDE *will override*
|
||||
# any settings specified in this file.
|
||||
|
||||
# For more details on how to configure your build environment visit
|
||||
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
||||
|
||||
# Specifies the JVM arguments used for the daemon process.
|
||||
# The setting is particularly useful for tweaking memory settings.
|
||||
# Default value: -Xmx10248m -XX:MaxPermSize=256m
|
||||
# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
|
||||
|
||||
# When configured, Gradle will run in incubating parallel mode.
|
||||
# This option should only be used with decoupled projects. More details, visit
|
||||
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
||||
# org.gradle.parallel=true
|
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
6
gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
#Wed Apr 10 15:27:10 PDT 2013
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip
|
164
gradlew
vendored
Executable file
@ -0,0 +1,164 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
##
|
||||
##############################################################################
|
||||
|
||||
# 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
|
||||
|
||||
# For Cygwin, ensure paths are in UNIX format before anything is touched.
|
||||
if $cygwin ; then
|
||||
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
|
||||
fi
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
# Need this for relative symlinks.
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG=`dirname "$PRG"`"/$link"
|
||||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >&-
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >&-
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD="java"
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
MAX_FD="$MAX_FD_LIMIT"
|
||||
fi
|
||||
ulimit -n $MAX_FD
|
||||
if [ $? -ne 0 ] ; then
|
||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||
fi
|
||||
else
|
||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Darwin, add options to specify how the application appears in the dock
|
||||
if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if $cygwin ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||
SEP=""
|
||||
for dir in $ROOTDIRSRAW ; do
|
||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||
SEP="|"
|
||||
done
|
||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||
# Add a user-defined pattern to the cygpath arguments
|
||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||
fi
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
i=0
|
||||
for arg in "$@" ; do
|
||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||
|
||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=$((i+1))
|
||||
done
|
||||
case $i in
|
||||
(0) set -- ;;
|
||||
(1) set -- "$args0" ;;
|
||||
(2) set -- "$args0" "$args1" ;;
|
||||
(3) set -- "$args0" "$args1" "$args2" ;;
|
||||
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
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=("$@")
|
||||
}
|
||||
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
|
||||
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
|
||||
|
||||
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
|
90
gradlew.bat
vendored
Normal file
@ -0,0 +1,90 @@
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@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 Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:init
|
||||
@rem Get command-line arguments, handling Windowz 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.
|
||||
set CMD_LINE_ARGS=
|
||||
set _SKIP=2
|
||||
|
||||
:win9xME_args_slurp
|
||||
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
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
37
import-summary.txt
Normal file
@ -0,0 +1,37 @@
|
||||
ECLIPSE ANDROID PROJECT IMPORT SUMMARY
|
||||
======================================
|
||||
|
||||
Ignored Files:
|
||||
--------------
|
||||
The following files were *not* copied into the new Gradle project; you
|
||||
should evaluate whether these are still needed in your project and if
|
||||
so manually move them:
|
||||
|
||||
* .gitignore
|
||||
* COPYING
|
||||
* build.xml
|
||||
|
||||
Moved Files:
|
||||
------------
|
||||
Android Gradle projects use a different directory structure than ADT
|
||||
Eclipse projects. Here's how the projects were restructured:
|
||||
|
||||
* AndroidManifest.xml => tesstwo/src/main/AndroidManifest.xml
|
||||
* jni/ => tesstwo/src/main/jni/
|
||||
* res/ => tesstwo/src/main/res/
|
||||
* src/ => tesstwo/src/main/java/
|
||||
|
||||
Next Steps:
|
||||
-----------
|
||||
You can now build the project. The Gradle project needs network
|
||||
connectivity to download dependencies.
|
||||
|
||||
Bugs:
|
||||
-----
|
||||
If for some reason your project does not build, and you determine that
|
||||
it is due to a bug or limitation of the Eclipse to Gradle importer,
|
||||
please file a bug at http://b.android.com with category
|
||||
Component-Tools.
|
||||
|
||||
(This import summary is for your information only, and can be deleted
|
||||
after import once you are satisfied with the results.)
|
1
settings.gradle
Normal file
@ -0,0 +1 @@
|
||||
include ':app', ':tesseract'
|
44
tesseract/build.gradle
Normal file
@ -0,0 +1,44 @@
|
||||
apply plugin: 'com.android.library'
|
||||
android {
|
||||
compileSdkVersion 19
|
||||
buildToolsVersion '21.1.2'
|
||||
defaultConfig {
|
||||
minSdkVersion 14
|
||||
targetSdkVersion 19
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
|
||||
}
|
||||
}
|
||||
//// This prevents the auto generation of Android.mk
|
||||
sourceSets.main.jni.srcDirs = []
|
||||
task buildNative(type: Exec, description: 'Compile JNI source via NDK') {
|
||||
def ndkDir = android.plugin.ndkFolder
|
||||
commandLine "$ndkDir/ndk-build",
|
||||
'-C', file('src/main/jni').absolutePath,
|
||||
'-j', Runtime.runtime.availableProcessors(),
|
||||
'all',
|
||||
'NDK_DEBUG=1'
|
||||
}
|
||||
task cleanNative(type: Exec, description: 'Clean JNI object files') {
|
||||
def ndkDir = android.plugin.ndkFolder
|
||||
commandLine "$ndkDir/ndk-build",
|
||||
'-C', file('src/main/jni').absolutePath,
|
||||
'clean'
|
||||
}
|
||||
clean.dependsOn 'cleanNative'
|
||||
tasks.withType(JavaCompile) {
|
||||
compileTask -> compileTask.dependsOn buildNative
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_7
|
||||
targetCompatibility JavaVersion.VERSION_1_7
|
||||
}
|
||||
productFlavors {
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
/**
|
||||
* Automatically generated file. DO NOT MODIFY
|
||||
*/
|
||||
package com.googlecode.tesseract.android;
|
||||
|
||||
public final class BuildConfig {
|
||||
public static final boolean DEBUG = Boolean.parseBoolean("true");
|
||||
public static final String APPLICATION_ID = "com.googlecode.tesseract.android";
|
||||
public static final String BUILD_TYPE = "debug";
|
||||
public static final String FLAVOR = "";
|
||||
public static final int VERSION_CODE = 1;
|
||||
public static final String VERSION_NAME = "";
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
/**
|
||||
* Automatically generated file. DO NOT MODIFY
|
||||
*/
|
||||
package com.googlecode.tesseract.android;
|
||||
|
||||
public final class BuildConfig {
|
||||
public static final boolean DEBUG = false;
|
||||
public static final String APPLICATION_ID = "com.googlecode.tesseract.android";
|
||||
public static final String BUILD_TYPE = "release";
|
||||
public static final String FLAVOR = "";
|
||||
public static final int VERSION_CODE = 1;
|
||||
public static final String VERSION_NAME = "";
|
||||
}
|