SandroMachado / openalpr-android

Android Automatic License Plate Recognition library (http://www.openalpr.com) ported for android.
Apache License 2.0
770 stars 272 forks source link

Error #38

Closed denizme closed 7 years ago

denizme commented 7 years ago

Hi, I can speak a little English. I want to read the plate from Android application.

I'm getting an error. Test phone: LG-L90 Android: 5.0

Error:

E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #1
                  Process: fortibasedanismanlik.plate, PID: 6705
                  java.lang.UnsatisfiedLinkError: com.android.tools.fd.runtime.IncrementalClassLoader$DelegateClassLoader[DexPathList[[dex file "/data/data/fortibasedanismanlik.plate/files/instant-run/dex/slice-support-annotations-23.0.1_1ac4e020d4c8fe58e32dc7d55b3c675a547a2efe-classes.dex", dex file "/data/data/fortibasedanismanlik.plate/files/instant-run/dex/slice-slice_9-classes.dex", dex file "/data/data/fortibasedanismanlik.plate/files/instant-run/dex/slice-slice_8-classes.dex", dex file "/data/data/fortibasedanismanlik.plate/files/instant-run/dex/slice-slice_7-classes.dex", dex file "/data/data/fortibasedanismanlik.plate/files/instant-run/dex/slice-slice_6-classes.dex", dex file "/data/data/fortibasedanismanlik.plate/files/instant-run/dex/slice-slice_5-classes.dex", dex file "/data/data/fortibasedanismanlik.plate/files/instant-run/dex/slice-slice_4-classes.dex", dex file "/data/data/fortibasedanismanlik.plate/files/instant-run/dex/slice-slice_3-classes.dex", dex file "/data/data/fortibasedanismanlik.plate/files/instant-run/dex/slice-slice_2-classes.dex", dex file "/data/data/fortibasedanismanlik.plate/files/instant-run/dex/slice-slice_1-classes.dex", dex file "/data/data/fortibasedanismanlik.plate/files/instant-run/dex/slice-slice_0-classes.dex", dex file "/data/data/fortibasedanismanlik.plate/files/instant-run/dex/slice-picasso-2.5.2_27cfa72c06fe581632ec0927aac379dc32fb8992-classes.dex", dex file "/data/data/fortibasedanismanlik.plate/files/instant-run/dex/slice-internal_impl-23.0.1_5ee279ce67983e03ad7ba03383b9ae3f02a1c09c-classes.dex", dex file "/data/data/fortibasedanismanlik.plate/files/instant-run/dex/slice-gson-2.5_de0e2f4ced45b506f8481ad283630c47e362a524-classes.dex", dex file "/data/data/fortibasedanismanlik.plate/files/instant-run/dex/slice-com.github.SandroMachado-openalpr-android-1.0.0_4bad39b75169c2cbf5aa079edeb5edbc34a5776a-classes.dex", dex file "/data/data/fortibasedanismanlik.plate/files/instant-run/dex/slice-com.android.support-support-v4-23.0.1_045c15e5c19e08c7f1f4e27118dd515c017cd47c-classes.dex", dex file "/data/data/fortibasedanismanlik.plate/files/instant-run/dex/slice-com.android.support-appcompat-v7-23.0.1_d198809873213e007bd5d1c1ef7f8f137ed0f35f-classes.dex"],nativeLibraryDirectories=[/vendor/lib, /system/lib, /vendor/lib, /system/lib]]] couldn't find "libopenalpr-native.so"
                      at java.lang.Runtime.loadLibrary(Runtime.java:366)
                      at java.lang.System.loadLibrary(System.java:989)
                      at org.openalpr.AlprJNIWrapper.<clinit>(AlprJNIWrapper.java:9)
                      at org.openalpr.OpenALPR$Factory.create(OpenALPR.java:78)
                      at fortibasedanismanlik.plate.MainActivity$2.run(MainActivity.java:86)
                      at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
                      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
                      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
                      at java.lang.Thread.run(Thread.java:818)
I/art: Background sticky concurrent mark sweep GC freed 2161(536KB) AllocSpace objects, 4(64KB) LOS objects, 2% free, 7MB/7MB, paused 13.642ms total 36.305ms
I/art: CheckpointMarkThreadRoots callback created = 0xab7ffe00
I/art: CheckpointMarkThreadRoots callback created = 0xab7ffdf0
E/WindowManager: android.view.WindowLeaked: Activity fortibasedanismanlik.plate.MainActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView{91705a5 V.E..... R......D 0,0-513,242} that was originally added here
                     at android.view.ViewRootImpl.<init>(ViewRootImpl.java:376)
                     at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:261)
                     at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:69)
                     at android.app.Dialog.show(Dialog.java:306)
                     at android.app.ProgressDialog.show(ProgressDialog.java:117)
                     at android.app.ProgressDialog.show(ProgressDialog.java:100)
                     at fortibasedanismanlik.plate.MainActivity.onActivityResult(MainActivity.java:72)
                     at android.app.Activity.dispatchActivityResult(Activity.java:6222)
                     at android.app.ActivityThread.deliverResults(ActivityThread.java:3627)
                     at android.app.ActivityThread.handleSendResult(ActivityThread.java:3674)
                     at android.app.ActivityThread.access$1300(ActivityThread.java:151)
                     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1358)
                     at android.os.Handler.dispatchMessage(Handler.java:102)
                     at android.os.Looper.loop(Looper.java:135)
                     at android.app.ActivityThread.main(ActivityThread.java:5349)
                     at java.lang.reflect.Method.invoke(Native Method)
                     at java.lang.reflect.Method.invoke(Method.java:372)
                     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:908)
                     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:703)

Codes:

Gradle:project

allprojects {
    repositories {
        maven { url "https://jitpack.io" }
        jcenter()
    }
}

Gradle:Module

apply plugin: 'com.android.application'

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.1"
    defaultConfig {
        applicationId "fortibasedanismanlik.plate"
        minSdkVersion 16
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:23.0.1'
    testCompile 'junit:junit:4.12'

    compile('com.github.SandroMachado:openalpr-android:1.0.0@aar') {
        transitive = true
    }

    compile 'com.google.code.gson:gson:2.5'
    compile 'com.squareup.picasso:picasso:2.5.2'
}

MainActivity: `public class MainActivity extends AppCompatActivity {

private static final int REQUEST_IMAGE = 100;
private static final int STORAGE=1;
private String ANDROID_DATA_DIR;
private static File destination;
private TextView resultTextView;
private ImageView imageView;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    ANDROID_DATA_DIR = this.getApplicationInfo().dataDir;

    findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            checkPermission();
        }
    });
    resultTextView = (TextView) findViewById(R.id.textView);
    imageView = (ImageView) findViewById(R.id.imageView);

    resultTextView.setText("Press the button below to start a request.");
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == REQUEST_IMAGE && resultCode == Activity.RESULT_OK) {
        final ProgressDialog progress = ProgressDialog.show(this, "Loading", "Parsing result...", true);
        final String openAlprConfFile = ANDROID_DATA_DIR + File.separatorChar + "runtime_data" + File.separatorChar + "openalpr.conf";

        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inSampleSize = 10;

        Picasso.with(MainActivity.this).load(destination).fit().centerCrop().into(imageView);
        resultTextView.setText("Processing");

        AsyncTask.execute(new Runnable() {
            @Override
            public void run() {

                String result = OpenALPR.Factory.create(MainActivity.this,
                        ANDROID_DATA_DIR).recognizeWithCountryRegionNConfig("us"
                        ,"",
                        destination.getAbsolutePath(),
                        openAlprConfFile, 10);

                Log.d("OPEN ALPR", result);

                try {
                    final Results results = new Gson().fromJson(result, Results.class);
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            if (results == null || results.getResults() == null || results.getResults().size() == 0) {
                                Toast.makeText(MainActivity.this, "It was not possible to detect the licence plate.", Toast.LENGTH_LONG).show();
                                resultTextView.setText("It was not possible to detect the licence plate.");
                            } else {
                                resultTextView.setText("Plate: " + results.getResults().get(0).getPlate()
                                        // Trim confidence to two decimal places
                                        + " Confidence: " + String.format("%.2f", results.getResults().get(0).getConfidence()) );
                            }
                        }
                    });

                } catch (JsonSyntaxException exception) {
                    final ResultsError resultsError = new Gson().fromJson(result, ResultsError.class);

                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            resultTextView.setText(resultsError.getMsg());
                        }
                    });
                }
                progress.dismiss();
            }
        });
    }
}

private void checkPermission() {
    List<String> permissions = new ArrayList<>();
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
        permissions.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
    }
    if (!permissions.isEmpty()) {
        Toast.makeText(this, "Storage access needed to manage the picture.", Toast.LENGTH_LONG).show();
        String[] params = permissions.toArray(new String[permissions.size()]);
        ActivityCompat.requestPermissions(this, params, STORAGE);
    } else { // We already have permissions, so handle as normal
        takePicture();
    }
}

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    switch (requestCode) {
        case STORAGE:{
            Map<String, Integer> perms = new HashMap<>();
            // Initial
            perms.put(Manifest.permission.WRITE_EXTERNAL_STORAGE, PackageManager.PERMISSION_GRANTED);
            // Fill with results
            for (int i = 0; i < permissions.length; i++)
                perms.put(permissions[i], grantResults[i]);
            // Check for WRITE_EXTERNAL_STORAGE
            Boolean storage = perms.get(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
            if (storage) {
                // permission was granted, yay!
                takePicture();
            } else {
                // Permission Denied
                Toast.makeText(this, "Storage permission is needed to analyse the picture.", Toast.LENGTH_LONG).show();
            }
        }
        default:
            break;
    }
}

public String dateToString(Date date, String format) {
    SimpleDateFormat df = new SimpleDateFormat(format, Locale.getDefault());

    return df.format(date);
}

public void takePicture() {
    // Use a folder to store all results
    File folder = new File(Environment.getExternalStorageDirectory() + "/OpenALPR/");
    if (!folder.exists()) {
        folder.mkdir();
    }

    // Generate the path for the next photo
    String name = dateToString(new Date(), "yyyy-MM-dd-hh-mm-ss");
    destination = new File(folder, name + ".jpg");

    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(destination));
    startActivityForResult(intent, REQUEST_IMAGE);
}

@Override
protected void onResume() {
    super.onResume();
    if (destination != null) {// Picasso does not seem to have an issue with a null value, but to be safe
        Picasso.with(MainActivity.this).load(destination).fit().centerCrop().into(imageView);
    }
}

}`

What could be the problem? Thanks.

SandroMachado commented 7 years ago

Hi @mehmetdniz

Try to disable the InstantRun feature and please let me know if it works.

Regards

denizme commented 7 years ago

Hi @SandroMachado

Thank you for your interest. I solved the problem, but I have another problem. I want to reduce the processing time. Average reading speed 2 seconds, I want to read 1 second.

screenshot

SandroMachado commented 7 years ago

@mehmetdniz unfortunately that is not possible without changing the open alpr binary or improving the hardware.