I want to use open alpr (automatic licences plate recognition) library in my android project. I compiled everything successfully and now it is time to use open alpr in app but...
to create Alpr class object properly I have to provide path to config file and path to runtime_data folder which contains some mandatory files needed by open alpr (ocr and trained data).
I tried something like:
Alpr alpr = new Alpr("eu", "android_assets/alpr.conf", "android_assets/runtime_data");
but Alpr.isLoaded() returns false which means that config or runtime_data have not been found.
Path to assets folder in project is: src/main/assets.
Can someone explain to me how path to "runtime_data" directory and "alpr.conf"
should looks to be visible by open alpr?
Thanks in advance.
I am not familiar with the specific library, but on newer Android devices (Android 6 and up), you can not rely on your application files residing under /data/data/your.package.name
The actual library name still includes the package name of your app, but also has some identifier appended to it in base64 format.
This identifier is unique per installation, and it will change if you uninstall and reinstall the app on the same device.
So, if your library needs to use a configuration file with a path to some other files, there are 2 options:
The right way:
Get the real address of your application files folder using Context.getFilesDir().
Unpack you files from the assets folder of the APK on the device using AssetManager.
Programmatically rewrite your configuration file with the path returned by getFilesDir().
The "hacky" but simpler way:
Use public storage to unpack your files.
You will need to add WRITE_EXTERNAL_STORAGE permission to your app, and unpack the assets files to the external storage.
For backwards compatibility this will be available under /sdcard folder on most Android devices, even with the latest Android version.
The second method is not recommended since using /sdcard directly is deprecated and strongly discouraged by Google.
Also, not all Android devices have /sdcard link to their public storage, but this is the only way to avoid dynamically editing the configuration file after installation.
Important note before you start implementing those steps. This library supports only arm CPU architecture. Good news is, most probably, your physical device is using arm architecture but to make sure just double-check it before implemting those steps.
I've recompiled this library to a new wrapper library. In original library, you need to manually configure openalpr.conf file and edit its content with correct path to your data directory. Manual configuration is cumbersome because since Android 5 multiple user accounts is supported and we can't simply hardcode data directory as /data/data/com.your.packagename/..... Because every user gets their symlink to data directory as /data/user/0/com.your.packagename/..... All those manual steps are gone in recompiled wrapper library.
Implementation
Add this in your root build.gradle at the end of repositories:
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
Add the dependency into app module:
dependencies {
...
implementation 'com.github.mecoFarid:openalpr:1.0.0'
}
And you're done. Please check this sample app to get started with UI.
Troubleshooting:
If your target sdk is targetSdkVersion >= 24 and you're running your app on a device with Android API 24+ you'll get following error:
android.os.FileUriExposedException: file:///storage/emulated/0/OpenALPR/2019-09-21-01-32-13.jpg exposed beyond app through ClipData.Item.getUri()
To solve this error: you can add following lines into onCreate() of your Activity as a workaround or you may use this thread for offical solution:
if(Build.VERSION.SDK_INT>=24){
try{
Method m = StrictMode.class.getMethod("disableDeathOnFileUriExposure");
m.invoke(null);
}catch(Exception e){
e.printStackTrace();
}
}
TEST:
You can use this image to test your app.
"/data/data/yourpackagename" + File.separatorChar + "runtime_data"
+ File.separatorChar + "openalpr.conf";
Related
I want to know the correct steps to keep local saved data after app update.
I confirmed the following old question, but I can't solve the issue.
Save app data in kivy on Android
I tried the following.
1-1:I made android APK with buildozer(command:buildozer android debug). 1-2:And execute 'store.put' method using 'kivy.storage'. then 'hello.json' file was created in the './' directory.
https://kivy.org/doc/stable/api-kivy.storage.html
1-1:'./' directory in APK ver.1
main.pyo
1-2:'./' directory in APK ver.1
main.pyo, hello.json(created)
2-1:I made android APK ver.2(same app name as 1.APK). 2-2:After installing in update mode, execute only 'store.get' method using 'kivy.storage'. then method failed because 'hello.json' file was automatically deleted with app update.
2-1:'./' directory in APK ver.2
main.pyo(changed from APK ver.1)
2-2:'./' directory in updated APK
main.pyo(ver.2)
I tried changing the output location of the 'hello.json' file but it made no sense.
e.g. './data/data/[app_name]/files/hello.json' and './data/data/[app_name]/shared_prefs/hello.json'
How can I update my application?
Everything in the default current directory, which is named app, is deleted and replaced on app update. You can place persistent data in the directory above this, i.e. ../, and it should stick around between updates.
You can also use your app's external storage directory, using pyjnius to query the Android API for its location, but I don't have code for that right now.
This isn't especially well documented, I'll try to improve it.
I am trying to generate source maps in the Gradle build process of a React Native app and read the source map file in the application.
I used this project as a starting point: https://github.com/philipshurpik/react-native-source-maps
I didn't succeed in including it as it is, so I tried to take and modify parts of it.
In app/gradle.build I added:
project.ext.react = [
extraPackagerArgs: ["--sourcemap-output", "$buildDir/intermediates/assets/release/index.map"]
]
and indeed when I'm running the release build I see the file index.map under android/app/build/intermediates/assets/release , but when I deploy the APK to a device or emulator, I can't see this file anywhere in Android's filesystem. For that matter, I also can't see the bundle file or any files that were in android/app/src/main/assets and I do see in android/app/build/intermediates/assets/release after build.
The application code uses https://github.com/itinance/react-native-fs to read the file. This is how I first check if the file exists:
const fileExists = await RNFS.existsAssets(`${RNFS.DocumentDirectoryPath}/index.map`)
and the file doesn't exist there. RNFS.DocumentDirectoryPath returns /data/user/0/mypackagename/files , which is empty when I check (using adb shell with root access).
What am I missing? How do I get the source map file to a location which will be available to the application to read?
Turned out the gradle.build part was fine, and in order to read the source map file I needed to use just the file name, like so: RNFS.existsAssets('index.map')
I'm trying to include an extension in a custom build of Firefox for Android (Fennec) so that when the user installs the APK, the Fennec browser already has the extension installed.
I'm using a baseline of Fennec v48.0b6. It might be worth drawing attention to the fact that this is beta build, although I don't expect it should make a difference.
The simple way this should work
Documentation for such a process does seem to exist but I'm having trouble getting it to work. The Mozilla Wiki has a guide to this. It, and other hints surrounding the solution I've found, indicate that I need a 'distribution' folder somewhere in the Firefox workspace. I have a folder structure as follows:
firefox-48.0b6
custom-dist
assets
distribution
preferences.json
extensions
my-extension.xpi
where 'firefox-48.0b6' is the root folder containing all of the source directories such as b2g, browser, chrome, mobile, and so on. This matches the sample directory structure provided by Mozilla.
I've added the following line to my mozconfig:
ac_add_options --with-android-distribution-directory="/data/workspaces/firefox/firefox-48.0b6/custom-dist"
which correctly tracks the absolute distribution location. If this path doesn't point to a distribution then I get an error when I run mach configure, so it must be being read.
The extension's XPI name needs to match the ID (as indicated on the same Mozilla Wiki page) given in the extension's install.rdf file. I've changed the install.rdf file and the XPI name so that they match.
Having done all of this I still don't see my extension in the list of add-ons when I install the APK.
What I've done to try to get this to work
I've tried a few additional things (none of which have solved my problem):
Changing the MOZ_ANDROID_PACKAGE_INSTALL_BOUNCER flag to False in mobile/android/moz.configure. This is mentioned in the Mozilla Wiki. Bugzilla seems to indicate that there is a bug still present in this version so this is probably not worth further enquiry.
Having read the comments (specifically comment 2) on the linked bug from the above point, I've tried setting changing the MOZ_ANDROID_PACKAGE_INSTALL_BOUNCER=1 to MOZ_ANDROID_PACKAGE_INSTALL_BOUNCER= in mobile/android/confvars.sh so that it's not read as a truthy value.
I've tried deleting MOZ_ANDROID_PACKAGE_INSTALL_BOUNCER from confvars.sh altogether.
Tried putting the distribution folder into objdir-droid/dist/bin as indicated in this StackOverflow question and answer. It's notable that this is not mentioned on the Mozilla Wiki. From this Bugzilla bug report it looks like it relates to an old method of doing things.
Where I'm stuck
Ultimately, I still don't have a build of Firefox for Android that has the extension included by default. There are a couple of points that might be the source of the problem, but I don't know enough about the process to say for sure, namely:
I'm using a beta build of Firefox for Android as my baseline. Will this cause problems for the purposes of including a distribution?
I push the APK directly to /system/priv-app rather than installing it (either within the Android OS itself or by using adb install). Does this make a difference as to whether the distribution is applied?
What have I missed that will get this working?
Edit
I've since realised that I also need a minimal preferences.json file in the distribution directory. However, including this hasn't solved the problem...
I have the same problem with you.
After extracting the apk file into a folder, I found that my xpi file is not included.
Maybe there is a bug related to fennec packaging scripts about option "--with-android-distribution-directory"? Maybe dig more into the scripts implementation is another choice. Also we can try to install the xpi ourselves by referencing the following js script which is implemented in fennec:
mozilla-central/mobile/android/chrome/content/browser.js
installDistroAddons: Task.async(function* () {
const PREF_ADDONS_INSTALLED = "distribution.addonsInstalled";
try {
let installed = Services.prefs.getBoolPref(PREF_ADDONS_INSTALLED);
if (installed) {
return;
}
} catch (e) {
Services.prefs.setBoolPref(PREF_ADDONS_INSTALLED, true);
}
let distroPath;
try {
distroPath = FileUtils.getDir("XREAppDist", ["extensions"]).path;
let info = yield OS.File.stat(distroPath);
if (!info.isDir) {
return;
}
} catch (e) {
return;
}
let it = new OS.File.DirectoryIterator(distroPath);
try {
yield it.forEach(entry => {
// Only support extensions that are zipped in .xpi files.
if (entry.isDir || !entry.name.endsWith(".xpi")) {
dump("Ignoring distribution add-on that isn't an XPI: " + entry.path);
return;
}
new Promise((resolve, reject) => {
AddonManager.getInstallForFile(new FileUtils.File(entry.path), resolve);
}).then(install => {
let id = entry.name.substring(0, entry.name.length - 4);
if (install.addon.id !== id) {
Cu.reportError("File entry " + entry.path + " contains an add-on with an incorrect ID");
return;
}
this.pendingAddonInstalls.add(install);
install.install();
}).catch(e => {
Cu.reportError("Error installing distribution add-on: " + entry.path + ": " + e);
});
});
} finally {
it.close();
}
})
I know that the IceCat mobile browser for Android is such a derivative that includes preinstalled extensions. Keep in mind that they're based on the ESR channel so you might need to mess with their build scripts a bit, but I'd take a look at their implementation. Here's the project page:
https://www.gnu.org/software/gnuzilla/
If that's no good then maybe take a look at the TOR firefox distribution (I'm pretty sure they include noscript by default).
I'm using ruboto (ruby) on an android tablet. I'd like my source to be in a subdirectory of the usual default source directory. Is there a way to do this?
You have not stated your motivation for placing the Ruby source in a subdirectory, so I'll speculate that it is for tidiness in a polyglot environment. Also, I'll assume you want all the Ruby source in the same directory, including source for Activity classes.
Adding your path to both the Ruby $LOAD_PATH and the Android component search path has been combined into one method in org.ruboto.JRubyAdapter.addLoadPath. In JRubyAdapter.setUpJRuby, you can find a call to addLoadPath around line 289: https://github.com/ruboto/ruboto/blob/1.4.0/assets/src/org/ruboto/JRubyAdapter.java#L289
You can add your own call below the existing one:
addLoadPath("file:" + apkName + "!/<your_path_here>")
That will add the path to the Ruby load path and the Android component search path.
If you have a clear use case, I would submit it to the Ruboto tracker at https://github.com/ruboto/ruboto/issues . It sounds like something more Ruboto developers could use.
This code works in the simulator but not on my Android device:
local path = system.pathForFile("chinese_rules.db")
print("PATH:: " .. tostring( path ) )
When I run this code on my Galaxy S4 path returns nil.
My first thought was that it was some typo (case sensitivity) but I can't find any typo:
http://i59.tinypic.com/wlpu14.png
I can't find any reason why it should receive nil. This causes a problem as I can't load my database.
I have also tried this with the same result:
local path = system.pathForFile("chinese_rules.db", system.ResourceDirectory)
I have been able to load a path and load databases like this before.
Corona Build: 2013.2100 (2013.12.7)
Further reading the documentation I don't see that .db is a restricted file type:
Corona allows direct loading of images and audio files using the
appropriate APIs, but it has limited access to resource files on
Android using the file I/O APIs. Specifically, the following types can
not be read from the resources directory: .html, .htm., .3gp, .m4v,
.mp4,.png, .jpg, and .ttf.
http://docs.coronalabs.com/api/library/system/pathForFile.html
I found out the reason for the problem:
We are two that are working on this project and he had setup to use expansion files so two files was created (the main APK and the OBB expansion file) which I didn't notice and I only loaded the main APK file and I guess the database is in the OBB file. After setting not to use an expansion file the app works.
usesExpansionFile = false