-
Notifications
You must be signed in to change notification settings - Fork 16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: Fix ApkInstaller for Android <7 (SDK version <24) #586
Conversation
FYI the changes to the Java code here are mainly copied from F-Droid from:
I also borrowed some code from https://github.com/mikehardy/react-native-update-apk |
Great job @gmaclennan, it's working now! I was going to point out the code for installing apk from react-native-send-intent, but you handled it. I suppose we're just missing:
|
482775d
to
e09cbe0
Compare
rebased on
@luandro not sure what you mean. I added logging intentionally for any errors. I think it should be left in.
This is already here - the permission change only happens if I think this is good to merge, do you agree @luandro? |
The logging makes sense @gmaclennan. I was reading the |
🚀 |
* Add AppInfo native module for accessing sourceDir * Add share sheet for sharing Mapeo APK * Test auto-updating app from an APK * Test reading package signatures * Prep APK for sharing and start upgrade server. * get correct mapeo app version + show on settings * remove old comments * implement upgrade storage module * prevent 'filename' from being exposed on upgrades * add createReadStream API to stream upgrade data * chore: add eslint linting * test: move fake.apk to static/ subdir * test: formatting * fix: make 'arch' an array of strings * chore: add 'test' npm script * add initial UpgradeServer implementation * add new UpgradeServer implementation * test: add edge case tests for upgrade server * move the upgrade discovery key to its own file * have UpgradeServer accept a port to advertise on * make UpgradeStorage#getAvailableUpgrades sync * refactor: consolidate apk->upgradeoption logic * Revert "make UpgradeStorage#getAvailableUpgrades sync" This reverts commit 2b4e3ac. * refactor: use a file for downloaded upgrade info * refactor: move LocalUpgradeInfo into a nodule * refactor: rename createApkWriteStream * add work-in-progress UpgradeDownloader component * chore: lint * add download progress tracking to state * implement the UpgradeDownloader checker component * chore: cleanup * implement the UpgradeManager * fix: ignore non-mapeo app keys * chore: add eslintrc for backend * don't access UpgradeDownloader's internals * auto-download upgrades that UpgradeManager finds * chore: lint * UpgradeDownload doesn't need version/arch/etc args * fix bugs in case where server waits to shut down * upgrade-server runs its own http server * expose 'startTime' context for upgrade searches * chore: upgrade deps * p2p-upgrades: pass in version to storage * wip: integrate upgrademanager into server * chore: add missing dep from develop * workaround for github:#521 * wip: fixes * test: lint * fix: be able to listen for multiple ready events * add upload info to sharing state * DotIndicator: accept optional size parameter * wip: frontend implementation * move upgrade state constants to a common module * backend: upgrade simulator tool * implement upgrade state validation module * use a common storage path for downloaded APKs * expose filename property from upgrade-storage api * clone upgrade state context when modifying * add more thorough upgrade state management * fix: expose upgrade filename instead of hash * add more thorough state mgmt to upgrade-server * add more upgrade state mgmnt to upgrade-manager * wip: variety of frontend implementation upgrade changes * prevent older APKs from trying to be installed * simplify frontend state handling of upgrades * add another effect to track peer + upgrade state * test: fixes * test: files aren't left over after write error * feat: check hash upon upgrade download + cleanup * storage: use a temp dir for in-progress downloads * p2p-upgrades: make logging prefixes consistent * lint * add debug logging to upgrade backend * fix: write completed upgrade to root storage dir * Internationalization example * fix(upgrade): remove TTL; re-announce regularly * Update src/backend/lib/local-upgrade-info.js Co-authored-by: Gregor MacLennan <[email protected]> * fix: readd flipper code (merge issue) * use strings for upgrade state constants * Internationalize text in update bar * Remove unused import * chore(linting): Combine duplicate imports * chore(linting): Remove unreachable code * Extract messages for translation * java: add missing import * fix: prevent redownload of locally-stored upgrades * do not copy the APK; use privateStorage instead * add optional param to upgrade simulator * chore: fix line-endings for gradlew.bat (should be CRLF) * feat: Add minSdkVersion to AppInfo interface * chore: Add context to backend status errors * chore: Remove unused "flavor" option in createServer * chore: Don't try to support multiple "config" RPC messages We wait for the config RPC message to start the server. This code would try to restart the server with new config, but we don't have a use for that and it makes the code a lot more complicated to manage, so I'm removing it for now - it was not tested anyway and probably did not work * feat: Pass apkPath, minSdkVersion etc. to createServer() apkPath: Path to currently running APK (file can be read from nodejs) minSdkVersion: Min Android SDK version supported by currently running APK version: Version name of running APK (semver if release, but not if testing) buildNumber: Increments every time CI build happens - must always increase bundleId: Different variants have different bundleIds - com.mapeo - com.mapeo.qa - com.mapeo.debug - com.mapeo.icca Different bundle ids install as separate apps * chore: have UpgradeManager expose functions instead of events and ajust tests * Revert "Test reading package signatures" This reverts commit 28271b1. * Remove redundant keys from backend setup Co-authored-by: Gregor MacLennan <[email protected]> * remove unused error handling * Fix naming of apkVersion * Opt-in setting for p2p upgrades (#561) * chore: cleanup old items in settings * chore: add messages for experiments * feat: Add Experiments page, route and state to SettingsContext * feat: Only start p2p-upgrade if enabled on settings * chore: Remove redundant code * Add experimental flag to useEffect deps Without this the useEffect will not run if this value changes * fix: boolean type is lowercase * Change shape of settings context We plan to use this for other features in the future, so adding `experiments` as a property on settingsContext. * Set test IDs Co-authored-by: Gregor MacLennan <[email protected]> * fix: Don't copy src/backend/test/fake.apk as part of CI Gradle build * Update backend build script to only copy whitelisted files The backend build script uses noderify to bundle JS into a single file. Previously the script would then blacklist unnecessary files to delete them from the packaged app, but that is a maintenance burden. This change whitelists the necessary files that must be included in the APK and only includes those. * fix: use correct variable names * chore: Run backend tests on CI (#577) * chore: Run backend tests on CI * chore: Run backend tests in parallel with e2e tests * fix(AppInfo): Remove minSdkVersion This property is only available in Android API 24 and later (Android v7) We planned to use it to check compatibility incase our supported minSdkVersion increased (it is currently API 20). Since this is not available in phones we support, it is not useful for this purpose, and using it causes a crash on phones running Android <v7 * Revert "fix: use correct variable names" This reverts commit 4526fba. Variable names were already corrected in 5709722 * Add integration with server.js * Fix upgrade simulator for new upgrademanager pattern * Update settings store key for new settings shape This will cause anyone who has used the "Coordinate format" setting to loose their chosen format, but we have not released that yet. For the next time we update the settings that are persisted, we need a way to migrate old settings, because leaving this at @1 broke my phone, because it had stored settings that did not have the experiments option. * Remove changes that should not be in this PR * chore: Fix backend tests CI * fix: upgrade semver sorting * fix: add upgrade options listener only once * fix: check for upgrades after current d/l finishes * fix: prioritize Downloading over ReadyToUpgrade * fix: reset upgrade state on download completion * fix: remove extra setState; fix param on a setState * fix: remove setState(IDLE) on error * test: fixes These are some fixes re: recent changes to the upgrade state machines that needed correction in the tests. These fixes are pretty hacky, but I didn't feel it made sense to invest time into rewriting them right now. * fix: don't show search:IDLE as an error state This is normal behaviour: the frontend will generally do a 'get-state' request before search has initialized, revealing it as IDLE. * fix: remove DOWNLOADED upgrade state * clean up UpgradeManager download logic * remove unused code * allow UpgradeCheck to re-check + choose latest version * fix: Fix tests (maybe?) * fix: Fix ApkInstaller for Android <7 (SDK version <24) (#586) * fix: Throttle upload/download progress events to 100ms * Fix lint issues * fix: Throttle progress events to every 400ms * s/PROGRESS_THROTTLE/PROGRESS_THROTTLE_MS * remove obsolete comment * Use same node as nodejs-mobile * WIP: Refactor in Typscript * upgrade-storage tests & fixes * rename state type * Fix upgrade candidate check for device.supportedAbis * fix storage test * Remove hardcoded filepaths from expected APK info * fix beforeAfterStream tests * UpgradeServer tests & corresponding fixes * Additional tests for trying to write invalid APKs (no uncaught error) * fix: Don't query a peer if a request to that peer is already in progress * Add UpgradeDiscovery test & fixes (just one test for now, more coming later) * delete upgrade-download.js (delete was lost in rebase) * Discovery test for peer going offline * oops, remove test.only() * Update Node version for CI tests (use same as nodejs-mobile) * Finish UpgradeDiscovery tests * Fix for backend build scripts * properly fix backend build scripts this time * Fix typo in comment * Fix: once() on error Co-authored-by: Kira Oakley <[email protected]> * fix: Add tests from duplexify * Fix for error state of AsyncService * Add test to ensure different discovery keys do not find each other * fix: An installer with the same hash as current APK is not an upgrade * Fix: An installer < version of current APK is not an upgrade * fix: fake-apk-info should have same applicationId as valid APK fixtures * chore: Add initial upgrade manager integration test * fix: Don't download an upgrade candidate that we already have in storage * feat: Allow state emit throttle to be changed for testing * chore: rename var Co-authored-by: Kira Oakley <[email protected]> * chore: rename var * chore: fix typo in comment Co-authored-by: Kira Oakley <[email protected]> * fix: Remove incorrect setState in _stop() * chore: remove redundant dep * chore: rename function * chore: Comprehensive logging * chore: make all class fields private instance fields I was using `_name` for instance fields initialized in the constructor. This was not necessary. Changing all to `#name`. * chore: Additional APK fixtures for testing, and consistent naming scheme * chore: Setup UpgradeManager test scenarios * chore: integration tests for UpgradeManager * chore: remove old tests * chore: Ensure tmp folders created in tests are removed afterwards * chore: Double-check downloaded hash in UpgradeManager tests * chore: Simplify abi check code Co-authored-by: Kira Oakley <[email protected]> * chore: fix hash error message Co-authored-by: Kira Oakley <[email protected]> * fix: Remove test.only() * WIP integrate new UpgradeManager API with server.js and front-end Builds upon work in #574 * Add script to build APKs for testing p2p upgrades * Update Upgrade Simulator for new API * cleanup UpgradeBar code * Fix filepaths for share to switch to cache-path vs. files-path * fix: Fix upload progress * Allow upgrade bar to expand in height if needed * Change button text to "Install" from "Install update" due to space con.. ..straints * Don't show install button if there are active downloads / uploads * Add Mapeo version to wifi bar (above upgrade bar) * Create small button variant for use in upgrade bar * Add error icon for error state * Use normal weight text in upgrade bar * Cleanup unused imports * Turn off debug logging in production builds * chore: Reduce noise in adb logcat logs * fix: Don't debug log in production * fix: Wait for server to start before trying to start p2p-upgrades When starting the app directly to the sync screen the initial announce was not happening * fix: Don't query self for upgrades * Don't use fastify.inject() for tests - test with actual requests via got * fix: Ensure storage tests fail if expected throw does not happen * chore: use readJson from helpers * feat: Show "No app updates found" once at least one device is checked * Add explanation for unusual code in upgrade-simulator * feat: Use keep-alive to re-use same connection for upgrade check polling * Add test for download completing before server close * Add test for broken connection * Cleanup AsyncService code and fix bugs * fix: Don't throttle state events, only download progress The throttling seems to introduce race conditions in the tests (not all events that the tests wait for are guaranteed to fire). * Fix manager tests * Determine update candidate based on new version naming scheme (#596) * Remove debug logging on CI (was used for debugging test failure) * chore: Fix to backend build script * chore: Clean up logging code * Failing test for checkedPeers * fix: checkedPeers should only update after potential upgrades r checked * chore: typings for tests * failing test for checkedPeers reseting after stop,start * fix: Checked Peers should reset after start and stop * fix tests, stricter testing for empty arrays in state the lodash.isMatch function we are using will match an empty array against any array, so to check the state is an empty array, we need to use the compare function to strictly check the array length. * fix: Don't use same keep-alive connection for downloads and polling fixes #612 * Update upgrades QA build numbers * fix typo * Fix "Go to Map" button style for empty observation list screen * fix e2e debug test config (for local testing) * Increase server start timeout in attempt to fix e2e tests Co-authored-by: Kira Oakley <[email protected]> Co-authored-by: Kira Oakley <[email protected]> Co-authored-by: luandro <[email protected]> Co-authored-by: Kira Oakley <[email protected]>
Fixes #582
It turns out that for Android <7, the APK and any parent folders need to have their file permissions set be world-readable. E.g. we store the APK in
[INTERNAL_FILES_DIR]/installer/myApk.apk
. To be able to install this,myApk.apk
needs to be world-readable and theinstaller
folder needs to be world-executable.We could set these permissions when creating the
installer
folder, but since these permissions are only needed on Android <7 I think it's better to leave the folder with more restrictive permissions, and set the permissions in the Java code which only runs for Android <7.Ideally the Java code that sets permissions would set all parent folders up to
[INTERNAL_FILES_DIR]
to be world-executable, but my Java knowledge it not good enough, so for now it assumes the APK is in a folder one-level deep, e.g. it only sets permissions on the parent folder.@luandro can you test this on your phone and see if it now works as expected?