Thursday, March 3, 2022

How to decompile and repack Android App on ChromeOS (Part 2)

(1) This is the sequel to How to decompile android app (part 1)
And the demo apk can be download from here. TouchCalculator_1.0-debug.apk

(2) Part 1 is to demo the use of ChromeOS (devloper mode on) plus the decompile tools and the process of decode and edit some resource files then rebuild the apk using apktool.
If you have Windows machine, you can also download the required decompile tools as demo here.

(3) This part 2 is to continue to modify the logic in the Android App which involved the source code. I will use the JADX tools and Android Studio to edit the code.

cd ~/DecompileProjects
# Use jadx to decode the apk and export gradle project file and java source code
jadx --export-gradle TouchCalculator_1.0-debug.apk -d TouchCalculator2


(4) Then, launch Android Studio and open the project in ~/DecompileProjects/TouchCalculator2 and wait for the gradle to sync. If you try to Build -> Make Project (Ctrl F9), you will notice it has a lot of errors and these errors are mainly partial packages download from repo and many of them are not linkable. So we have to study the code, to see what are the actual code files needed for this project.

(5) Then create a new Android Studio project file with Empty Activity and with the following parameters.


(6) After creation of the new project, copy the decompiled java source code and resource files to the New Project as below:
shell script    Select all
cp ~/DecompileProjects/TouchCalculator2/app/src/main/java/com/pragmatouch/calculator/*.java ~/DecompileProjects/TouchCalculator3/app/src/main/java/com/pragmatouch/calculator/. cp ~/DecompileProjects/TouchCalculator2/app/src/main/res/drawable/k*.xml ~/DecompileProjects/TouchCalculator3/app/src/main/res/drawable/. cp ~/DecompileProjects/TouchCalculator2/app/src/main/res/drawable/stackview1.xml ~/DecompileProjects/TouchCalculator3/app/src/main/res/drawable/. cp ~/DecompileProjects/TouchCalculator2/app/src/main/res/drawable/inputview1.xml ~/DecompileProjects/TouchCalculator3/app/src/main/res/drawable/. cp ~/DecompileProjects/TouchCalculator2/app/src/main/res/drawable/appvertical1.xml ~/DecompileProjects/TouchCalculator3/app/src/main/res/drawable/. cp ~/DecompileProjects/TouchCalculator2/app/src/main/res/values/colors.xml ~/DecompileProjects/TouchCalculator3/app/src/main/res/values/. cp ~/DecompileProjects/TouchCalculator2/app/src/main/res/values/strings.xml ~/DecompileProjects/TouchCalculator3/app/src/main/res/values/. cp ~/DecompileProjects/TouchCalculator2/app/src/main/res/layout/activity_main.xml ~/DecompileProjects/TouchCalculator3/app/src/main/res/layout/ cp ~/DecompileProjects/TouchCalculator2/app/src/main/res/layout/calutor.xml ~/DecompileProjects/TouchCalculator3/app/src/main/res/layout/



(7) Then, there are several changes to the build.gradle settings. Target Sdk should be set to 30 in order to build as App Bundle format.
# Sdk should not use 32 and change to 30
   compileSdk 30
   targetSdk 30

# dependencies package change to lower version as below
   implementation 'androidx.appcompat:appcompat:1.3.0'
   implementation 'com.google.android.material:material:1.3.0'

For Release build type add
   debuggable false


(8) Then, we try to Build -> Make Project (Ctrl F9) again in the New Project and see if there are any errors to solve. For complex project, it is not possible to have a full project file to build after decompile. So there is a part 3 for this topic.

(9) In fact, the project code was from here, so I can find out the required project files easily. However, there are still some features of this app which have not been implemented yet and with the decompiled java source code, you can modify the decompiled code and rebuild it to apk and test again. ALternatively, you can copy the original source code from here and paste them to the relevant java source code files of your new project.

(10) Change the resource files as in Part 1 of this artcile and add the following lines in MainActivity.java to implement the PERCENT, SQRT and RRECIPROC functions. And then Run the app in Android Studio or rebuild the apk to test on real Android device.
diff results    Select all
# diff ./TouchCalculator2/app/src/main/java/com/pragmatouc h/calculator/MainActivity.java ./TouchCalculator3/app/src/main/java/com/pragmatouch/calculator/MainActivity.java 192a193,236 > case 16: // PERCENT > double userInputValue4 = tryParseUserInput(); > if (!Double.isNaN(userInputValue4)) { > if (Double.isNaN(this.memoryValue)) { > this.memoryValue = 0.0d; > } > this.memoryValue = (userInputValue4/100); > this.userInputText.setText(doubleToString(this.memoryValue)); > this.hasFinalResult = true; > return; > } > return; > case 17: // SQRT > // reject negative num > if (currentInputLen > 0 && currentInput.charAt(0) == '-') { > return; > } > double userInputValue5 = tryParseUserInput(); > if (!Double.isNaN(userInputValue5)) { > if (Double.isNaN(this.memoryValue)) { > this.memoryValue = 0.0d; > } > this.memoryValue = Math.sqrt(userInputValue5); > this.userInputText.setText(doubleToString(this.memoryValue)); > this.hasFinalResult = true; > return; > } > return; > case 18: // RECIPROC > // reject zero > if (currentInputLen == 1 && currentInput.charAt(0) == '0') { > return; > } > double userInputValue6 = tryParseUserInput(); > if (!Double.isNaN(userInputValue6)) { > if (Double.isNaN(this.memoryValue)) { > this.memoryValue = 0.0d; > } > this.memoryValue = (1/userInputValue6); > this.userInputText.setText(doubleToString(this.memoryValue)); > this.hasFinalResult = true; > return; > } > return; 276a321,332 > } > try { > $SwitchMap$com$pragmatouch$calculator$KeypadButton[KeypadButton.PERCENT.ordinal()] = 16; > } catch (NoSuchFieldError e16) { > } > try { > $SwitchMap$com$pragmatouch$calculator$KeypadButton[KeypadButton.SQRT.ordinal()] = 17; > } catch (NoSuchFieldError e17) { > } > try { > $SwitchMap$com$pragmatouch$calculator$KeypadButton[KeypadButton.RECIPROC.ordinal()] = 18; > } catch (NoSuchFieldError e18) {



There are still bugs here and please feel free to correct them plus any new enhancements of this calculator and Enjoy Android Studio Programming.



(11) When decompiling some apks that was compiled with old sdk or converting some old android projects to the at least using SDK 30, some conversion of libraries are needed as below:
In build.gradle, you should use androidx instead of old Android Support Libraries
     compileSdkVersion 30
    implementation 'androidx.appcompat:appcompat:1.3.0'
instead of 'com.android.support:appcompat-v7:28.0.0' or something like 'com.android.support:support-v13:26.0.2'
You also should use kotlin library if the decompiled project was converted from kotlin to Java
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"

See here for reference. https://developer.android.com/jetpack/androidx

In gradle.properties, you should setup useAndroidX and enableJetifier
android.useAndroidX=true
android.enableJetifier=true

For converted/decompiled Java classes source, don't use old android support libraries, use androidx instead.
Full class-mapping here https://developer.android.com/jetpack/androidx/migrate/class-mappings
//import android.support.v4.app.NotificationCompat;
//import android.support.v7.app.AppCompatActivity;
//import android.support.v4.app.RemoteInput;
//import android.support.v4.app.Fragment;
import androidx.core.app.NotificationCompat;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.RemoteInput;
import androidx.fragment.app.Fragment;
import androidx.annotation.RequiresApi;
import android.annotation.TargetApi;
import android.annotation.SuppressLint;




(12) If you really want to support old devices and not using androidx, you should use SdkVersion 28 and compatible appcompat version as below:
      compileSdkVersion 28

    implementation 'com.android.support:appcompat-v7:28.0.0'

How to decompile and repack Android App on ChromeOS

(1) You need ChromeOS with developer mode turn on for your machine. Either use a Chromebook (after powerwash) or install a recovery image on your old pc, with developer mode on (see here How to install ChromeOS to your USB stick for your old PC)

(2) You have to install Android Studio and decompile tools on your ChromeOS machine (see here How to run Android Emulator on ChromeOS)

(3) Here is the walkthrough on how to decompile apk and change the resource file and repack and sign the apk file again. Assume you don't have the source code project file. The original demo apk can be download from here. TouchCalculator_1.0-debug.apk

(4) The problem of this TouchCalculator app has two problems on the interface: a) The memory text on the left should be smaller in size b) The key (on the right) with a comma is wrong and it should be a dot for input decimal point. Without the source project file, and in order to modify it, you have to decompile it and study the code and repack it to apk file to run.

(5) Assume, you have the ChromeOS machine and installed software and also setup the decompile tools as in Steps (1) and (2). And In Linux Terminal execute these steps:

mkdir ~/DecompileProjects
cd ~/DecompileProjects
# Then copy the download apk file to this Linux folder DecompileProjects
# Use apktool to decode the apk
apktool decode TouchCalculator_1.0-debug.apk -o TouchCalculator

# After studying the xml files in the res/layout folder
# modify the file: TouchCalculator/res/layout/activity_main.xml
# and change from 25.0sp to a smaller textSize of 12.0sp
   <TextView android:textSize="25.0sp" android:textColor="@color/lightyellow" android:gravity="right" android:id="@id/txtMemory"
#to
   <TextView android:textSize="12.0sp" android:textColor="@color/lightyellow" android:gravity="right" android:id="@id/txtMemory"

# modify the file: TouchCalculator/smali_classes3/com/pragmatouch/calculator/KeypadButton.smali

# line 453 and change the button label from "," to "•"
   const-string v3, ","
# to
   const-string v3, "\u2022"

# Use apktool to build the apk after modification of the resource files
apktool build TouchCalculator -o TouchCalculator_1.01.apk
# generate a keystore with SHA256RSA (if not yet generated) and remember the storepassword
keytool -genkey -v -keystore my-release-key256.keystore -alias mykey256 -sigalg SHA256withRSA -keyalg RSA -keysize 2048 -validity 10000 -deststoretype pkcs12
# sign the apk with self-signed certificate and enter the storepassword
jarsigner -verbose -sigalg SHA256withRSA -keystore my-release-key256.keystore TouchCalculator_1.01.apk mykey256
# verify the signature
jarsigner -verify -verbose -certs -keystore my-release-key256.keystore TouchCalculator_1.01.apk
# zipalign the apk
zipalign -v 4 TouchCalculator_1.01.apk TouchCalculator_1.01-aligned.apk

(6) Install the TouchCalculator_1.01-aligned.apk on your ChromeOS (with developer mode on) machine or your Android device (With Unknown Sources on) for testing. For ChromeOS, please uninstall the previous apk version before installation of the new one.

(7) This is just a proof of concept that using apktool can decompile then modify and repack again to an apk file. To further modify the java / smali code in the decompile source, just stay tune for my next article.



Tuesday, March 1, 2022

How to run Android Emulator on ChromeOS

(1) You need a ChromeOS machine with x86_64 CPU, 8GB RAM or above and for Intel CPU say i5 or above and 128GB storage.

(2) Setup Linux Environment (here) in ChromeOS with at least 20GB linux file size and Download the installation file here and while downloading the file Open the Terminal app then do step 3 below and then follow the Installation Steps of Android Studio in ChromeOS (here).

(3) In Linux Terminal, you have to install libnns3
sudo apt update && sudo apt upgrade
sudo apt install libnss3-dev libgdk-pixbuf2.0-dev libgtk-3-dev libxss-dev


(4) After the acceptance of the license and Finish with the download of SDK platform and tools and this might take some time to download and unzip. Then start Android Studio and with create a new blank project or import a project from github and wait for the update of gradle sync then goto Tools -> SDK Manager to check whether the required SDK are proerly installed and then goto Tools -> Device Manager and click Create device.

(5) Choose a Hardware layout e.g. Phone Pixel 4 XL and then click Next to select a system image e.g. Release Name S, API 31, x86_64 Andoird 12.0 (Google APIs) and then click the Download next to Release Name. This may take a much longer time to download and unzip and would occupy a lot of Linux System storage space if you download more than one image.

(6) After download is done, click Finish and then Next to name the device and fill in Advanced Settings if any and then click Finish to create.

(7) Then start the emulator by Running your project to the emulator and check whether the compileSdkVersion (e.g. 32) in build.gradle for Module match with your download and first click the Build -> Make Project (Ctrl+F9) to see if there is any error. Then, start the project by clicking the Run -> Run App (Shift+F10) or start the Emulator manually in Device Manager. After this step your ChromeOS will experience a significant slow down when the Emulator is running. My testing is that Intel 10th generation i5 CPU with 8GB Ram and 128 GB storage can run reasonably well for the simple project in Android Emulator.

(8) If you want a larger screen or floating window for the Emulator, you can click the Settings button of the elumlator window and set it to View Mode -> Window and then resize the detached window.

(9) You can debug the project source code with the Emulator if you click Run -> Debug App (Shift+F9). If you have enabled Developer Mode in ChromeOS (which is default for Brunch framework). Alternatively, you could build the apk and side load it to the ChromeOS or real device for test run, but debugging on ChromeOS or real device has to first powerwash the ChromeOS machine and then open the ADB port

(10) If you like to have this android studio project (written in Java) for testing, you can download it from here PeamonCalculator.zip

There is another Android Studio Project on Calculator which is written in Kotlin GitHub project source code download here. You might have to change the build SDK version for this project to your Settings in SDK, e.g. compileSdkVersion 32 which is the default SDK version currently for newly installed Android Studio.


(11) If you want to use the JRE from Android Studio in Terminal, add these lines in your ~/.profile
# set JAVA_HOME for Android Studio
export JAVA_HOME=/opt/android-studio/jre
export ANDROID_HOME="$HOME/Android"
export ANDROID_SDK_ROOT="$ANDROID_HOME/Sdk"
PATH="$JAVA_HOME/bin:$ANDROID_SDK_ROOT/build-tools/30.0.3:$PATH"


(12) If you want to install decompile tools on ChromeOS
sudo apt install -y curl unzip
export ANDROID_DECOMPILE_TOOLS=="$ANDROID_HOME/DecompileTools"
# install apktool (d) decompile apk file to smali and resource folders or (b) build them to apk file
mkdir -p $ANDROID_DECOMPILE_TOOLS/apktool && pushd $ANDROID_DECOMPILE_TOOLS/apktool && curl -OL https://bitbucket.org/iBotPeaches/apktool/downloads/apktool_2.6.0.jar && ln -s apktool_2.6.0.jar apktool.jar && curl -OL https://raw.githubusercontent.com/iBotPeaches/Apktool/master/scripts/linux/apktool && chmod +x apktool && popd
# install jadx (to compile smali file to java source code and support whole project or single file conversion)
curl -OL https://github.com/skylot/jadx/releases/download/v1.3.3/jadx-1.3.3.zip && unzip jadx-1.3.3.zip -d $ANDROID_DECOMPILE_TOOLS/jadx && rm -v jadx-1.3.3.zip
PATH="$ANDROID_HOME/DecompileTools/apktool:$ANDROID_HOME/DecompileTools/jadx/bin:$PATH"


# install jadx (to compile java/kotlin project files to smali code, but does not support single file conversion)
For Java2Smali, install the plugin version in Android Studio. File -> Settings (Ctrl-ALt-S ) -> Plugins and search java2smali to install.


Sunday, February 27, 2022

How to install ChromeOS to your USB stick for your old PC

(1) Prepare an USB stick with at least 16G. I am using 64G for demo and you need this size to download and install Linux in ChromeOS. Your PC should x86_64 based computer with UEFI boot support and ave Intel gen 1 to 9 to download rammus recovery image. For detail requirements see here https://github.com/sebanc/brunch.

(2) For Windows OS, first install WSL2 and Ubuntu 20.04 and you must enable this in "Turn On Windows features on and off"

(3) Alternativey, you can use Linux machine with Ubuntu 20.04 to do this

(4) According to the Brunch USB guide The ChromeOS recovery image is based on your CPU of your PC.
For Intel
"rammus" is suggested for 1st gen -> 9th gen.
"volteer" is suggested for 10th & 11th gen.
11th gen (and some 10th gen) may need kernel 5.10
For AMD
"grunt" is suggested for Stoney Ridge & Bristol Ridge.
"zork" is suggested for Ryzen.
Ryzen 4xxx devices need kernel 5.10 when Brunch Framework boot up

(5) After setting up the Ubuntu user and password run these scripts to create the image file (e.g. rammus for USB 64G drive)
sudo apt update
sudo apt -y install pv cgpt tar unzip
mkdir rammus
cd rammus
wget https://github.com/sebanc/brunch/releases/download/r97-stable-20220121/brunch_r97_stable_20220121.tar.gz
tar xzvf brunch_r97_stable_20220121.tar.gz
wget https://dl.google.com/dl/edgedl/chromeos/recovery/chromeos_14388.61.0_rammus_recovery_stable-channel_mp-v2.bin.zip
unzip chromeos_14388.61.0_rammus_recovery_stable-channel_mp-v2.bin.zip
# 64G USB has only about 58G for actual usage, so the size parameter here is 58.
sudo bash chromeos-install.sh -src chromeos_14388.61.0_rammus_recovery_stable-channel_mp-v2.bin -dst /mnt/c/Users/Public/Downloads/chromeos_rammus_58g.bin -s 58


(6) Then use ChromeOS Recovery Utility to flash the images, Use local image in Settings and select the "C:/Users/Public/Downloads/chromeos_rammus_58g.bin" image. See here

(7) If you are lazy to create this image, you can use mine and download it from chromeos_rammus_58g.bin.zip (3.61GB). You don't need to unzip it for creation of USB flash drive in ChromeOS Recovery Utility or Rufus

(8) If your PC has secure boot enabled, either disable it (ig you have set the supervisor password) or import the key from USB. To enroll the key directly from a USB, select OK -> Enroll key from disk -> EFI-SYSTEM -> brunch.der -> Continue and reboot. Moreoover, enable of UEFI support and change the boot order to USB is needed in BIOS.

Friday, February 25, 2022

How to download and resize Chrome OS Flex Image for USB boot Install

While you can live boot Chrome OS Flex from the USB installer, Google recommends that you fully install it on devices. When you live-boot Chrome OS Flex, limited storage (4GB) is available because of the layout of Chrome OS Flex's partition table. To overcome this limitation, we have to resize the partition to fully utilise your USB storage space.

How to download and resize Chrome OS Flex Image to 20GB, which is suitable to be use on a 32GB USB drive.
# use a linux machine, or Windows WSL Ubuntu 20.04 # see here https://github.com/sebanc/brunch/blob/master/install-with-windows.md

shell script    Select all
sudo apt update sudo apt -y install pv cgpt tar unzip curl cloud-guest-utils mkdir -p ~/Downloads cd ~/Downloads # download ChromeOS Flex image based on this conf file https://dl.google.com/dl/edgedl/chromeos/recovery/cloudready_recovery.conf # curl -OL https://dl.google.com/dl/edgedl/chromeos/recovery/chromeos_14516.0.0_reven_recovery_dev-channel_mp-v2.bin.zip curl -OL https://dl.google.com/dl/edgedl/chromeos/recovery/chromeos_14574.0.0_reven_recovery_dev-channel_mp-v2.bin.zip unzip chromeos_14574.0.0_reven_recovery_dev-channel_mp-v2.bin.zip ls -lh chromeos_14574.0.0_reven_recovery_dev-channel_mp-v2.bin # 20G is seek=20971520 # 28G is seek=29360128 (there is only 28G for 32G USB stick) # 58G is seek=60817408 (there is only 58G for 64G USB stick) # don't do method 1 on removable HD # grow image method 1 dd if=/dev/zero of=chromeos_14516.0.0_reven_recovery_dev-channel_mp-v2.bin seek=20971520 obs=1024 count=0 # grow image method 2, slower but works on removeable HD # 58G is count=52452 (there is only 58G for 64G USB stick) expr 20 \* 1024 - 6940 # calculate 20G = 13540 expr 28 \* 1024 - 6940 # calculate 28G = 21732 expr 58 \* 1024 - 6940 # calculate 58G = 52452 dd if=/dev/zero bs=1M count=13540 >> ./chromeos_14574.0.0_reven_recovery_dev-channel_mp-v2.bin # rename the file mv chromeos_14574.0.0_reven_recovery_dev-channel_mp-v2.bin chromeosflex20g.bin # grow partition 1, growpart is part of cloud-guest-utils package growpart chromeosflex20g.bin 1 # show new data partition 1, start is 5152768 , size is now 36790239 (17G) cgpt show chromeosflex20g.bin | grep -B 5 STATE cgpt repair chromeosflex20g.bin



Then use ChromeOS Recovery Utility to flash the images, Use local image in Settings and select the chromeosflex20g.bin image.
See here



IMPORTANT
The final step is to put the USB drive to linux system and check the drive using
sudo fdisk -l
# e.g. the USB drive partition 1 is sda1

# first check
sudo e2fsck -f /dev/sda1
# then resize it
sudo resize2fs /dev/sda1


However, one of the limitations of live-boot USB is that the ChromeOS cannot be updated live. So your work has to be able to backup to Google Drive, Dropbox (using File System for Dropbox), OneDrive (using File System for OneDrive) or your LAN network share drive.

Tuesday, January 25, 2022

How to install vs code-server in Windows WSL2 and setup firewall rules to access from other LAN machines

(1) Start Ubuntu 20.04 of WSL2 and install code-server
curl -fsSL https://code-server.dev/install.sh | sh

(2) Modify bind IP address port settings and password of the code-server
Get Ubuntu IP address
ifconfig eth0 | grep 'inet '
Edit bind address and password in
~/.config/code-server/config.yaml

(3) start code-server in Ubuntu
code-server

(4) Modify firewall rule and add forward port in Windows using PowerShell with Admin Right. Create the following file vscode_server_port_wsl2.ps1 and run in PowerShell with Admin Right
.\vscode_server_port_wsl2.ps1
vscode_server_port_wsl2.ps1    Select all
# Get network information $network_information = bash.exe -c "ifconfig eth0 | grep 'inet '"; # Define ip address pattern $ip_address_pattern = "\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"; # Get ip address $ip_address = $network_information -match $ip_address_pattern # Proceed if ip address is found if ($ip_address) { # Get remote address $remote_address = $matches[0]; } # Define rule name $rule_name = "VS Code Server (WSL2)"; # Define port for the VS Code Server - default is 8080 $port = 8080; # Check if rule exists $rule_exists = Get-NetFirewallRule -DisplayName $rule_name 2> $null; # Proceed if rule doesn't exists if (-Not $rule_exists) { # Add new inbound rule New-NetFirewallRule -DisplayName $rule_name -Direction Inbound -LocalPort $port -Protocol TCP -Action Allow } # Define listen address $listen_address = "0.0.0.0"; # Update ip address iex "netsh interface portproxy delete v4tov4 listenport = $port listenaddress = $listen_address"; iex "netsh interface portproxy add v4tov4 listenport = $port listenaddress = $listen_address connectport = $port connectaddress = $remote_address";

Do this in powershell with admin right.

Set-ExecutionPolicy Unrestricted -Force





(5) Test access of code-server from other machine in the LAN
Use browser to access this address and enter password as in
http://<IP address of your windows machine>:8080/

(6) Test access of code-server from VPN connection from Internet.
First use OpenVPN to connect to your home/office network
Then use browser to access
http://<IP address of your windows machine>:8080/

(7) If you have installed docker for Windows, this command will help you to install and run code-server in docker.
command prompt shell    Select all
# Testing on local host machine docker run --name code-server -p 127.0.0.1:8080:8080 -v "$HOME/.config:/home/coder/.config" -v "$HOME/:/home/coder/project" -e "USER=$env:UserName" -e "DOCKER_USER=$env:UserName" codercom/code-server:latest #or publish to the host machine IP address with port no 8081, to allow access from other LAN machines docker run --name code-server -p 8081:8080 -v "$HOME/.config:/home/coder/.config" -v "$HOME/:/home/coder/project" -e "USER=$env:UserName" -e "DOCKER_USER=$env:UserName" codercom/code-server:latest # stop container docker stop code-server # start container docker start code-server
run this command to get the password in config.yaml and then edit it of wanted.
docker exec -it code-server cat .config/code-server/config.yaml
or
type $HOME\.config\code-server\config.yaml
. . .

Thursday, January 13, 2022

Decompile and Recompile an Android APK using apktool

You need these tools to do the jobs

Android Studio (with build tools such as keytool, jarsigner)
apktool download from https://bitbucket.org/iBotPeaches/apktool/downloads/ and extract and rename to apktool.jar
apktool wrapper script https://raw.githubusercontent.com/iBotPeaches/Apktool/master/scripts/windows/apktool.bat
Java SE 8 JDK download from https://www.oracle.com/java/technologies/javase/javase8u211-later-archive-downloads.html
dex2jar download from https://sourceforge.net/projects/dex2jar/
JD_GUI download from http://jd.benow.ca/
smalidea download from https://github.com/JesusFreke/smalidea
Online Decompiler for apk https://appscms.com/apk-decompiler
jadx download from https://github.com/skylot/jadx/releases

apktool — tool for reverse engineering Android apk files. In this case we are using to extract files from apk and rebuild.
keytool — Java tool for creating keys/certs, that comes with the Java SE JDK.
jarsigner Java tool for signing JAR/APK files, that comes with the Java SE JDK.
zipalign — archive alignment tool, that comes with the Android SDK.
JD-GUI — To view java code
dex2jar — Converts Android dex files to class/jar files.
smalidea is a smali language plugin for AS and to edit the file in Android Studio
jadx — convert single smali file to java code to test the modification of smali

For smali syntax, please refer to this doc
https://programmer.help/blogs/smali-introduction-manual.html
or http://source.android.com/devices/tech/dalvik/dalvik-bytecode.html

Instructions:
First, Take any apk file and unpack(decompile) it. This will create an “application” directory with assets, resources, compiled code, etc.
# To decompile an apk
apktool d -r -s my_application.apk
or
apktool d my_application.apk

Then, you can use Android Studio to open the smali file and edit it. Use APKRepacker to test the single smali file conversion.

# To recompile(build) the apk
apktool b -f -d my_application -o my_application2.apk

After recompiling (building) the apk the new apk (my_application2.apk) will be generated in directory.

The APK must be signed before you run on your device. If you want an official key from google play signing key, you should register with https://play.google.com/console/u/0/signup first and pay $25 registration key
Before signing an apk, create a self-signing key if you don't have an existing one from google play. If prompted for a password, create your own password.
These tools are installed withn JDK e.g. in "c:\Program Files\Java\jdk1.8.0_301\bin\". Add this to the environment PATH.

macOS binary are here /Applications/Android Studio.app/Contents/jre/Contents/Home/bin

# To generate a key. And remember the store password
keytool -genkey -v -keystore my-release-key.keystore -alias alias_name -keyalg RSA -keysize 2048 -validity 10000

# if want to generate SHA256withRSA keystore (in order to get rid of the warning of security when signing with SHA1), use this command
keytool -genkey -v -keystore my-release-key256.keystore -alias mykey256 -sigalg SHA256withRSA -keyalg RSA -keysize 2048 -validity 10000 -deststoretype pkcs12

Now sign the APK with the key:
# Sign the apk
jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore my-release-key.keystore my_application2.apk alias_name

# if Sign with SHA256withRSA (in order to get rid of the warning of security when signing with SHA1)
jarsigner -verbose -sigalg SHA256withRSA -keystore my-release-key256.keystore my_application2.apk mykey256

# Verify apk
jarsigner -verify -verbose -certs -keystore my-release-key.keystore my_application2.apk

# Verify apk with SHA256withRSA
jarsigner -verify -verbose -certs -keystore my-release-key256.keystore my_application2.apk

# Finally, the apk must be aligned for optimal loading:
zipalign is installed with Android SDK e.g. in c:\Users\User\AppData\Local\Android\Sdk\build-tools\28.0.3\zipalign.exe Add this to the environment PATH.
zipalign -v 4 my_application2.apk my_application2-aligned.apk
you have a my_application2-aligned.apk file, which you can install onto your device.


Other useful tools using command prompt under Windows
# Command Prompt to list android virtual devices %USERPROFILE%\AppData\Local\Android\Sdk\emulator\emulator -list-avds
# PowerShell command to list android virtual devices & $env:UserProfile\AppData\Local\Android\Sdk\emulator\emulator -list-avds
# Command Prompt to list android virtual device in background
start /b %USERPROFILE%\AppData\Local\Android\Sdk\emulator\emulator -avd Pixel_3a_API_30_x86 -netdelay none -netspeed full
# Command Prompt to show running emulator devices
%USERPROFILE%\AppData\Local\Android\Sdk\platform-tools\adb devices
# Command Prompt to attach to running emulator device shell
%USERPROFILE%\AppData\Local\Android\Sdk\platform-tools\adb -s emulator-5554 shell
# Command Prompt to install apk to running emulator device
%USERPROFILE%\AppData\Local\Android\Sdk\platform-tools\adb -s emulator-5554 install %USERPROFILE%\Downloads\my_application2-aligned.apk
export ANDROID_HOME="%USERPROFILE%\AppData\Local\Android\Sdk"




Other useful tools using Terminal under macOS
# macOS Terminal to list android virtual devices $HOME/Library/Android/sdk/emulator/emulator -list-avds
# macOS Terminal to show running emulator devices
$HOME/Library/Android/sdk/platform-tools/adb devices
# macOS Terminal to attach to running emulator device shell
$HOME/Library/Android/sdk/platform-tools/adb -s emulator-5554 shell
# macOS Terminal to install apk to running emulator device
$HOME/Library/Android/sdk/platform-tools/adb -s emulator-5554 install ~/Downloads/my_application2-aligned.apk
export ANDROID_HOME="$HOME/Library/Android/sdk" export JAVA_HOME="/Applications/Android Studio.app/Contents/jre/Contents/Home" export PATH=$ANDROID_HOME/build-tools/30.0.3:$ANDROID_HOME/platform-tools:$JAVA_HOME/bin:$PATH


Setup sdk and decompile tools in WSL2 Ubuntu 20.04    Select all
#!/bin/bash sudo apt install -y libarchive-tools export ANDROID_SDK_TOOLS_VERSION=6858069 export ANDROID_SDK_TOOLS_CHECKSUM=87f6dcf41d4e642e37ba03cb2e387a542aa0bd73cb689a9e7152aad40a6e7a08 export ANDROID_HOME="/opt/android-sdk-linux" export ANDROID_SDK_ROOT="/opt/android-sdk-linux" export ANDROID_DECOMPILE_TOOLS="$ANDROID_HOME/Decompile" curl -s https://dl.google.com/android/repository/commandlinetools-linux-${ANDROID_SDK_TOOLS_VERSION}_latest.zip > ./tools.zip && echo "$ANDROID_SDK_TOOLS_CHECKSUM ./tools.zip" | sha256sum -c && sudo mkdir -p $ANDROID_HOME && sudo chown $(id -u):$(id -g) $ANDROID_HOME && unzip -qq ./tools.zip -d $ANDROID_HOME && rm -v ./tools.zip sudo mkdir -p $ANDROID_HOME/licenses/ && sudo chown $(id -u):$(id -g) $ANDROID_HOME/licenses && echo "8933bad161af4178b1185d1a37fbf41ea5269c55\nd56f5187479451eabf01fb78af6dfcb131a6481e\n24333f8a63b6825ea9c5514f83c2829b004d1fee" > $ANDROID_HOME/licenses/android-sdk-license && echo "84831b9409646a918e30573bab4c9c91346d8abd\n504667f4c0de7af1a06de9f4b1727b84351f2910" > $ANDROID_HOME/licenses/android-sdk-preview-license --licenses && yes | $ANDROID_HOME/cmdline-tools/bin/sdkmanager --licenses --sdk_root=${ANDROID_SDK_ROOT} curl -OL https://raw.githubusercontent.com/MobileDevOps/android-sdk-image/master/packages.txt $ANDROID_HOME/cmdline-tools/bin/sdkmanager --update --sdk_root=${ANDROID_SDK_ROOT} && while read -r pkg; do PKGS="${PKGS}${pkg} "; done < $HOME/packages.txt && $ANDROID_HOME/cmdline-tools/bin/sdkmanager $PKGS > /dev/null --sdk_root=${ANDROID_SDK_ROOT} curl -OL https://nchc.dl.sourceforge.net/project/dex2jar/dex2jar-2.0.zip && unzip dex2jar-2.0.zip -d $ANDROID_HOME/Decompile && chmod +x $ANDROID_HOME/Decompile/dex2jar-2.0/*.sh && rm -v dex2jar-2.0.zip mkdir -p $ANDROID_DECOMPILE_TOOLS/apktool && pushd $ANDROID_DECOMPILE_TOOLS/apktool && curl -OL https://bitbucket.org/iBotPeaches/apktool/downloads/apktool_2.6.0.jar && ln -s apktool_2.6.0.jar apktool.jar && curl -OL https://raw.githubusercontent.com/iBotPeaches/Apktool/master/scripts/linux/apktool && chmod +x apktool && popd curl -OL https://github.com/skylot/jadx/releases/download/v1.3.3/jadx-1.3.3.zip && unzip jadx-1.3.3.zip -d $ANDROID_DECOMPILE_TOOLS/jadx && rm -v jadx-1.3.3.zip mkdir -p $ANDROID_DECOMPILE_TOOLS/java2smali && curl -OL https://github.com/izgzhen/java2smali/releases/download/1.1/dist.zip && bsdtar xvf dist.zip --strip-components=1 -C $ANDROID_DECOMPILE_TOOLS/java2smali/ && rm -v dist.zip mkdir -p $ANDROID_DECOMPILE_TOOLS/java2smali && pushd $ANDROID_HOME/Decompile/java2smali && curl -OL https://github.com/JesusFreke/smali/releases/download/v2.0b6/smali-2.0b6.jar && curl -OL https://github.com/JesusFreke/smali/releases/download/v2.0b6/baksmali-2.0b6.jar && curl -OL https://raw.githubusercontent.com/JesusFreke/smali/master/scripts/smali && curl -OL https://raw.githubusercontent.com/JesusFreke/smali/master/scripts/baksmali && popd pushd $ANDROID_DECOMPILE_TOOLS/java2smali && ln -s baksmali-2.0b6.jar baksmali.jar && ln -s smali-2.0b6.jar smali.jar && chmod +x baksmali && chmod +x smali && popd # Then append these lines to ~/.profile export ANDROID_HOME="/opt/android-sdk-linux" export ANDROID_SDK_ROOT=$ANDROID_HOME export ANDROID_DECOMPILE_TOOLS=="$ANDROID_HOME/Decompile" export PATH=$ANDROID_HOME/cmdline-tools:$ANDROID_HOME/cmdline-tools/bin:$ANDROID_HOME/platform-tools:$ANDROID_HOME/build-tools/30.0.3:$ANDROID_DECOMPILE_TOOLS/jadx/bin:$ANDROID_DECOMPILE_TOOLS/java2smali:$ANDROID_DECOMPILE_TOOLS/apktool:$ANDROID_DECOMPILE_TOOLS/dex2jar-2.0:$PATH