diff options
Diffstat (limited to 'static/src/_posts/2021-01-30-building-mobile-nebula.md')
-rw-r--r-- | static/src/_posts/2021-01-30-building-mobile-nebula.md | 390 |
1 files changed, 0 insertions, 390 deletions
diff --git a/static/src/_posts/2021-01-30-building-mobile-nebula.md b/static/src/_posts/2021-01-30-building-mobile-nebula.md deleted file mode 100644 index 0645e70..0000000 --- a/static/src/_posts/2021-01-30-building-mobile-nebula.md +++ /dev/null @@ -1,390 +0,0 @@ ---- -title: >- - Building Mobile Nebula -description: >- - Getting my hands dirty with Android development. -series: nebula -tags: tech ---- - -This post is going to be cheating a bit. I want to start working on adding DNS -resolver configuration to the [mobile nebula][mobile_nebula] app (if you don't -know nebula, [check it out][nebula], it's well worth knowing about), but I also -need to write a blog post for this week, so I'm combining the two exercises. -This post will essentially be my notes from my progress on today's task. - -(Protip: listen to [this][heilung] while following along to achieve the proper -open-source programming aesthetic.) - -The current mobile nebula app works very well, but it is lacking one major -feature: the ability to specify custom DNS resolvers. This is important because -I want to be able to access resources on my nebula network by their hostname, -not their IP. Android does everything in its power to make DNS configuration -impossible, and essentially the only way to actually accomplish this is by -specifying the DNS resolvers within the app. I go into more details about why -Android is broken [here][dns_issue]. - -## Setup - -Before I can make changes to the app I need to make sure I can correctly build -it in the first place, so that's the major task for today. The first step to -doing so is to install the project's dependencies. As described in the -[mobile_nebula][mobile_nebula] README, the dependencies are: - -- [`flutter`](https://flutter.dev/docs/get-started/install) -- [`gomobile`](https://godoc.org/golang.org/x/mobile/cmd/gomobile) -- [`android-studio`](https://developer.android.com/studio) -- [Enable NDK](https://developer.android.com/studio/projects/install-ndk) - -It should be noted that as of writing I haven't used any of these tools ever, -and have only done a small amount of android programming, probably 7 or 8 years -ago, so I'm going to have to walk the line between figuring out problems on the -fly and not having to completely learning these entire ecosystems; there's only -so many hours in a weekend, after all. - -I'm running [Archlinux][arch] so I install android-studio and flutter by -doing: - -```bash -yay -Sy android-studio flutter -``` - -And I install `gomobile`, according to its [documentation][gomobile] via: - -```bash -go get golang.org/x/mobile/cmd/gomobile -gomobile init -``` - -Now I startup android-studio and go through the setup wizard for it. I choose -standard setup because customized setup doesn't actually offer any interesting -options. Next android-studio spends approximately two lifetimes downloading -dependencies while my eyesight goes blurry because I'm drinking my coffee too -fast. - -It's annoying that I need to install these dependencies, especially -android-studio, in order to build this project. A future goal of mine is to nix -this whole thing up, and make a build pipeline where you can provide a full -nebula configuration file and it outputs a custom APK file for that specific -config; zero configuration required at runtime. This will be useful for -lazy/non-technical users who want to be part of the nebula network. - -Once android-studio starts up I'm not quite done yet: there's still the NDK -which must be enabled. The instructions given by the link in -[mobile_nebula][mobile_nebula]'s README explain doing this pretty well, but it's -important to install the specific version indicated in the mobile_nebula repo -(`21.0.6113669` at time of writing). Only another 1GB of dependency downloading -to go.... - -While waiting for the NDK to download I run `flutter doctor` to make sure -flutter is working, and it gives me some permissions errors. [This blog -post][flutter_blog] gives some tips on setting up, and after running the -following... - -```bash -sudo groupadd flutterusers -sudo gpasswd -a $USER flutterusers -sudo chown -R :flutterusers /opt/flutter -sudo chmod -R g+w /opt/flutter/ -newgrp flutterusers -``` - -... I'm able to run `flutter doctor`. It gives the following output: - -``` -[✓] Flutter (Channel stable, 1.22.6, on Linux, locale en_US.UTF-8) - -[!] Android toolchain - develop for Android devices (Android SDK version 30.0.3) - ✗ Android licenses not accepted. To resolve this, run: flutter doctor --android-licenses -[!] Android Studio - ✗ Flutter plugin not installed; this adds Flutter specific functionality. - ✗ Dart plugin not installed; this adds Dart specific functionality. -[!] Connected device - ! No devices available - -! Doctor found issues in 3 categories. -``` - -The first issue is easily solved as per the instructions given. The second is -solved by finding the plugin manager in android-studio and installing the -flutter plugin (which installs the dart plugin as a dependency, we call that a -twofer). - -After installing the plugin the doctor command still complains about not finding -the plugins, but the above mentioned blog post indicates to me that this is -expected. It's comforting to know that the problems indicated by the doctor may -or may not be real problems. - -The [blog post][flutter_blog] also indicates that I need `openjdk-8` installed, -so I do: - -```bash -yay -S jdk8-openjdk -``` - -And use the `archlinux-java` command to confirm that that is indeed the default -version for my shell. The [mobile_nebula][mobile_nebula] helpfully expects an -`env.sh` file to exist in the root, so if openjdk-8 wasn't already the default I -could make it so within that file. - -## Build - -At this point I think I'm ready to try actually building an APK. Thoughts and -prayers required. I run the following in a terminal, since for some reason the -`Build > Flutter > Build APK` dropdown button in android-studio did nothing. - -``` -flutter build apk -``` - -It takes quite a while to run, but in the end it errors with: - -``` -make: 'mobileNebula.aar' is up to date. -cp: cannot create regular file '../android/app/src/main/libs/mobileNebula.aar': No such file or directory - -FAILURE: Build failed with an exception. - -* Where: -Build file '/tmp/src/mobile_nebula/android/app/build.gradle' line: 95 - -* What went wrong: -A problem occurred evaluating project ':app'. -> Process 'command './gen-artifacts.sh'' finished with non-zero exit value 1 - -* Try: -Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights. - -* Get more help at https://help.gradle.org - -BUILD FAILED in 1s -Running Gradle task 'bundleRelease'... -Running Gradle task 'bundleRelease'... Done 1.7s -Gradle task bundleRelease failed with exit code 1 -``` - -I narrow down the problem to the `./gen-artifacts.sh` script in the repo's root, -which takes in either `android` or `ios` as an argument. Running it directly -as `./gen-artifacts.sh android` results in the same error: - -```bash -make: 'mobileNebula.aar' is up to date. -cp: cannot create regular file '../android/app/src/main/libs/mobileNebula.aar': No such file or directory -``` - -So now I gotta figure out wtf that `mobileNebula.aar` file is. The first thing I -note is that not only is that file not there, but the `libs` directory it's -supposed to be present in is also not there. So I suspect that there's a missing -build step somewhere. - -I search for the string `mobileNebula.aar` within the project using -[ag][silver_searcher] and find that it's built by `nebula/Makefile` as follows: - -```make -mobileNebula.aar: *.go - gomobile bind -trimpath -v --target=android -``` - -So that file is made by `gomobile`, good to know! Additionally the file is -actually there in the `nebula` directory, so I suspect there's just a missing -build step to move it into `android/app/src/main/libs`. Via some more `ag`-ing I -find that the code which is supposed to move the `mobileNebula.aar` file is in -the `gen-artifacts.sh` script, but that script doesn't create the `libs` folder -as it ought to. I apply the following diff: - -```bash -diff --git a/gen-artifacts.sh b/gen-artifacts.sh -index 601ed7b..4f73b4c 100755 ---- a/gen-artifacts.sh -+++ b/gen-artifacts.sh -@@ -16,7 +16,7 @@ if [ "$1" = "ios" ]; then - elif [ "$1" = "android" ]; then - # Build nebula for android - make mobileNebula.aar -- rm -rf ../android/app/src/main/libs/mobileNebula.aar -+ mkdir -p ../android/app/src/main/libs - cp mobileNebula.aar ../android/app/src/main/libs/mobileNebula.aar - - else -``` - -(The `rm -rf` isn't necessary, since a) that file is about to be overwritten by -the subsequent `cp` whether or not it's there, and b) it's just deleting a -single file so the `-rf` is an unnecessary risk). - -At this point I re-run `flutter build apk` and receive a new error. Progress! - -``` -A problem occurred evaluating root project 'android'. -> A problem occurred configuring project ':app'. - > Removing unused resources requires unused code shrinking to be turned on. See http://d.android.com/r/tools/shrink-resources.html for more information. -``` - -I recall that in the original [mobile_nebula][mobile_nebula] README it mentions -to run the `flutter build` command with the `--no-shrink` option, so I try: - -```bash -flutter build apk --no-shrink -``` - -Finally we really get somewhere. The command takes a very long time to run as it -downloads yet more dependencies (mostly android SDK stuff from the looks of it), -but unfortunately still errors out: - -``` -Execution failed for task ':app:processReleaseResources'. -> Could not resolve all files for configuration ':app:releaseRuntimeClasspath'. - > Failed to transform mobileNebula-.aar (:mobileNebula:) to match attributes {artifactType=android-compiled-dependencies-resources, org.gradle.status=integration}. - > Execution failed for AarResourcesCompilerTransform: /home/mediocregopher/.gradle/caches/transforms-2/files-2.1/735fc805916d942f5311063c106e7363/jetified-mobileNebula. - > /home/mediocregopher/.gradle/caches/transforms-2/files-2.1/735fc805916d942f5311063c106e7363/jetified-mobileNebula/AndroidManifest.xml -``` - -Time for more `ag`-ing. I find the file `android/app/build.gradle`, which has -the following block: - -``` - implementation (name:'mobileNebula', ext:'aar') { - exec { - workingDir '../../' - environment("ANDROID_NDK_HOME", android.ndkDirectory) - environment("ANDROID_HOME", android.sdkDirectory) - commandLine './gen-artifacts.sh', 'android' - } - } -``` - -I never set up the `ANDROID_HOME` or `ANDROID_NDK_HOME` environment variables, -and I suppose that if I'm running the flutter command outside of android-studio -there wouldn't be a way for flutter to know those values, so I try setting them -within my `env.sh`: - -```bash -export ANDROID_HOME=~/Android/Sdk -export ANDROID_NDK_HOME=~/Android/Sdk/ndk/21.0.6113669 -``` - -Re-running the build command still results in the same error. But it occurs to -me that I probably had built the `mobileNebula.aar` without those set -previously, so maybe it was built with the wrong NDK version or something. I -tried deleting `nebula/mobileNebula.aar` and try building again. This time... -new errors! Lots of them! Big ones and small ones! - -At this point I'm a bit fed up, and want to try a completely fresh build. I back -up my modified `env.sh` and `gen-artifacts.sh` files, delete the `mobile_nebula` -repo, re-clone it, reinstall those files, and try building again. This time just -a single error: - -``` -Execution failed for task ':app:lintVitalRelease'. -> Could not resolve all artifacts for configuration ':app:debugRuntimeClasspath'. - > Failed to transform libs.jar to match attributes {artifactType=processed-jar, org.gradle.libraryelements=jar, org.gradle.usage=java-runtime}. - > Execution failed for JetifyTransform: /tmp/src/mobile_nebula/build/app/intermediates/flutter/debug/libs.jar. - > Failed to transform '/tmp/src/mobile_nebula/build/app/intermediates/flutter/debug/libs.jar' using Jetifier. Reason: FileNotFoundException, message: /tmp/src/mobile_nebula/build/app/intermediates/flutter/debug/libs.jar (No such file or directory). (Run with --stacktrace for more details.) - Please file a bug at http://issuetracker.google.com/issues/new?component=460323. -``` - -So that's cool, apparently there's a bug with flutter and I should file a -support ticket? Well, probably not. It seems that while -`build/app/intermediates/flutter/debug/libs.jar` indeed doesn't exist in the -repo, `build/app/intermediates/flutter/release/libs.jar` _does_, so this appears -to possibly be an issue in declaring which build environment is being used. - -After some googling I found [this flutter issue][flutter_issue] related to the -error. Tldr: gradle's not playing nicely with flutter. Downgrading could help, -but apparently building with the `--debug` flag also works. I don't want to -build a release version anyway, so this sits fine with me. I run... - -```bash -flutter build apk --no-shrink --debug -``` - -And would you look at that, I got a result! - -``` -✓ Built build/app/outputs/flutter-apk/app-debug.apk. -``` - -## Install - -Building was probably the hard part, but I'm not totally out of the woods yet. -Theoretically I could email this apk to my phone or something, but I'd like -something with a faster turnover time; I need `adb`. - -I install `adb` via the `android-tools` package: - -```bash -yay -S android-tools -``` - -Before `adb` will work, however, I need to turn on USB debugging on my phone, -which I do by following [this article][usb_debugging]. Once connected I confirm -that `adb` can talk to my phone by doing: - -```bash -adb devices -``` - -And then, finally, I can install the apk: - -``` -adb install build/app/outputs/flutter-apk/app-debug.apk -``` - -NOT SO FAST! MORE ERRORS! - -``` -adb: failed to install build/app/outputs/flutter-apk/app-debug.apk: Failure [INSTALL_FAILED_UPDATE_INCOMPATIBLE: Package net.defined.mobile_nebula signatures do not match previously installed version; ignoring!] -``` - -I'm guessing this is because I already have the real nebula app installed. I -uninstall it and try again. - -AND IT WORKS!!! FUCK YEAH! - -``` -Performing Streamed Install -Success -``` - -I can open the nebula app on my phone and it works... fine. There's some -pre-existing networks already installed, which isn't the case for the Play Store -version as far as I can remember, so I suspect those are only there in the -debugging build. Unfortunately the presence of these test networks causes the -app the throw a bunch of errors because it can't contact those networks. Oh well. - -The presence of those test networks, in a way, is actually a good thing, as it -means there's probably already a starting point for what I want to do: building -a per-device nebula app with a config preloaded into it. - -## Further Steps - -Beyond continuing on towards my actual goal of adding DNS resolvers to this app, -there's a couple of other paths I could potentially go down at this point. - -* As mentioned, nixify the whole thing. I'm 99% sure the android-studio GUI - isn't actually needed at all, and I only used it for installing the CMake and - NDK plugins because I didn't bother to look up how to do it on the CLI. - -* Figuring out how to do a proper release build would be great, just for my own - education. Based on the [flutter issue][flutter_issue] it's possible that all - that's needed is to downgrade gradle, but maybe that's not so easy. - -* Get an android emulator working so that I don't have to install to my phone - everytime I want to test the app out. I'm not sure if that will also work for - the VPN aspect of the app, but it will at least help me iterate on UI changes - faster. - -But at this point I'm done for the day, I'll continue on this project some other -time. - -[mobile_nebula]: https://github.com/DefinedNet/mobile_nebula -[nebula]: https://slack.engineering/introducing-nebula-the-open-source-global-overlay-network-from-slack/ -[dns_issue]: https://github.com/DefinedNet/mobile_nebula/issues/9 -[arch]: https://archlinux.org/ -[android_wiki]: https://wiki.archlinux.org/index.php/Android#Making_/opt/android-sdk_group-writeable -[heilung]: https://youtu.be/SMJ7pxqk5d4?t=220 -[flutter_blog]: https://www.rockyourcode.com/how-to-get-flutter-and-android-working-on-arch-linux/ -[gomobile]: https://pkg.go.dev/golang.org/x/mobile/cmd/gomobile -[silver_searcher]: https://github.com/ggreer/the_silver_searcher -[flutter_issue]: https://github.com/flutter/flutter/issues/58247 -[usb_debugging]: https://www.droidviews.com/how-to-enable-developer-optionsusb-debugging-mode-on-devices-with-android-4-2-jelly-bean/ |