Android analytics done, camera instructions added.

This commit is contained in:
Ivan Murashov
2018-04-22 18:43:29 +03:00
parent be4f2dc7cf
commit bc02327b3e
42 changed files with 1015 additions and 1386 deletions

View File

@@ -12,6 +12,7 @@ if (flutterRoot == null) {
} }
apply plugin: 'com.android.application' apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android { android {
@@ -24,7 +25,7 @@ android {
defaultConfig { defaultConfig {
targetSdkVersion 27 targetSdkVersion 27
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" minSdkVersion 16
applicationId "com.dinect.checker" applicationId "com.dinect.checker"
} }
@@ -35,13 +36,13 @@ android {
} }
release { release {
signingConfig signingConfigs.debug signingConfig signingConfigs.debug
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
} }
} }
flavorDimensions "checker" flavorDimensions "checker"
// Не смог разобраться, как коомбинировать flavors в flutter при запуске
productFlavors { productFlavors {
dinect { dinect {
@@ -174,16 +175,9 @@ android {
buildConfigField "boolean", "showBonus", "true" buildConfigField "boolean", "showBonus", "true"
} }
} }
compileOptions {
sourceSets { targetCompatibility 1.8
sourceCompatibility 1.8
main.jniLibs.srcDir 'jniLibs'
pip {
res.srcDirs = ['src/pip/res']
manifest.srcFile 'src/pip/AndroidManifest.xml'
}
} }
} }
@@ -192,9 +186,22 @@ flutter {
} }
dependencies { dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs') implementation fileTree(include: ['*.jar'], dir: 'libs')
compile 'com.android.support:appcompat-v7:27.1.0' implementation 'com.android.support:appcompat-v7:27.1.1'
compile 'com.squareup.okhttp3:okhttp:3.8.1' implementation 'com.android.support:recyclerview-v7:27.1.1'
compile 'com.squareup.okio:okio:1.13.0' implementation 'com.google.firebase:firebase-core:15.0.0'
compile 'me.dm7.barcodescanner:zxing:1.9.8' implementation 'com.google.firebase:firebase-crash:15.0.0'
implementation 'com.android.support:support-v4:27.1.1'
implementation 'com.android.support:support-media-compat:27.1.1'
implementation 'com.squareup.okhttp3:okhttp:3.9.0'
implementation 'com.squareup.okio:okio:1.13.0'
implementation 'me.dm7.barcodescanner:zxing:1.9.8'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
}
apply plugin: 'com.google.gms.google-services'
repositories {
mavenCentral()
} }

View File

@@ -0,0 +1,363 @@
{
"project_info": {
"project_number": "930872418262",
"firebase_url": "https://choker-d8897.firebaseio.com",
"project_id": "choker-d8897",
"storage_bucket": "choker-d8897.appspot.com"
},
"client": [
{
"client_info": {
"mobilesdk_app_id": "1:930872418262:android:5a64db21df36f8f2",
"android_client_info": {
"package_name": "com.dinect.checker.autoclub"
}
},
"oauth_client": [
{
"client_id": "930872418262-26ligstlb75a1s453r8t79l2jc0hk0ak.apps.googleusercontent.com",
"client_type": 1,
"android_info": {
"package_name": "com.dinect.checker.autoclub",
"certificate_hash": "26e013fe8b305ca736d5513db6281fb3b43a3e30"
}
},
{
"client_id": "930872418262-uv19fji9j1p16hjstr06jt5ec7joq4kp.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyCh7I1Za0MfKMN2EnsYYEO_hSW4RTkqfFk"
}
],
"services": {
"analytics_service": {
"status": 1
},
"appinvite_service": {
"status": 2,
"other_platform_oauth_client": [
{
"client_id": "930872418262-uv19fji9j1p16hjstr06jt5ec7joq4kp.apps.googleusercontent.com",
"client_type": 3
}
]
},
"ads_service": {
"status": 2
}
}
},
{
"client_info": {
"mobilesdk_app_id": "1:930872418262:android:7889aafb1e16814e",
"android_client_info": {
"package_name": "com.dinect.checker.int"
}
},
"oauth_client": [
{
"client_id": "930872418262-as5veeoulblnv8pc53u60s4isd0m4qll.apps.googleusercontent.com",
"client_type": 1,
"android_info": {
"package_name": "com.dinect.checker.int",
"certificate_hash": "26e013fe8b305ca736d5513db6281fb3b43a3e30"
}
},
{
"client_id": "930872418262-uv19fji9j1p16hjstr06jt5ec7joq4kp.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyCh7I1Za0MfKMN2EnsYYEO_hSW4RTkqfFk"
}
],
"services": {
"analytics_service": {
"status": 1
},
"appinvite_service": {
"status": 2,
"other_platform_oauth_client": [
{
"client_id": "930872418262-uv19fji9j1p16hjstr06jt5ec7joq4kp.apps.googleusercontent.com",
"client_type": 3
}
]
},
"ads_service": {
"status": 2
}
}
},
{
"client_info": {
"mobilesdk_app_id": "1:930872418262:android:5525e12f52441ac8",
"android_client_info": {
"package_name": "com.dinect.checker.ote"
}
},
"oauth_client": [
{
"client_id": "930872418262-n3rv7njq92gddlji1cp1bljcntao2r2k.apps.googleusercontent.com",
"client_type": 1,
"android_info": {
"package_name": "com.dinect.checker.ote",
"certificate_hash": "26e013fe8b305ca736d5513db6281fb3b43a3e30"
}
},
{
"client_id": "930872418262-uv19fji9j1p16hjstr06jt5ec7joq4kp.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyCh7I1Za0MfKMN2EnsYYEO_hSW4RTkqfFk"
}
],
"services": {
"analytics_service": {
"status": 1
},
"appinvite_service": {
"status": 2,
"other_platform_oauth_client": [
{
"client_id": "930872418262-uv19fji9j1p16hjstr06jt5ec7joq4kp.apps.googleusercontent.com",
"client_type": 3
}
]
},
"ads_service": {
"status": 2
}
}
},
{
"client_info": {
"mobilesdk_app_id": "1:930872418262:android:39049aaa560f7f4b",
"android_client_info": {
"package_name": "com.dinect.checker.pip"
}
},
"oauth_client": [
{
"client_id": "930872418262-id10iejb9f87vs1qt8lbtiq6oue2v1co.apps.googleusercontent.com",
"client_type": 1,
"android_info": {
"package_name": "com.dinect.checker.pip",
"certificate_hash": "26e013fe8b305ca736d5513db6281fb3b43a3e30"
}
},
{
"client_id": "930872418262-uv19fji9j1p16hjstr06jt5ec7joq4kp.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyCh7I1Za0MfKMN2EnsYYEO_hSW4RTkqfFk"
}
],
"services": {
"analytics_service": {
"status": 1
},
"appinvite_service": {
"status": 2,
"other_platform_oauth_client": [
{
"client_id": "930872418262-uv19fji9j1p16hjstr06jt5ec7joq4kp.apps.googleusercontent.com",
"client_type": 3
}
]
},
"ads_service": {
"status": 2
}
}
},
{
"client_info": {
"mobilesdk_app_id": "1:930872418262:android:5b51a93686bedd68",
"android_client_info": {
"package_name": "com.dinect.checker.staging"
}
},
"oauth_client": [
{
"client_id": "930872418262-3kldujcmf26hmhssefj8qqvt7hbfv4ro.apps.googleusercontent.com",
"client_type": 1,
"android_info": {
"package_name": "com.dinect.checker.staging",
"certificate_hash": "26e013fe8b305ca736d5513db6281fb3b43a3e30"
}
},
{
"client_id": "930872418262-uv19fji9j1p16hjstr06jt5ec7joq4kp.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyCh7I1Za0MfKMN2EnsYYEO_hSW4RTkqfFk"
}
],
"services": {
"analytics_service": {
"status": 1
},
"appinvite_service": {
"status": 2,
"other_platform_oauth_client": [
{
"client_id": "930872418262-uv19fji9j1p16hjstr06jt5ec7joq4kp.apps.googleusercontent.com",
"client_type": 3
}
]
},
"ads_service": {
"status": 2
}
}
},
{
"client_info": {
"mobilesdk_app_id": "1:930872418262:android:17854c6d56c76a29",
"android_client_info": {
"package_name": "com.dinect.checker.testing"
}
},
"oauth_client": [
{
"client_id": "930872418262-0rtlks627b91ve32alkgpoondelhmciv.apps.googleusercontent.com",
"client_type": 1,
"android_info": {
"package_name": "com.dinect.checker.testing",
"certificate_hash": "26e013fe8b305ca736d5513db6281fb3b43a3e30"
}
},
{
"client_id": "930872418262-uv19fji9j1p16hjstr06jt5ec7joq4kp.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyCh7I1Za0MfKMN2EnsYYEO_hSW4RTkqfFk"
}
],
"services": {
"analytics_service": {
"status": 1
},
"appinvite_service": {
"status": 2,
"other_platform_oauth_client": [
{
"client_id": "930872418262-uv19fji9j1p16hjstr06jt5ec7joq4kp.apps.googleusercontent.com",
"client_type": 3
}
]
},
"ads_service": {
"status": 2
}
}
},
{
"client_info": {
"mobilesdk_app_id": "1:930872418262:android:ac7262e14afe8c26",
"android_client_info": {
"package_name": "com.joys.checker.crypto"
}
},
"oauth_client": [
{
"client_id": "930872418262-rh2es35igpv1d0i2caj21oac56ieqhnb.apps.googleusercontent.com",
"client_type": 1,
"android_info": {
"package_name": "com.joys.checker.crypto",
"certificate_hash": "26e013fe8b305ca736d5513db6281fb3b43a3e30"
}
},
{
"client_id": "930872418262-uv19fji9j1p16hjstr06jt5ec7joq4kp.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyCh7I1Za0MfKMN2EnsYYEO_hSW4RTkqfFk"
}
],
"services": {
"analytics_service": {
"status": 1
},
"appinvite_service": {
"status": 2,
"other_platform_oauth_client": [
{
"client_id": "930872418262-uv19fji9j1p16hjstr06jt5ec7joq4kp.apps.googleusercontent.com",
"client_type": 3
}
]
},
"ads_service": {
"status": 2
}
}
},
{
"client_info": {
"mobilesdk_app_id": "1:930872418262:android:1989d1b101c854c1",
"android_client_info": {
"package_name": "ru.fivefit.biochecker"
}
},
"oauth_client": [
{
"client_id": "930872418262-5qmhf3e05a16ndhkj7jsv6qb7t6ut081.apps.googleusercontent.com",
"client_type": 1,
"android_info": {
"package_name": "ru.fivefit.biochecker",
"certificate_hash": "26e013fe8b305ca736d5513db6281fb3b43a3e30"
}
},
{
"client_id": "930872418262-uv19fji9j1p16hjstr06jt5ec7joq4kp.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyCh7I1Za0MfKMN2EnsYYEO_hSW4RTkqfFk"
}
],
"services": {
"analytics_service": {
"status": 1
},
"appinvite_service": {
"status": 2,
"other_platform_oauth_client": [
{
"client_id": "930872418262-uv19fji9j1p16hjstr06jt5ec7joq4kp.apps.googleusercontent.com",
"client_type": 3
}
]
},
"ads_service": {
"status": 2
}
}
}
],
"configuration_version": "1"
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

View File

@@ -4,10 +4,6 @@
android:versionCode="13" android:versionCode="13"
android:versionName="1.1.18"> android:versionName="1.1.18">
<uses-sdk
android:minSdkVersion="16"
android:targetSdkVersion="21"/>
<!-- The INTERNET permission is required for development. Specifically, <!-- The INTERNET permission is required for development. Specifically,
flutter needs it to communicate with the running application flutter needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc. to allow setting breakpoints, to provide hot reload, etc.
@@ -31,7 +27,7 @@
android:hardwareAccelerated="true" android:hardwareAccelerated="true"
android:launchMode="singleTop" android:launchMode="singleTop"
android:screenOrientation="portrait" android:screenOrientation="portrait"
android:theme="@android:style/Theme.Light.NoTitleBar" android:theme="@style/Theme.AppCompat.Light.NoActionBar"
android:windowSoftInputMode="adjustResize"> android:windowSoftInputMode="adjustResize">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN"/> <action android:name="android.intent.action.MAIN"/>
@@ -39,14 +35,10 @@
</intent-filter> </intent-filter>
</activity> </activity>
<activity
android:name=".zbar.CameraActivity"
android:screenOrientation="portrait"
android:theme="@style/AppTheme"/>
<activity <activity
android:name=".zxing.ScannerActivity" android:name=".ScannerActivity"
android:screenOrientation="portrait" android:screenOrientation="portrait"
android:theme="@style/AppTheme"/> android:theme="@style/Theme.AppCompat.Light.NoActionBar"/>
</application> </application>
</manifest> </manifest>

View File

@@ -1,331 +0,0 @@
/*
* Copyright 2017 .
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.dinect.checker;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.util.Pair;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.Window;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.TextView;
import android.widget.Toast;
import org.json.JSONArray;
import org.json.JSONException;
import java.io.IOException;
import java.util.Locale;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Response;
import okhttp3.ResponseBody;
import com.dinect.checker.net.ApiClient;
import com.dinect.checker.StatedImageButton;
import com.dinect.checker.SearchType;
import com.dinect.checker.StatedImageButton.StatedImageButtonInteractorListener;
/**
* Created by anonymous
*/
public abstract class AbstractScannerActivity extends AppCompatActivity implements StatedImageButtonInteractorListener{
private final static String TAG = "Checker.ScannerActivity";
private int counter;
public static final String SCAN_MODES = "SCAN_MODES";
public static final String ERROR_INFO = "ERROR_INFO";
private ApiClient mClient;
private StatedImageButton statedImageButton;
boolean isCameraAvailable() {
Log.d(TAG, "isCameraAvailable");
PackageManager pm = getPackageManager();
return pm.hasSystemFeature(PackageManager.FEATURE_CAMERA);
}
void cancelRequest(final @NonNull String message) {
Log.d(TAG, "cancelRequest: " + message);
final Intent response = new Intent();
response.putExtra(ERROR_INFO, message);
setResult(RESULT_CANCELED, response);
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final String appToken = getIntent().getStringExtra(MainActivity.PREF_APP_TOKEN);
final String token = getIntent().getStringExtra(MainActivity.PREF_POS_TOKEN);
final String url = getIntent().getStringExtra(MainActivity.PREF_API_URL) + "/users/";
mClient = new ApiClient(url, appToken, token);
}
/**
* initialize activity
* - removes windows title
* - set content view to layout id
*
* @param layoutID layout to use
*/
protected final boolean init(final int layoutID) {
Log.d(TAG, "init");
if (!isCameraAvailable()) {
// Cancel request if there is no rear-facing camera.
cancelRequest("Camera unavailable");
return false;
}
// Hide the window title.
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(layoutID);
return true;
}
/**
* Configure toolbar of app
*/
protected final void initToolbar(Intent intent) {
final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
toolbar.setBackgroundColor((int) intent.getLongExtra(MainActivity.PREF_APP_BAR_COLOR, 0xffffff));
setSupportActionBar(toolbar);
//
final ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setTitle(null);
actionBar.setDisplayHomeAsUpEnabled(false);
}
initManualInput();
initSwitchButton();
setupSecretClickHandler(toolbar);
}
private void initSwitchButton() {
statedImageButton = (StatedImageButton) findViewById(R.id.cardPhoneButton);
statedImageButton.setButtonState(SearchType.CARD);
statedImageButton.setStatedImageButtonInteractorListener(this);
}
@Override
public void onStateChanged(SearchType searchType) {
Log.d(TAG, searchType.toString());
EditText manualInput = (EditText) findViewById(R.id.manual_input);
switch (searchType) {
case CARD:
manualInput.setHint(getIntent().getStringExtra("enter_manual"));
break;
case PHONE_NUMBER:
manualInput.setHint(getIntent().getStringExtra("enter_phone"));
break;
}
}
private void initManualInput() {
EditText manualInput = (EditText) findViewById(R.id.manual_input);
// для удобства, чтоб не вводить постоянно руками при разработке
// manualInput.setText("9990010009012057060904229");
// manualInput.setText("4620011139016337050236302");
manualInput.setHint(getIntent().getStringExtra("enter_manual"));
manualInput.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
handleBarcode(v.getText().toString());
return false;
}
});
}
private void setupSecretClickHandler(final @NonNull View toolbar) {
// Configure increment handler
toolbar.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (counter == 15) {
switchScanner();
} else {
counter++;
}
Log.d(TAG, "toolbar clicked " + counter + " times");
}
});
}
private void switchScanner() {
final SharedPreferences prefs = getSharedPreferences("scanner", Context.MODE_PRIVATE);
int idx = (prefs.getInt(MainActivity.SCANNER_BACKEND_KEY, 0) == MainActivity.ZXING)
? MainActivity.ZBAR
: MainActivity.ZXING;
Log.d(TAG, "switch to scanner backend " + idx + ", " + MainActivity.SCANNER_BACKEND[idx].toString());
prefs.edit().putInt(MainActivity.SCANNER_BACKEND_KEY, idx).apply();
cancelRequest("Scanner backend changed");
setResult(RESULT_OK);
finish();
}
/**
* Adds scanner view to target frame layout
*/
protected final void addScanner(final @NonNull View view, final int targetFrameId) {
Log.d(TAG, "addScanner");
final FrameLayout root = (FrameLayout) findViewById(targetFrameId);
root.addView(view, 0);
}
protected abstract View initScanner();
public void handleBarcode(final @NonNull String searchString) {
mClient.findUser(searchString, statedImageButton.getCurrentState(), new Callback() {
@Override
public void onFailure(Call call, IOException e) {
handleFail(searchString);
}
@Override
public void onResponse(Call call, Response response) throws IOException {
try {
ResponseBody body = response.body();
if (body != null) {
switch (response.code()) {
case 200:
final JSONArray users = new JSONArray(body.string());
if (users.length() > 0) {
handleSuccess(searchString, users.get(0).toString());
} else {
handleFail(searchString);
}
break;
case 204:
handleFail(searchString);
break;
}
}
} catch (final IOException | JSONException e) {
Log.e(TAG, e.getMessage(), e);
handleFail(searchString);
}
}
});
}
protected final void handleSuccess(final String card, final String user) {
runOnUiThread(new Runnable() {
@Override
public void run() {
setResult(RESULT_OK, new Intent().putExtra("user", user).putExtra("card", card));
finish();
}
});
}
protected final void handleFail(final String searchString) {
runOnUiThread(new Runnable() {
@Override
public void run() {
String message = String.format(getIntent().getStringExtra("identifier_not_found"), searchString)
+ ".\n"
+ String.format(getIntent().getStringExtra("error_contact_support"), BuildConfig.supportPhone);
Toast.makeText(AbstractScannerActivity.this, message, Toast.LENGTH_SHORT).show();
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu, menu);
return true;
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
MenuItem settings = menu.findItem(R.id.settings);
settings.setIcon(getResources().getDrawable(R.drawable.settings));
settings.setTitle(getIntent().getStringExtra("settings"));
MenuItem faq = menu.findItem(R.id.faq);
faq.setIcon(getResources().getDrawable(R.drawable.help));
faq.setTitle(getIntent().getStringExtra("faq"));
MenuItem exit = menu.findItem(R.id.exit);
exit.setIcon(getResources().getDrawable(R.drawable.exit));
exit.setTitle(getIntent().getStringExtra("exit"));
return super.onPrepareOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.settings) {
final Intent intent = new Intent();
intent.putExtra("item", "settings");
setResult(RESULT_OK, intent);
finish();
return true;
} else if (item.getItemId() == R.id.exit) {
exit();
return true;
} else if (item.getItemId() == R.id.faq) {
final Intent intent = new Intent();
intent.putExtra("item", "faq");
setResult(RESULT_OK, intent);
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
void exit() {
final Intent intent = new Intent();
intent.putExtra("item", "exit");
setResult(RESULT_OK, intent);
finish();
}
}

View File

@@ -1,63 +1,55 @@
package com.dinect.checker; package com.dinect.checker;
import android.Manifest;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.content.res.Resources; import android.content.res.Resources;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle; import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.widget.Toast; import android.widget.Toast;
import android.util.Log;
import com.dinect.checker.zbar.CameraActivity; import com.google.firebase.analytics.FirebaseAnalytics;
import com.dinect.checker.zxing.ScannerActivity; import com.google.firebase.crash.FirebaseCrash;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Locale;
import java.util.Map;
import io.flutter.app.FlutterActivity; import io.flutter.app.FlutterActivity;
import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.Result; import io.flutter.plugin.common.MethodChannel.Result;
import io.flutter.plugins.GeneratedPluginRegistrant; import io.flutter.plugins.GeneratedPluginRegistrant;
import android.support.v4.app.Fragment;
import android.Manifest;
import android.content.pm.PackageManager;
import android.support.v4.content.ContextCompat;
import android.support.v4.app.ActivityCompat;
import android.content.pm.PackageInfo;
import java.util.*;
public class MainActivity extends FlutterActivity { public class MainActivity extends FlutterActivity {
private static final int START_SCANNER_REQUEST_CODE = 2017; private static final int START_SCANNER_REQUEST_CODE = 2017;
private static final String FLUTTER_CHANNEL_NAME = "com.dinect.checker/instance_id"; private static final String FLUTTER_CHANNEL_NAME = "com.dinect.checker/instance_id";
private static final String ERROR_MESSAGE = "message";
static final String PREF_API_URL = "url"; static final String PREF_API_URL = "url";
static final String PREF_APP_TOKEN = "appToken"; static final String PREF_APP_TOKEN = "appToken";
static final String PREF_POS_TOKEN = "token"; static final String PREF_POS_TOKEN = "token";
static final String PREF_APP_BAR_COLOR = "color"; static final String PREF_APP_BAR_COLOR = "color";
static final String SCANNER_BACKEND_KEY = "scanner_backend_idx";
static final int ZXING = 0;
static final int ZBAR = 1;
static final Class[] SCANNER_BACKEND = {
ScannerActivity.class,
CameraActivity.class,
};
private MethodChannel mChannel; private MethodChannel mChannel;
private Map mScannerArgs; private Map mScannerArgs;
private FirebaseAnalytics mAnalytics;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
GeneratedPluginRegistrant.registerWith(this); GeneratedPluginRegistrant.registerWith(this);
mAnalytics = FirebaseAnalytics.getInstance(this);
mChannel = new MethodChannel(getFlutterView(), FLUTTER_CHANNEL_NAME); mChannel = new MethodChannel(getFlutterView(), FLUTTER_CHANNEL_NAME);
mChannel.setMethodCallHandler( mChannel.setMethodCallHandler(this::callMethod);
new MethodChannel.MethodCallHandler() {
@Override
public void onMethodCall(MethodCall call, Result result) {
callMethod(call, result);
}
});
} }
private void callMethod(MethodCall call, Result result) { private void callMethod(MethodCall call, Result result) {
@@ -72,8 +64,7 @@ public class MainActivity extends FlutterActivity {
result.success(BuildConfig.currency); result.success(BuildConfig.currency);
break; break;
case "startScanner": case "startScanner":
mScannerArgs = call.arguments(); startScannerActivity(call);
startScannerActivity();
break; break;
case "isOnline": case "isOnline":
checkInternetConnection(result); checkInternetConnection(result);
@@ -97,18 +88,24 @@ public class MainActivity extends FlutterActivity {
result.success(BuildConfig.showBonus); result.success(BuildConfig.showBonus);
break; break;
case "finish": case "finish":
Log.d("kifio", call.method);
finish(); finish();
break; break;
case "getVersionName": case "getVersionName":
result.success(getVersion()); result.success(getVersion());
break; break;
case "logError":
handleError(call.arguments());
default: default:
result.notImplemented(); result.notImplemented();
break; break;
} }
} }
private void handleError(Map args) {
String message = args.get(ERROR_MESSAGE).toString();
FirebaseCrash.report(new Exception("handleError, " + message));
}
private String getVersion() { private String getVersion() {
try { try {
PackageInfo pInfo = this.getPackageManager().getPackageInfo(getPackageName(), 0); PackageInfo pInfo = this.getPackageManager().getPackageInfo(getPackageName(), 0);
@@ -120,8 +117,7 @@ public class MainActivity extends FlutterActivity {
} }
private String getLanguage() { private String getLanguage() {
List<String> availableLanguages = Arrays.asList("ru", "en"); if (Arrays.asList("ru", "en").contains(Locale.getDefault().getLanguage())) {
if (availableLanguages.contains(Locale.getDefault().getLanguage())) {
return Locale.getDefault().getLanguage(); return Locale.getDefault().getLanguage();
} else { } else {
return BuildConfig.locale; return BuildConfig.locale;
@@ -129,9 +125,10 @@ public class MainActivity extends FlutterActivity {
} }
private void checkInternetConnection(Result result) { private void checkInternetConnection(Result result) {
boolean connected = Utils.isOnline(this); boolean connected = isOnline(this);
if (!connected) if (!connected) {
Toast.makeText(this, "Проверьте интернет соединение", Toast.LENGTH_SHORT).show(); Toast.makeText(this, "Проверьте интернет соединение", Toast.LENGTH_SHORT).show();
}
result.success(connected); result.success(connected);
} }
@@ -144,17 +141,27 @@ public class MainActivity extends FlutterActivity {
res.updateConfiguration(configuration, res.getDisplayMetrics()); res.updateConfiguration(configuration, res.getDisplayMetrics());
} }
private void startScannerActivity(MethodCall call) {
mScannerArgs = call.arguments();
startScannerActivity();
}
private void startScannerActivity() { private void startScannerActivity() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, 101); ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, 101);
} else { } else {
final int idx = getSharedPreferences("scanner", Context.MODE_PRIVATE).getInt( openScanner();
SCANNER_BACKEND_KEY, 0); }
Intent cameraIntent = new Intent(MainActivity.this, SCANNER_BACKEND[idx]); }
private void openScanner() {
Intent cameraIntent = new Intent(MainActivity.this, ScannerActivity.class);
for (Object key : mScannerArgs.keySet()) { for (Object key : mScannerArgs.keySet()) {
if (key.equals("color")) { if (key.equals("color")) {
cameraIntent.putExtra((String) key, Long.parseLong((String) mScannerArgs.get(key))); cameraIntent.putExtra((String) key,
Long.parseLong((String) mScannerArgs.get(key)));
} else { } else {
cameraIntent.putExtra((String) key, (String) mScannerArgs.get(key)); cameraIntent.putExtra((String) key, (String) mScannerArgs.get(key));
} }
@@ -163,17 +170,11 @@ public class MainActivity extends FlutterActivity {
setLocale((String) mScannerArgs.get("localeCode")); setLocale((String) mScannerArgs.get("localeCode"));
startActivityForResult(cameraIntent, START_SCANNER_REQUEST_CODE); startActivityForResult(cameraIntent, START_SCANNER_REQUEST_CODE);
} }
}
@Override @Override
public void onRequestPermissionsResult(int requestCode, public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) { String permissions[], int[] grantResults) {
if (requestCode == 101) { openScanner();
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
startScannerActivity();
}
}
} }
@Override @Override
@@ -182,7 +183,7 @@ public class MainActivity extends FlutterActivity {
if (resultCode == RESULT_CANCELED) { if (resultCode == RESULT_CANCELED) {
finish(); finish();
} else if (resultCode == RESULT_OK) { } else if (resultCode == RESULT_OK) {
if (data != null) { if (data != null && data.getExtras() != null) {
String user = data.getExtras().getString("user", null); String user = data.getExtras().getString("user", null);
if (user != null) { if (user != null) {
String card = data.getExtras().getString("card", null); String card = data.getExtras().getString("card", null);
@@ -207,51 +208,12 @@ public class MainActivity extends FlutterActivity {
} }
} }
public void getFlavor() { private static boolean isOnline(Context context) {
NetworkInfo netInfo = getConnectivityManager(context).getActiveNetworkInfo();
return netInfo != null && netInfo.isConnected();
} }
public void getCurrency() { private static ConnectivityManager getConnectivityManager(Context context) {
return (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
}
public void getLocale() {
}
public void setUserLocale() {
}
public void startScanner() {
}
public void isOnline() {
}
public void getSupportPhone() {
}
public void getSupportUrl() {
}
public void getEndpoint() {
}
public void getAppToken() {
}
public void getVersionName() {
}
public void setStrings() {
} }
} }

View File

@@ -0,0 +1,382 @@
/*
* Copyright 2017 .
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.dinect.checker;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.provider.Settings;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.google.zxing.Result;
import org.json.JSONArray;
import org.json.JSONException;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import me.dm7.barcodescanner.zxing.ZXingScannerView;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Headers;
import okhttp3.HttpUrl;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
/**
* Created by anonymous
*/
public class ScannerActivity extends AppCompatActivity implements
View.OnClickListener, ZXingScannerView.ResultHandler {
private final static String TAG = "Checker.ScannerActivity";
private static final int SCAN_INTERVAL_PERIOD = 500;
enum SearchType {
CARD,
PHONE_NUMBER
}
private ApiClient mClient;
private ImageView mButton;
private EditText mInputField;
private SearchType mSearchType;
private ZXingScannerView scannerView;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.a_zxing);
final String appToken = getIntent().getStringExtra(MainActivity.PREF_APP_TOKEN);
final String token = getIntent().getStringExtra(MainActivity.PREF_POS_TOKEN);
final String url = getIntent().getStringExtra(MainActivity.PREF_API_URL) + "/users/";
mClient = new ApiClient(url, appToken, token);
initToolbar(getIntent());
scannerView = new ZXingScannerView(this);
ViewGroup instructions = findViewById(R.id.instructions);
TextView text = (TextView) instructions.getChildAt(0);
text.setText(getIntent().getStringExtra("camera_instructions").replace("%s", BuildConfig.appTitle));
Button button = (Button) instructions.getChildAt(1);
button.setText(getIntent().getStringExtra("open_settings"));
button.setOnClickListener((v) ->
startActivityForResult(new Intent(Settings.ACTION_SETTINGS), 0));
}
@Override
public void onResume() {
super.onResume();
ViewGroup root = findViewById(R.id.zxingRoot);
int count = root.getChildCount();
if (root.getChildAt(count - 1).equals(scannerView)) {
scannerView.setResultHandler(this);
scannerView.startCamera();
} else if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.CAMERA)
== PackageManager.PERMISSION_GRANTED) {
View instructions = findViewById(R.id.instructions);
if (instructions != null) {
root.removeView(instructions);
}
root.addView(scannerView);
scannerView.setResultHandler(this);
scannerView.startCamera();
}
}
@Override
public void onPause() {
super.onPause();
scannerView.stopCamera();
}
@Override
public void onBackPressed() {
setResult(RESULT_CANCELED);
finish();
}
@Override
public void handleResult(Result raw) {
handleBarcode(raw.getText());
scannerView.postDelayed(() -> scannerView.resumeCameraPreview(ScannerActivity.this), SCAN_INTERVAL_PERIOD);
}
protected final void initToolbar(Intent intent) {
final Toolbar toolbar = findViewById(R.id.toolbar);
toolbar.setBackgroundColor((int) intent.getLongExtra(MainActivity.PREF_APP_BAR_COLOR, 0xffffff));
setSupportActionBar(toolbar);
final ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setTitle(null);
actionBar.setDisplayHomeAsUpEnabled(false);
}
initManualInput();
initSwitchButton();
}
private void initSwitchButton() {
mButton = findViewById(R.id.cardPhoneButton);
resetSearchType(SearchType.CARD, R.drawable.ic_card, "enter_manual");
}
private void resetSearchType(SearchType type, int iconId, String hintKey) {
mSearchType = type;
mButton.setBackgroundResource(iconId);
mInputField.setHint(getIntent().getStringExtra(hintKey));
}
@Override
public void onClick(View v) {
if (mSearchType == SearchType.CARD) {
resetSearchType(SearchType.PHONE_NUMBER, R.drawable.ic_phone, "enter_phone");
} else {
resetSearchType(SearchType.CARD, R.drawable.ic_card, "enter_manual");
}
}
private void initManualInput() {
mInputField = findViewById(R.id.manual_input);
mInputField.setOnEditorActionListener((v, actionId, event) -> {
handleBarcode(v.getText().toString());
return false;
});
if (BuildConfig.DEBUG) {
if ("autobonus".equals(BuildConfig.FLAVOR)) {
mInputField.setText("9990010009012057060904229");
} else if ("dinect_INT".equals(BuildConfig.FLAVOR)) {
mInputField.setText("4620011139016337050236302");
}
}
}
public void handleBarcode(final @NonNull String searchString) {
mClient.findUser(searchString, mSearchType, new Callback() {
@Override
public void onFailure(Call call, IOException e) {
handleFail(searchString);
}
@Override
public void onResponse(Call call, Response response) {
try {
ResponseBody body = response.body();
if (body != null) {
switch (response.code()) {
case 200:
final JSONArray users = new JSONArray(body.string());
if (users.length() > 0) {
handleSuccess(searchString, users.get(0).toString());
} else {
handleFail(searchString);
}
break;
case 204:
handleFail(searchString);
break;
}
}
} catch (final IOException | JSONException e) {
Log.e(TAG, e.getMessage(), e);
handleFail(searchString);
}
}
});
}
protected final void handleSuccess(final String card, final String user) {
runOnUiThread(() -> {
setResult(RESULT_OK, new Intent().putExtra("user", user).putExtra("card", card));
finish();
});
}
protected final void handleFail(final String searchString) {
runOnUiThread(() -> {
String message = String.format(getIntent().getStringExtra("identifier_not_found"), searchString)
+ ".\n"
+ String.format(getIntent().getStringExtra("error_contact_support"), BuildConfig.supportPhone);
Toast.makeText(ScannerActivity.this, message, Toast.LENGTH_SHORT).show();
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu, menu);
return true;
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
MenuItem settings = menu.findItem(R.id.settings);
settings.setIcon(getResources().getDrawable(R.drawable.settings));
settings.setTitle(getIntent().getStringExtra("settings"));
MenuItem faq = menu.findItem(R.id.faq);
faq.setIcon(getResources().getDrawable(R.drawable.help));
faq.setTitle(getIntent().getStringExtra("faq"));
MenuItem exit = menu.findItem(R.id.exit);
exit.setIcon(getResources().getDrawable(R.drawable.exit));
exit.setTitle(getIntent().getStringExtra("exit"));
return super.onPrepareOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.settings) {
final Intent intent = new Intent();
intent.putExtra("item", "settings");
setResult(RESULT_OK, intent);
finish();
return true;
} else if (item.getItemId() == R.id.exit) {
exit();
return true;
} else if (item.getItemId() == R.id.faq) {
final Intent intent = new Intent();
intent.putExtra("item", "faq");
setResult(RESULT_OK, intent);
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
void exit() {
final Intent intent = new Intent();
intent.putExtra("item", "exit");
setResult(RESULT_OK, intent);
finish();
}
private static class ApiClient {
private static final int TIMEOUT = 3;
private OkHttpClient mHttp;
private String mEndpoint;
private ApiClient(final String url, final @NonNull String appToken, final @NonNull String token) {
mEndpoint = url;
mHttp = new OkHttpClient().
newBuilder()
.connectTimeout(TIMEOUT, TimeUnit.SECONDS)
.readTimeout(TIMEOUT, TimeUnit.SECONDS)
.writeTimeout(TIMEOUT, TimeUnit.SECONDS)
.addInterceptor(new DinectAuthorizationInterceptor(appToken, token, "checker/0.1", true))
.build();
}
private void findUser(String searchString, ScannerActivity.SearchType searchType, Callback callback) {
final Request.Builder requestBuilder = new Request.Builder();
final HttpUrl url = HttpUrl.parse(mEndpoint);
if (url != null) {
HttpUrl.Builder httpBuilder = url.newBuilder();
switch (searchType) {
case CARD:
httpBuilder.addQueryParameter("auto", searchString);
break;
case PHONE_NUMBER:
httpBuilder.addQueryParameter("phone", searchString);
break;
}
mHttp.newCall(requestBuilder.url(httpBuilder.build()).build()).enqueue(callback);
}
}
}
private static class DinectAuthorizationInterceptor implements Interceptor {
private final String token;
private final String appToken;
private final String dmAuthorization;
private final String authorization;
private final String userAgent;
private final boolean useAuthHeader;
DinectAuthorizationInterceptor(final String appToken, final String token, final String clientInfo, final boolean useAuthHeader) {
this.appToken = appToken;
this.token = token;
this.useAuthHeader = useAuthHeader;
userAgent = clientInfo;
dmAuthorization = "dmapptoken " + appToken;
authorization = "dmtoken " + token;
}
@Override
public Response intercept(Interceptor.Chain chain) throws IOException {
final Request originalRequest = chain.request();
final HttpUrl originalUrl = originalRequest.url();
final Request.Builder requestBuilder = originalRequest.newBuilder();
HttpUrl url = originalUrl;
Headers headers;
headers = originalRequest.headers();
final Headers.Builder headersBuilder = headers.newBuilder();
headersBuilder.set("User-Agent", userAgent);
if (useAuthHeader) {
headersBuilder.set("DM-Authorization", dmAuthorization);
if (null != token) {
headersBuilder.set("Authorization", authorization);
}
headers = headersBuilder.build();
} else {
final HttpUrl.Builder urlBuilder = originalRequest.url().newBuilder();
urlBuilder.addQueryParameter("_dmapptoken", appToken);
urlBuilder.addQueryParameter("user_agent", userAgent);
if (null != token) {
urlBuilder.addQueryParameter("_dmtoken", token);
}
url = urlBuilder.build();
}
final Request request = requestBuilder.url(url).headers(headers).build();
return chain.proceed(request);
}
}
}

View File

@@ -1,6 +0,0 @@
package com.dinect.checker;
public enum SearchType {
CARD,
PHONE_NUMBER
}

View File

@@ -1,81 +0,0 @@
package com.dinect.checker;
import android.content.Context;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import com.dinect.checker.R;
import com.dinect.checker.SearchType;
public class StatedImageButton extends LinearLayout {
private Context mContext;
private View mRootView;
private ImageButton mBtnImageState;
private SearchType mCurrentButtonState = SearchType.CARD;
private StatedImageButtonInteractorListener statedImageButtonInteractorListener;
public StatedImageButton(Context context) {
super(context);
init(context);
}
public SearchType getCurrentState() {
return mCurrentButtonState;
}
public StatedImageButton(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init(context);
}
public StatedImageButton(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
private void init(Context context) {
mContext = context;
mRootView = inflate(mContext, R.layout.partial_buttons_layout, this);
mBtnImageState = (ImageButton) mRootView.findViewById(R.id.btn_image_state);
mBtnImageState.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (mCurrentButtonState == SearchType.CARD) {
mCurrentButtonState = SearchType.PHONE_NUMBER;
} else {
mCurrentButtonState = SearchType.CARD;
}
setButtonState(mCurrentButtonState);
if (statedImageButtonInteractorListener != null) {
statedImageButtonInteractorListener.onStateChanged(mCurrentButtonState);
}
}
});
}
public void setButtonState(SearchType searchType) {
mCurrentButtonState = searchType;
switch (mCurrentButtonState) {
case CARD:
mBtnImageState.setBackground(getResources().getDrawable(R.drawable.ic_card));
break;
case PHONE_NUMBER:
mBtnImageState.setBackground(getResources().getDrawable(R.drawable.ic_phone));
break;
}
}
public void setStatedImageButtonInteractorListener(StatedImageButtonInteractorListener statedImageButtonInteractorListener) {
this.statedImageButtonInteractorListener = statedImageButtonInteractorListener;
}
public interface StatedImageButtonInteractorListener {
void onStateChanged(SearchType searchType);
}
}

View File

@@ -1,21 +0,0 @@
package com.dinect.checker;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
public class Utils {
private Utils() {
}
public static boolean isOnline(Context context) {
NetworkInfo netInfo = getConnectivityManager(context).getActiveNetworkInfo();
return netInfo != null && netInfo.isConnected();
}
private static ConnectivityManager getConnectivityManager(Context context) {
return (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
}
}

View File

@@ -1,68 +0,0 @@
/*
* Copyright 2017 .
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.dinect.checker.net;
import android.support.annotation.NonNull;
import java.util.concurrent.TimeUnit;
import okhttp3.Callback;
import okhttp3.HttpUrl;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import com.dinect.checker.SearchType;
/**
* Created by anonymous
*/
public final class ApiClient {
private static final String TAG = "Checker.ApiClient";
private static final int TIMEOUT = 3;
private OkHttpClient mHttp;
private String mEndpoint;
public ApiClient(final String url, final @NonNull String appToken, final @NonNull String token) {
mEndpoint = url;
mHttp = new OkHttpClient().
newBuilder()
.connectTimeout(TIMEOUT, TimeUnit.SECONDS)
.readTimeout(TIMEOUT, TimeUnit.SECONDS)
.writeTimeout(TIMEOUT, TimeUnit.SECONDS)
.addInterceptor(new DinectAuthorizationInterceptor(appToken, token, "checker/0.1", true))
.build();
}
public void findUser(String searchString, SearchType searchType, Callback callback) {
final Request.Builder requestBuilder = new Request.Builder();
final HttpUrl url = HttpUrl.parse(mEndpoint);
if (url != null) {
HttpUrl.Builder httpBuilder = url.newBuilder();
switch (searchType) {
case CARD:
httpBuilder.addQueryParameter("auto", searchString);
break;
case PHONE_NUMBER:
httpBuilder.addQueryParameter("phone", searchString);
break;
}
mHttp.newCall(requestBuilder.url(httpBuilder.build()).build()).enqueue(callback);
}
}
}

View File

@@ -1,84 +0,0 @@
/*
* Copyright 2017 .
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.dinect.checker.net;
import java.io.IOException;
import okhttp3.Headers;
import okhttp3.HttpUrl;
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;
/**
* @author anonymous
*/
public final class DinectAuthorizationInterceptor implements Interceptor {
private final String token;
private final String appToken;
private final String dmAuthorization;
private final String authorization;
private final String userAgent;
private final boolean useAuthHeader;
public DinectAuthorizationInterceptor(final String appToken, final String token, final String clientInfo, final boolean useAuthHeader) {
this.appToken = appToken;
this.token = token;
this.useAuthHeader = useAuthHeader;
userAgent = clientInfo;
// optimization: concatenate once
dmAuthorization = "dmapptoken " + appToken;
authorization = "dmtoken " + token;
}
@Override
public Response intercept(Interceptor.Chain chain) throws IOException {
final Request originalRequest = chain.request();
final HttpUrl originalUrl = originalRequest.url();
final Request.Builder requestBuilder = originalRequest.newBuilder();
HttpUrl url = originalUrl;
Headers headers;
headers = originalRequest.headers();
final Headers.Builder headersBuilder = headers.newBuilder();
// always set UA and content type
headersBuilder.set("User-Agent", userAgent);
// Add auth info. Either in headers or query parameters
if (useAuthHeader) {
headersBuilder.set("DM-Authorization", dmAuthorization);
if (null != token) {
headersBuilder.set("Authorization", authorization);
}
headers = headersBuilder.build();
} else {
final HttpUrl.Builder urlBuilder = originalRequest.url().newBuilder();
urlBuilder.addQueryParameter("_dmapptoken", appToken);
urlBuilder.addQueryParameter("user_agent", userAgent);
if (null != token) {
urlBuilder.addQueryParameter("_dmtoken", token);
}
url = urlBuilder.build();
}
final Request request = requestBuilder.url(url).headers(headers).build();
return chain.proceed(request);
}
}

View File

@@ -1,179 +0,0 @@
package com.dinect.checker.zbar;
import android.content.Intent;
import android.hardware.Camera;
import android.os.Bundle;
import android.os.Handler;
import android.text.TextUtils;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
import com.dinect.checker.AbstractScannerActivity;
import com.dinect.checker.R;
import com.dinect.checker.Utils;
import net.sourceforge.zbar.Config;
import net.sourceforge.zbar.Image;
import net.sourceforge.zbar.ImageScanner;
import net.sourceforge.zbar.Symbol;
import net.sourceforge.zbar.SymbolSet;
public class CameraActivity extends AbstractScannerActivity implements
Camera.PreviewCallback {
public static final String ERROR_INFO = "ERROR_INFO";
private int mOffset;
private CameraPreview mPreview;
private Camera mCamera;
private ImageScanner mScanner;
private Handler mAutoFocusHandler;
private boolean mPreviewing = true;
static {
System.loadLibrary("iconv");
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (!init(R.layout.a_zbar)) {
return;
}
initToolbar(getIntent());
mPreview = (CameraPreview) initScanner();
addScanner(mPreview, R.id.zbarRoot);
}
@Override
protected View initScanner() {
mOffset = (int) (56 * getResources().getDisplayMetrics().density);
mAutoFocusHandler = new Handler();
// create and configure image scanner
mScanner = new ImageScanner();
mScanner.setConfig(0, Config.X_DENSITY, 3);
mScanner.setConfig(0, Config.Y_DENSITY, 3);
int[] symbols = getIntent().getIntArrayExtra(SCAN_MODES);
if (symbols != null) {
mScanner.setConfig(Symbol.NONE, Config.ENABLE, 0);
for (int symbol : symbols) {
mScanner.setConfig(symbol, Config.ENABLE, 1);
}
}
mPreview = new CameraPreview(this, this, autoFocusCB);
return mPreview;
}
@Override
public void onResume() {
super.onResume();
// Open the default i.e. the first rear facing camera.
mCamera = Camera.open();
if (mCamera == null) {
// Cancel request if mCamera is null.
cancelRequest();
return;
}
mPreview.setCamera(mCamera);
mPreview.showSurfaceView();
mPreviewing = true;
}
@Override
public void onPause() {
super.onPause();
// Because the Camera object is a shared resource, it's very
// important to release it when the activity is paused.
if (mCamera != null) {
mPreview.setCamera(null);
mCamera.cancelAutoFocus();
mCamera.setPreviewCallback(null);
mCamera.stopPreview();
mCamera.release();
// According to Jason Kuang on http://stackoverflow.com/questions/6519120/how-to-recover-camera-preview-from-sleep,
// there might be surface recreation problems when the device goes to sleep. So lets just hide it and
// recreate on resume
mPreview.hideSurfaceView();
mPreviewing = false;
mCamera = null;
}
}
public void cancelRequest() {
Intent dataIntent = new Intent();
dataIntent.putExtra(ERROR_INFO, "Camera unavailable");
setResult(RESULT_CANCELED, dataIntent);
finish();
}
public void onPreviewFrame(byte[] data, Camera camera) {
if (mPreviewing) {
Camera.Parameters parameters = camera.getParameters();
Camera.Size size = parameters.getPreviewSize();
Image barcode = new Image(size.width, size.height, "Y800");
barcode.setData(data);
barcode.setCrop((size.width / 2) - mOffset, 0, (size.width / 2) + mOffset, size.height);
int result = mScanner.scanImage(barcode);
if (result != 0) {
mPreviewing = false;
SymbolSet syms = mScanner.getResults();
for (Symbol sym : syms) {
String symData = sym.getData();
if (!TextUtils.isEmpty(symData) && Utils.isOnline(this)) {
requestUser(sym.getData());
break;
} else {
mPreviewing = true;
Toast.makeText(this, "Проверьте интернет соединение", Toast.LENGTH_SHORT).show();
}
}
}
}
}
private Runnable doAutoFocus = new Runnable() {
public void run() {
if (mCamera != null && mPreviewing) {
mCamera.autoFocus(autoFocusCB);
}
}
};
// Mimic continuous auto-focusing
Camera.AutoFocusCallback autoFocusCB = new Camera.AutoFocusCallback() {
public void onAutoFocus(boolean success, Camera camera) {
mAutoFocusHandler.postDelayed(doAutoFocus, 1000);
}
};
@Override
public void onBackPressed() {
setResult(RESULT_CANCELED);
finish();
}
private void requestUser(String code) {
handleBarcode(code);
}
}

View File

@@ -1,209 +0,0 @@
package com.dinect.checker.zbar;
import android.app.Activity;
import android.content.Context;
import android.hardware.Camera;
import android.hardware.Camera.AutoFocusCallback;
import android.hardware.Camera.CameraInfo;
import android.hardware.Camera.PreviewCallback;
import android.hardware.Camera.Size;
import android.util.Log;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import java.io.IOException;
import java.util.List;
class CameraPreview extends ViewGroup implements SurfaceHolder.Callback {
private final static String TAG = "Checker.CameraPreview";
SurfaceView mSurfaceView;
SurfaceHolder mHolder;
Size mPreviewSize;
List<Size> mSupportedPreviewSizes;
Camera mCamera;
PreviewCallback mPreviewCallback;
AutoFocusCallback mAutoFocusCallback;
CameraPreview(Context context, PreviewCallback previewCallback, AutoFocusCallback autoFocusCb) {
super(context);
mPreviewCallback = previewCallback;
mAutoFocusCallback = autoFocusCb;
mSurfaceView = new SurfaceView(context);
addView(mSurfaceView);
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = mSurfaceView.getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void setCamera(Camera camera) {
mCamera = camera;
if (mCamera != null) {
mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes();
requestLayout();
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// We purposely disregard child measurements because act as a
// wrapper to a SurfaceView that centers the camera preview instead
// of stretching it.
final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec);
final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec);
setMeasuredDimension(width, height);
if (mSupportedPreviewSizes != null) {
mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, height);
}
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
if (changed && getChildCount() > 0) {
final View child = getChildAt(0);
final int width = r - l;
final int height = b - t;
int previewWidth = width;
int previewHeight = height;
if (mPreviewSize != null) {
previewWidth = mPreviewSize.width;
previewHeight = mPreviewSize.height;
}
child.layout(0, 0, width, height);
}
}
public void hideSurfaceView() {
mSurfaceView.setVisibility(View.INVISIBLE);
}
public void showSurfaceView() {
mSurfaceView.setVisibility(View.VISIBLE);
}
public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, acquire the camera and tell it where
// to draw.
try {
if (mCamera != null) {
mCamera.setPreviewDisplay(holder);
}
} catch (IOException exception) {
Log.e(TAG, "IOException caused by setPreviewDisplay()", exception);
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
// Surface will be destroyed when we return, so stop the preview.
if (mCamera != null) {
mCamera.cancelAutoFocus();
mCamera.stopPreview();
}
}
private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
final double ASPECT_TOLERANCE = 0.1;
double targetRatio = (double) w / h;
if (sizes == null) return null;
Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight = h;
// Try to find an size match aspect ratio and size
for (Size size : sizes) {
double ratio = (double) size.width / size.height;
if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
// Cannot find the one match the aspect ratio, ignore the requirement
if (optimalSize == null) {
minDiff = Double.MAX_VALUE;
for (Size size : sizes) {
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
return optimalSize;
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
if (holder.getSurface() == null) {
// preview surface does not exist
return;
}
if (mCamera != null) {
// Now that the size is known, set up the camera parameters and begin
// the preview.
setCameraDisplayOrientation(0);
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
requestLayout();
mCamera.setParameters(parameters);
mCamera.setPreviewCallback(mPreviewCallback);
mCamera.startPreview();
mCamera.autoFocus(mAutoFocusCallback);
}
}
void setCameraDisplayOrientation(int cameraId) {
int rotation = ((Activity) getContext()).getWindowManager().getDefaultDisplay().getRotation();
int degrees = 0;
switch (rotation) {
case Surface.ROTATION_0:
degrees = 0;
break;
case Surface.ROTATION_90:
degrees = 90;
break;
case Surface.ROTATION_180:
degrees = 180;
break;
case Surface.ROTATION_270:
degrees = 270;
break;
}
int result = 0;
// получаем инфо по камере cameraId
CameraInfo info = new CameraInfo();
Camera.getCameraInfo(cameraId, info);
// задняя камера
if (info.facing == CameraInfo.CAMERA_FACING_BACK) {
result = ((360 - degrees) + info.orientation);
} else
// передняя камера
if (info.facing == CameraInfo.CAMERA_FACING_FRONT) {
result = ((360 - degrees) - info.orientation);
result += 360;
}
result = result % 360;
mCamera.setDisplayOrientation(result);
}
}

View File

@@ -1,91 +0,0 @@
/*
* Copyright 2017 .
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.dinect.checker.zxing;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import com.dinect.checker.AbstractScannerActivity;
import com.dinect.checker.R;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.Result;
import java.util.ArrayList;
import me.dm7.barcodescanner.zxing.ZXingScannerView;
/**
* Created by anonymous
*/
public class ScannerActivity extends AbstractScannerActivity
implements ZXingScannerView.ResultHandler {
private static final int SCAN_INTERVAL_PERIOD = 500;
private ZXingScannerView scannerView;
@Override
public void onCreate(Bundle state) {
super.onCreate(state);
if (!init(R.layout.a_zxing)) {
return;
}
initToolbar(getIntent());
scannerView = (ZXingScannerView) initScanner();
addScanner(scannerView, R.id.zxingRoot);
}
@Override
protected View initScanner() {
return new ZXingScannerView(this);
}
@Override
public void onResume() {
super.onResume();
scannerView.setResultHandler(this);
scannerView.startCamera();
}
@Override
public void onPause() {
super.onPause();
scannerView.stopCamera();
}
@Override
public void onBackPressed() {
setResult(RESULT_CANCELED);
finish();
}
@Override
public void handleResult(Result raw) {
handleBarcode(raw.getText());
scannerView.postDelayed(new Runnable() {
@Override
public void run() {
scannerView.resumeCameraPreview(ScannerActivity.this);
}
}, SCAN_INTERVAL_PERIOD);
}
}

View File

@@ -1,51 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/zbarRoot"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<View
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginBottom="56dp"
android:layout_weight="0.5"/>
<View
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginTop="56dp"
android:layout_weight="0.5" />
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_gravity="center"
android:layout_marginBottom="56dp"
android:background="#00ff00" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_gravity="center"
android:layout_marginTop="56dp"
android:background="#00ff00" />
<include layout="@layout/v_custom_toolbar" />
<View
android:id="@+id/toolbarShadow"
android:layout_width="match_parent"
android:layout_height="4dp"
android:layout_marginTop="?attr/actionBarSize"
android:background="@drawable/shadow_bottom" />
</FrameLayout>

View File

@@ -1,18 +1,36 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/zxingRoot" android:id="@+id/zxingRoot"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical"
android:background="@android:color/white"> android:background="@android:color/white">
<include layout="@layout/v_custom_toolbar" /> <include layout="@layout/v_custom_toolbar" />
<View <LinearLayout
android:id="@+id/zxingToolbarShadow" android:id="@+id/instructions"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="4dp" android:layout_height="wrap_content"
android:layout_marginTop="?attr/actionBarSize" android:gravity="center"
android:background="@drawable/shadow_bottom" /> android:layout_marginTop="72dp"
android:orientation="vertical">
</FrameLayout> <TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:text="Для корректной работы приложения необходимо открыть Настройки, найти пункт Приложения, выбрать Autobonus, нажать на кнопку Разрешения, поставить галочку напротив слова Камера" />
<Button
android:id="@+id/openSettings"
android:layout_width="wrap_content"
android:layout_height="48dp"
android:layout_gravity="center"
android:text="Открыть настройки" />
</LinearLayout>
</LinearLayout>

View File

@@ -1,15 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageButton
android:id="@+id/btn_image_state"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</LinearLayout>
</merge>

View File

@@ -1,20 +1,19 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.Toolbar <android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/toolbar" android:id="@+id/toolbar"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:fitsSystemWindows="true" android:fitsSystemWindows="true"
android:orientation="vertical"
android:minHeight="?attr/actionBarSize" android:minHeight="?attr/actionBarSize"
android:orientation="vertical"
app:titleTextColor="@android:color/white"> app:titleTextColor="@android:color/white">
<com.dinect.checker.StatedImageButton <ImageView
android:id="@+id/cardPhoneButton" android:id="@+id/cardPhoneButton"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_marginRight="12dp" android:layout_height="wrap_content"
android:layout_height="wrap_content" /> android:layout_marginRight="12dp" />
<EditText <EditText
android:id="@+id/manual_input" android:id="@+id/manual_input"
@@ -26,4 +25,10 @@
android:textColor="@android:color/white" android:textColor="@android:color/white"
android:textColorHint="@android:color/white" /> android:textColorHint="@android:color/white" />
<View
android:layout_width="match_parent"
android:layout_height="4dp"
android:layout_marginTop="?attr/actionBarSize"
android:background="@drawable/shadow_bottom" />
</android.support.v7.widget.Toolbar> </android.support.v7.widget.Toolbar>

View File

@@ -1,5 +0,0 @@
<resources>
<dimen name="scanner_contour_left">24dp</dimen>
<dimen name="scanner_contour_top">178dp</dimen>
<dimen name="scanner_contour_height">232dp</dimen>
</resources>

View File

@@ -1,8 +0,0 @@
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:textColorSecondary">@android:color/white</item>
</style>
</resources>

View File

@@ -1,11 +1,16 @@
buildscript { buildscript {
ext.kotlin_version = '1.2.40'
repositories { repositories {
jcenter() jcenter()
google() google()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:3.0.1' classpath 'com.android.tools.build:gradle:3.1.1'
classpath('com.google.gms:google-services:3.2.0') {
exclude group: 'com.google.guava', module: 'guava-jdk5'
}
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
} }
} }
@@ -13,9 +18,6 @@ allprojects {
repositories { repositories {
jcenter() jcenter()
google() google()
maven {
url "https://maven.google.com"
}
} }
} }

View File

@@ -120,4 +120,13 @@ To improve barcode scanning quality, adjust the distance between the camera and
<string name="joys_minus">Joys was charged</string> <string name="joys_minus">Joys was charged</string>
<string name="joys_hint">Joys to charge</string> <string name="joys_hint">Joys to charge</string>
<string name="phone">Phone</string> <string name="phone">Phone</string>
<string name="camera_instructions">
Откройте Настройки.
Найдите пункт Приложения.
В появившемся списке выберите %s.
На открывшейся странице выберите строчку Разрешения.
Поставьте галочку напротив слова Камера
Вернитесь к приложению %s.
</string>
<string name="open_settings">Открыть настройки</string>
</resources> </resources>

View File

@@ -116,4 +116,13 @@ Hay que poner el dibujo del codigo de tarjeta en cámara del escanear totalmente
<string name="joys_minus">Joys fueron insumido</string> <string name="joys_minus">Joys fueron insumido</string>
<string name="joys_hint">¿Cuántas Joys hay que insumir?</string> <string name="joys_hint">¿Cuántas Joys hay que insumir?</string>
<string name="phone">Número de teléfono</string> <string name="phone">Número de teléfono</string>
<string name="camera_instructions">
Откройте Настройки.
Найдите пункт Приложения.
В появившемся списке выберите %s.
На открывшейся странице выберите строчку Разрешения.
Поставьте галочку напротив слова Камера
Вернитесь к приложению %s.
</string>
<string name="open_settings">Открыть настройки</string>
</resources> </resources>

View File

@@ -119,4 +119,13 @@
<string name="joys_minus">Joys было списано</string> <string name="joys_minus">Joys было списано</string>
<string name="joys_hint">Joys списать</string> <string name="joys_hint">Joys списать</string>
<string name="phone">Телефон</string> <string name="phone">Телефон</string>
<string name="camera_instructions">
Откройте Настройки.
Найдите пункт Приложения.
В появившемся списке выберите %s.
На открывшейся странице выберите строчку Разрешения.
Поставьте галочку напротив слова Камера
Вернитесь к приложению %s.
</string>
<string name="open_settings">Открыть настройки</string>
</resources> </resources>

View File

@@ -121,4 +121,13 @@
<string name="joys_minus">Joys списано</string> <string name="joys_minus">Joys списано</string>
<string name="joys_hint">Скільки Joys списати?</string> <string name="joys_hint">Скільки Joys списати?</string>
<string name="phone">Телефон</string> <string name="phone">Телефон</string>
<string name="camera_instructions">
Откройте Настройки.
Найдите пункт Приложения.
В появившемся списке выберите %s.
На открывшейся странице выберите строчку Разрешения.
Поставьте галочку напротив слова Камера
Вернитесь к приложению %s.
</string>
<string name="open_settings">Открыть настройки</string>
</resources> </resources>

View File

@@ -3,7 +3,6 @@ import 'dart:async';
import 'package:checker/screens/faq.dart'; import 'package:checker/screens/faq.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:image_picker/image_picker.dart';
import 'db.dart'; import 'db.dart';
import 'strings.dart'; import 'strings.dart';
@@ -51,8 +50,3 @@ getLocaleTitle(String code) {
return 'Español'; return 'Español';
} }
} }
// Добавил вызов, что-бы AOT компилер не выкинул либу.
getImage() async {
return await ImagePicker.pickImage();
}

View File

@@ -52,14 +52,12 @@ class SqliteHelper {
/// Создается запись в таблице, содержащая /// Создается запись в таблице, содержащая
/// необходимые для идентификации пользователя и проведения запросов. /// необходимые для идентификации пользователя и проведения запросов.
Future createSession(String merchantID, String posID, String token) async { Future createSession(String merchantID, String posID, String token) async {
Map session = { Map session = {
columnMerchantID: merchantID, columnMerchantID: merchantID,
columnPosID: posID, columnPosID: posID,
columnToken: token, columnToken: token,
columnDocID: 0 columnDocID: 0
}; };
return db.insert(tableSession, session); return db.insert(tableSession, session);
} }
@@ -109,7 +107,8 @@ class SqliteHelper {
Future<String> getPosID() async { Future<String> getPosID() async {
Map session = await selectAll(tableSession); Map session = await selectAll(tableSession);
return session != null ? session[columnPosID] : new DateTime.now().millisecondsSinceEpoch.toString(); String time = new DateTime.now().millisecondsSinceEpoch.toString();
return session != null ? session[columnPosID] : time;
} }
Future<int> getDocID() async { Future<int> getDocID() async {

View File

@@ -1,21 +1,16 @@
import 'dart:core';
import 'package:checker/db.dart'; import 'package:checker/db.dart';
import 'package:checker/strings.dart'; import 'package:checker/strings.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:checker/screens/splash.dart'; import 'package:checker/screens/splash.dart';
import 'package:flutter/services.dart'; import 'package:checker/common.dart';
const platform = const MethodChannel('com.dinect.checker/instance_id');
main() { main() {
platform.invokeMethod('getFlavor').then((flavor) { platform.invokeMethod('getFlavor').then((flavor) {
platform.invokeMethod('getAppTitle').then((title) { platform.invokeMethod('getAppTitle').then((title) {
String app = flavor; // dinect, autobonus String app = flavor; // dinect, autobonus
String appName = title; // Dinect, Dinect (INT), Autobonus String appName = title; // Dinect, Dinect (INT), Autobonus
SqliteHelper helper = new SqliteHelper(); SqliteHelper helper = new SqliteHelper();
helper.open().then((_) { helper.open().then((_) {
helper.getLocale().then((locale) { helper.getLocale().then((locale) {
if (locale == null) { if (locale == null) {
@@ -23,13 +18,22 @@ main() {
} else { } else {
start(app, appName, locale, helper); start(app, appName, locale, helper);
} }
}, onError: (e) {
platform.invokeMethod('logError', {"message":e.toString()});
}); });
}, onError: (e) {
platform.invokeMethod('logError', {"message":e.toString()});
}); });
}, onError: (e) {
platform.invokeMethod('logError', {"message":e.toString()});
}); });
}, onError: (e) {
platform.invokeMethod('logError', {"message":e.toString()});
}); });
} }
initWithSystemValue(String app, String name, String locale, SqliteHelper helper) { initWithSystemValue(String app, String name, String locale,
SqliteHelper helper) {
helper.getSettings(false).then((settings) { helper.getSettings(false).then((settings) {
if (settings.isEmpty) { if (settings.isEmpty) {
createSettingsTable(app, name, helper); createSettingsTable(app, name, helper);
@@ -44,7 +48,11 @@ createSettingsTable(String app, String name, SqliteHelper helper) {
platform.invokeMethod('getCurrency').then((currency) { platform.invokeMethod('getCurrency').then((currency) {
helper.createAppInfo(currency, locale).then((_) { helper.createAppInfo(currency, locale).then((_) {
start(app, name, locale, helper); start(app, name, locale, helper);
}, onError: (e) {
platform.invokeMethod('logError', {"message":e.toString()});
}); });
}, onError: (e) {
platform.invokeMethod('logError', {"message":e.toString()});
}); });
}); });
} }
@@ -64,7 +72,8 @@ class Checker extends StatefulWidget {
Checker(this.app, this.appName, this.helper); Checker(this.app, this.appName, this.helper);
@override @override
State<StatefulWidget> createState() => new CheckerState( State<StatefulWidget> createState() =>
new CheckerState(
this.app, this.app,
this.appName, this.appName,
this.helper); this.helper);

View File

@@ -79,11 +79,12 @@ class RegistrationScreenState extends BaseState<FinishRegistrationScreen> {
setState(() { setState(() {
_tokenActive = JSON.decode(response.body)['active']; _tokenActive = JSON.decode(response.body)['active'];
}); });
}).catchError((error) { }, onError: (e) {
print(error.toString()); platform.invokeMethod('logError', {"message":e.toString()}).then((_) {
return false; return false;
}); });
}); });
});
} }
}); });
} }

View File

@@ -123,8 +123,8 @@ class RegistrationScreenState extends BaseState<RegistrationScreen> {
error = parsedMap['errors'][0]; error = parsedMap['errors'][0];
}); });
} }
}).catchError((error) { }, onError: (e) {
print(error.toString()); platform.invokeMethod('logError', {"message":e.toString()});
}); });
} }
} }

View File

@@ -191,11 +191,12 @@ class SettingsState extends BaseState<SettingsScreen> {
helper.clear().then((result) { helper.clear().then((result) {
Navigator.of(context).pop(''); Navigator.of(context).pop('');
}); });
}).catchError((error) { }, onError: (e) {
print(error.toString()); platform.invokeMethod('logError', {"message":e.toString()}).then((_) {
Navigator.of(context).pop(''); Navigator.of(context).pop('');
}); });
}); });
});
} }
}); });
} }

View File

@@ -83,10 +83,11 @@ class _SplashScreenState extends BaseState<SplashScreen> {
} else if (token != null) { } else if (token != null) {
_initAndStartScanner(context, app, token, helper); _initAndStartScanner(context, app, token, helper);
} else { } else {
print('Произошла непредусмотренная ошибка в логике приложения'); platform.invokeMethod('logError', {"message":"Token is null"}).then((_) {
helper.getToken().then((token) { helper.getToken().then((token) {
_initAndStartScanner(context, app, token, helper); _initAndStartScanner(context, app, token, helper);
}); });
});
} }
}); });
}); });
@@ -103,8 +104,8 @@ class _SplashScreenState extends BaseState<SplashScreen> {
if (await platform.invokeMethod('isOnline')) { if (await platform.invokeMethod('isOnline')) {
getCheckTokenStatusRequest(token).then((statusResponse) { getCheckTokenStatusRequest(token).then((statusResponse) {
handleStatusResponse(statusResponse, helper); handleStatusResponse(statusResponse, helper);
}).catchError((error) { }, onError: (e) {
print(error.toString()); platform.invokeMethod('logError', {"message":e.toString()});
}); });
} }
} }
@@ -153,8 +154,8 @@ class _SplashScreenState extends BaseState<SplashScreen> {
} else if (response.statusCode == 201) { } else if (response.statusCode == 201) {
clearToken(response, helper); clearToken(response, helper);
} }
}).catchError((error) { }, onError: (e) {
print(error.toString()); platform.invokeMethod('logError', {"message":e.toString()});
}); });
} }
@@ -164,9 +165,11 @@ class _SplashScreenState extends BaseState<SplashScreen> {
Map parsedMap = JSON.decode(response.body); Map parsedMap = JSON.decode(response.body);
getDeleteTokenRequest(parsedMap['token']).then((_) { getDeleteTokenRequest(parsedMap['token']).then((_) {
showNextScreen(new RegistrationScreen(helper, app)); showNextScreen(new RegistrationScreen(helper, app));
}).catchError((error) { }, onError: (e) {
print(error.toString()); platform.invokeMethod('logError', {"message":e.toString()});
}); });
}, onError: (e) {
platform.invokeMethod('logError', {"message":e.toString()});
}); });
} }
@@ -257,7 +260,11 @@ class _SplashScreenState extends BaseState<SplashScreen> {
.value .value
.toString(); .toString();
platform.invokeMethod('startScanner', args); platform.invokeMethod('startScanner', args);
}, onError: (e) {
platform.invokeMethod('logError', {"message":e.toString()});
}); });
}, onError: (e) {
platform.invokeMethod('logError', {"message":e.toString()});
}); });
} }
} }