[UPDATE]
I uninstalled and then installed again the application on the test device, and it started working fine.
I'm implementing APK Expansion file support (but no XAPK ZIP library support).
The documentation implies that if a required APK Expansion file is missing (e.g. it got deleted from the obb folder), my application will re-download it. This doesn't happen for me; my app keeps saying NO_DOWNLOAD_REQUIRED. It seems that the Google Play Downloader Library gets null for the download info from its SQLite database. Note that I haven't updated the draft APK and Expansion file on Google Play - they are still the first version. Moreover, the versionCode of the APK uploaded to Google Play is also identical with the one on the test device.
In details:
There was an APK Expansion file in the correct folder (obb). I used it for testing purposes before I actually started implementing the downloader functionality.
When the Downloader implementation (based on Google Play Downloader Library) was finished, I changed the size of the above obb file to make it invalid for my app. Therefore, this makes my app call the startDownloadIfNeeded() method.
First, I ran my implementation without any files on Google Play. The response was, as I expected: "Download failed because the resources could not be found"
Then I uploaded my 40MB APK and a 4 MB expansion file to Google Play (for testing purposes). Note that this 4 MB expansion file is not the invalid one which was left in the obb folder. When I ran my implementation, the response came after 1.5 seconds: "Download complete".
This was strange, because my internet connection is not so fast to download 4 MB. Indeed, the obb folder (the folder for APK Expansion files) still contained the invalid expansion file that I initially put there manually. That is, nothing was downloaded!
I deleted the invalid file, i.e. the obb folder is now empty, but still no download starts, and Downloader Library says NO_DOWNLOAD_REQUIRED. (I checked its internal implementation: when it queries an SQLite database for download info, it gets null after the query.)
I just read on SO somewhere that the APK Expansion files uploaded to Google Play require a few hours to take effect. In my case, I tested my implementation immediately after upload. But it must have noticed that there are files on Google Play, because instead of "resources could not be found", it gave a different message ("Download completed"). Too bad that it didn't actually download anything; and since then, it doesn't even try to (it keeps returning NO_DOWNLOAD_REQUIRED).
What am I missing?
Shouldn't the Downloader Library notice if an APK Expansion file gets deleted? Its implementation seems to deal with this, but only if the SQLite database query returns non-null for downloadable files.
The relevant part of internal implementation of Google Play Downloader Library (the last comment is mine):
int status = NO_DOWNLOAD_REQUIRED;
// the database automatically reads the metadata for version code
// and download status when the instance is created
DownloadsDB db = DownloadsDB.getDB(context);
// we need to update the LVL check and get a successful status to
// proceed
if (isLVLCheckRequired(db, pi)) {
status = LVL_CHECK_REQUIRED;
}
// we don't have to update LVL. do we still have a download to start?
if (db.mStatus == 0) {
DownloadInfo[] infos = db.getDownloads();
if (null != infos) {
for (DownloadInfo info : infos) {
if (!Helpers.doesFileExist(context, info.mFileName, info.mTotalBytes, true)) {
status = DOWNLOAD_REQUIRED;
db.updateStatus(-1);
break;
}
}
}
/// <----- This is when infos==null, in this case result will be NO_DOWNLOAD_REQUIRED
} else {
status = DOWNLOAD_REQUIRED;
}
If you encounter the same issue, uninstall the application, and then install it again. (Don't let Eclipse reinstall it in the usual way. Uninstall it completely from the device, manually.)
Related
My app has already been signed and notarized successfully, but I got this error while trying to launch the app:
"jna7223640233751603426.tmp" cannot be opened because the developer cannot be verified
Does anybody have the solution for this?
How can I fix this problem? Can I block the file created while launching the app or make it valid for the Gatekeeper?
JNA releases have small precompiled binary JARs for each of its supported operating system/architecture combinations. These are not signed, although the source code is available if you wish to build and sign them yourself.
From a conversation on the JNA mailing list:
MacOS does not allow code created at runtime (which is typical malware behaviour), and that extracting a library at runtime looks like that code was created because it’s not visible outside the jar file in which it came.
A solution listed in that thread is:
by pre-extracting the library and bundling it as part of the installer.
In addition to this, you'll need to configure your application to tell JNA not to extract its own library but to use the one which you have signed and extracted as part of your installer. Source code from the above email thread:
boolean sandboxed = System.getenv("APP_SANDBOX_CONTAINER_ID") != null;
// Some 3rd party apps install to the system and can cause crashes
System.setProperty("jna.nosys", "true");
if(sandboxed) {
// Don't unpack the libraries
System.setProperty("jna.nounpack", "true");
// Tell JNA where the native libraries are
System.setProperty("jna.boot.library.path", "<path to native libs>");
}
I'm working on a custom AOSP 8.1 based OS. I have a system app (in /system/priv-app) with an exported broadcast receiver. This means it can accept Intents from outside the application. If I refactor the broadcast receiver, e.g. change its package location or class name and install the updated APK with "adb install -r ...", everything works great and the broadcast receiver receives the intent.
However if I produce an OTP image with the new app (APK + VDEX + ODEX) and flash it from the recovery, the app crashes as Android is still trying to reference the old broadcast receiver class:
AndroidRuntime: java.lang.RuntimeException: Unable to instantiate receiver com.example.app.receiver.ExampleReceiver: java.lang.ClassNotFoundException: Didn't find class "com.example.app.receiver.ExampleReceiver" on path: DexPathList[[zip file "/system/priv-app/ExampleApp/ExampleApp.apk"],nativeLibraryDirectories=[/system/priv-app/ExampleApp/lib/arm, /system/lib, /vendor/lib, /system/lib, /vendor/lib]]
It tries to reference com.example.app.receiver.ExampleReceiver, but the new class is com.example.app.receiver.NewReceiver. The old one is "cached" somewhere.
I can simulate the same problem by remounting the /system partition RW and using adb push ... to replace the new APK, ODEX and VDEX files. Strange enough if I delete the ODEX and VDEX files from /system, everything works great as apparently this act forces Android to parse again the APK.
As I understand the PackageManager system app should be able to detect when an app is updated and parse the exported parts (like classes for broadcast receivers and activities). Unfortunately this doesn't happen.
I also guess that's what happens after OTA when Android shows "Optimizing app xxx/xxx", but this doesn't happen here. How is this process supposed to be triggered?
Relevant information: http://www.programmersought.com/article/8031444654/
Android sourcecode for PackageManagerService has following lines:
mIsUpgrade = !Build.FINGERPRINT.equals(ver.fingerprint);
... some other code
if (mIsUpgrade && !onlyCore) {
Slog.i(TAG, "Build fingerprint changed; clearing code caches");
... cache clearing logic
ver.fingerprint = Build.FINGERPRINT;
}
That is, code caches will be cleared if build fingerprint is changed. This problem might occur because your OTA package has same fingerprint as the system it is installed on.
Check your makefile and make sure you are generating a unique fingerprint for each build.
Fingerprint value can be found in "system/buildprops" file. So you can check if that is the problem.
I am trying to get access to a text file (log.txt) in a directory. All other questions on this topic refer to getting directories from the emulators internal storage.
My file structure is as such
>androidApp
->App
-->Build
-->src
--->game_log
---->log.txt
--->Main
---->(Android app Code further)
Using new File(System.getProperty("user.dir) + "app\\src\\game_log\\log.txt").exists() gets me false.
Another thing I tried was System.getProperty("user.dir") but that yields me /.
Contextwrapper.getPath() gets me the path of the emulators storage.
Is the file structure of Android Studio different or I am using the wrong method to get the file from my project folder?
I am trying to deploy R Shiny App as an Windows Desktop App. So far I have used the framework described at http://blog.analytixware.com/2014/03/packaging-your-shiny-app-as-windows.html and managed to make it work with the help of stackoverflow users (question name "R Shiny as Windows Desktop App Creates Text File With Warning").
An update to this framework has been developed and it has several advantages over the previous one, such as not relying on Google Chrome browser etc. and it is described here: http://oddhypothesis.blogspot.com/2016/04/desktop-deployr.html
All files can be found in the GitHub account of framework creator (link is presented in the description)
I have adjusted the following:
app.R
require(shinyjs,quietly = TRUE,warn.conflicts=FALSE)
require(markdown,quietly = TRUE,warn.conflicts=FALSE)
require(scales,quietly = TRUE,warn.conflicts=FALSE)
require(DT,quietly = TRUE,warn.conflicts=FALSE)
runApp("./app/shiny/", launch.browser=TRUE,quiet=TRUE)
packages.txt
Added the names of the packages I am using
# Primary package dependencies for the application that are loaded during
# startup.
#
# If not available, they will be installed into app/library. Custom source
# packages need to be installed manually.
# bare miniminum: configurations are stored in json format
jsonlite
# if deploying shiny based applications:
shiny
shinyjs
markdown
scales
DT
App does launch, it works. However a new folder is created called log with file error.log, which includes the following:
library paths:
... C:/Users/VoronecI/Desktop/New folder (2)/app/library
... C:/Users/VoronecI/Desktop/New folder (2)/dist/R-Portable/App/R-Portable/library
working path:
... C:/Users/VoronecI/Desktop/New folder (2)
Loading required package: methods
ensuring packages: jsonlite, shiny, shinyjs, markdown, scales, DT
Attaching package: 'shiny'
The following object is masked from 'package:jsonlite':
validate
Attaching package: 'shinyjs'
The following object is masked from 'package:shiny':
runExample
The following objects are masked from 'package:methods':
removeClass, show
Attaching package: 'DT'
The following objects are masked from 'package:shiny':
dataTableOutput, renderDataTable
Is there a way to prevent this logging of the unmeaningful error?
The reason why I want to get rid of it is because I further use Inno Setup Compiler to create .exe and this is not working when I have a log file updating each time I run the app.
As you can see in this file (line 66) https://github.com/wleepang/DesktopDeployR/blob/7c81e72c5beb29bf84ca65fd1d5bb5486caec51a/dist/script/wsf/js/run.js
The command is run as
var strCommand = [Rexe, Ropts, RScriptFile, "1>", Outfile, "2>&1"].join(" ");
which redirects command line outputs (that normally directly print to the screen) to the Outfile. You can change this line to
var strCommand = [Rexe, Ropts, RScriptFile].join(" ");
which will disable the logging. This might have other implications though (you might see a command window for example, I am not too sure but test it out).
Alternatively, you might be able to change this file https://github.com/wleepang/DesktopDeployR/blob/7c81e72c5beb29bf84ca65fd1d5bb5486caec51a/app/config.cfg (line 27) and set
- use_userprofile: true
(you need to uncomment this line, it is currently inside a block comment). This will make sure the log file goes into the user profile folder, and that might also solve your problem.
Ivona, I just finished developing the RInno package which also uses Inno Setup and the DesktopDeployR project to install local Shiny apps, and it will log errors without a problem.
To get started:
install.packages("RInno")
require(RInno)
RInno::install_inno()
Then you just need to call two functions to create an installation framework:
create_app(app_name = "myapp", app_dir = "path/to/myapp")
compile_iss()
If you are interested in other features, check out FI Labs - RInno. I'd be interested to know if turning off the error logging feature is something you would like to add ;)
I am trying to save a file to my SDcard on my Samsung Galaxy Nexus running 4.2.2. From my app I am using
Environment.getExternalStorageDirectory()
But it returns
/storage/emulated/0/
Which is not where my SDcard information is located to. Is there any working method I can use to get the correct path to my SDcard?
Actually, that is the correct location.
From android 4,2 onwards, Google introduced multiple user accounts. Every user has his/her own external storage, which has the user ID in the path to maintain uniqueness.
The primary (default) user's ID is 0. So you get /storage/emulated/0/ as the path to the external storage.
I just learned this is the Jelly Bean's way of dealing with the lack of android.permission.WRITE_EXTERNAL_STORAGE permission. I haven't seen such a behavior with older versions of Android.
Just add this line to your AndroidManifest.xml:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Environment.getExternalStorageDirectory() refers to whatever the device manufacturer considered to be "external storage". I can be something else than the SD-card.
You may get more informations here: Find an external SD card location
I think its because of using genymotion emulator,
the path is true and in Eclipse it locates at
File Explorer - > mnt - > shell - > emulated -> 0
hope it helps ;)
Sure? Where do you think your sdcard is mounted? Try doing ls -l on that directory – it's probably a symlink to /storage/emulated/0/.
I had somehow lost my symlink at /storage/emulated/0, causing a similar failure. What I did was use the camera app to take a picture. I observed that the pictures details said it was within /storage/emulated/0, though that directory did not exist from the file explorer. Then I rebooted the phone. After reboot the link existed.
Try to use getExternalFilesDir() or getExternalStoragePublicDirectory().
From Android 4.2 documentation