Or how to stop looking like a phone-shaking lunatic while working with react native.
If you ever had to test your React Native app on a real android phone you know the struggle. To open the debugger menu you have to shake your phone. You shake, again and again, obviously the "wrong way". Then for no reason, it accepts to open the debugger menu.
What can we do about it? If you are still shaking your phone nowadays, you probably think that there is no way to avoid the struggle.
Hopefully, there is an easy solution you can execute into your terminal:
++pre>++code>$ adb shell input keyevent 82
++/code>++/pre>
This command replicates the shake action onto your USB connected device.
I give you this one as a partial fix. However, it's not enough for me. I want an easier way to toggle this menu without even having to be on my terminal.
Why not create a button on your Touch Bar to shake your React Native debug app?
MTMR is a swift project built @Toxblh and @ReDetection on this Github repo. It allows you to customize your touch bar with a single JSON file.
You can install it by downloading the last released .dmg here.
Or you can install it with Homebrew:
++pre>++code>brew cask install mtmr++/code>++/pre>
MTMR allow you to personalize your Touch Bar with custom buttons. You can create layouts to display one of the three following kind of elements on your touch-bar:
Let's launch MTMR app. You should have a bar looking like this:
Before you ask me in the comment on how to get your original Touch Bar layout back, let me answer you. You have to quit MTMR:
?Or you can add a button to display your macOS layout!
Open the setting file "items.json" by going to the app menu and click on Preference. Then add the following code between the "escape" button and the "dnd" button.
++pre>++code>{
"type": "exitTouchbar",
"align": "left",
"bordered": false,
"title": "exit",
"width": 50,
},
++/code>++/pre>
Then save the file.
We have made a built-in button. Its type defines the action that will executed on button press. Its title defines the label of the button. The other properties define the style.
Your bar should look like this now:
By clicking on your newly added button, you can go back to your macOS touch bar preset.
Then, you may notice that an "MT" button is now added to the preset. It leads you to your customized bar.
In the first part of this article, I wrote about the command to mock the shake action for the android debugger:
++pre>++code>adb shell input keyevent 82
++/code>++/pre>
Let's build a button to call this action from your customized touch bar!
You will need to have the Android Debugger Bridge (adb) installed on your computer to be able to create the button. If not installed, please run:
++pre>++code>brew cask install android-platform-tools
++/code>++/pre>
To check if the installation is correct, please enter the following command in a terminal window:
++pre>++code>which adb
++/code>++/pre>
We will begin with a static button, and improve it later:
++pre>++code>{
"type": "staticButton",
"title": "shake",
"action": "appleScript",
"actionAppleScript":
{
"inline": "do shell script \"/Users/florent/Library/Android/sdk/platform-tools/adb shell input keyevent 82\""
},
"align": "left",
"bordered": true
},
++/code>++/pre>
So what is the difference between a built-in button and static button? With a static button you can now define the action to execute with a script instead of using a pre-defined action.
Add the code next to the "exit" button we added earlier and save the file. You should now have a bar looking like this :
If you press the button with a React Native debug app running on your phone, your shake button will open the shake menu!
Let's improve the button:
In your favorite shell, go to the directory where you want to add your Touch Bar scripts. Then create the script file ( we will name it adb-shake.sh in this example) and finally add the following code inside the file.
++pre>++code>#!/bin/bash
/Users/florent/Library/Android/sdk/platform-tools/adb shell input keyevent 82;
++/code>++/pre>
Now let's add the script to the custom button. Don't forget to give yourself the right to execute the script:
++pre>++code>chmod +x adb-shake.sh
++/code>++/pre>
Get the absolute path of your script with:
++pre>++code>realpath adb-shake.sh
# => /Users/florent/Workspace/scripts/mtmr/adb-shake.sh
++/code>++/pre>
And then place it into your button:
++pre>++code>{
"type": "staticButton",
"title": "shake",
"action": "shellScript",
"executablePath": "/Users/florent/Workspace/scripts/mtmr/adb-shake.sh",
"align": "left",
"bordered": true
},
++/code>++/pre>
We need to display the button only when a device is connected to the computer.
First, create a render-adb-shake-button.sh file with the following content:
++pre>++code>#!/bin/bash
# List the devices then count the number of lines with `wc -l`
IS_DEVICE_CONNECTED=$({path to your adb} devices | wc -l | awk '{print $1}')
# If no device is connected we get two lines. Otherwise, we get 3 lines or more
if [ "$IS_DEVICE_CONNECTED" -gt 2 ];
then
echo "shake"
else
echo ""
fi
++/code>++/pre>
MTMR does not show a button with an empty title so this script echoes a space if there is a connected device, else an empty string.
Now let's add the script to the button. Give yourself the right to execute the script:
++pre>++code>chmod +x render-adb-shake-button.sh
++/code>++/pre>
Get the absolute path to your adb-shake script.
++pre>++code>realpath render-adb-shake-button.sh
# => /Users/florent/Workspace/scripts/mtmr/render-adb-shake-button.sh
++/code>++/pre>
And add it into the "source" as the "filePath of your "shellScriptTitledButton".
It may look like this:
++pre>++code>{
"type": "shellScriptTitledButton",
"source": {
"filePath": "/Users/florent/Workspace/scripts/mtmr/render-adb-shake-button.sh"
},
"action": "shellScript",
"executablePath": "/Users/florent/Workspace/scripts/mtmr/adb-shake.sh",
"align": "left",
"bordered": true
},
++/code>++/pre>
Then your button should show or hide when you connect a device!
Thanks for reading! If you have any questions or if you need troubleshooting, please feel free to ask in comments or to send me an email (florentp at bam.tech)
The React Native demo app used in the examples is from React-gondola repo. It's a React Native declarative navigation library. Github repo here. Npm package there.
Be sure to check this blog regularly, my next article is on the way. I will show you how to debug in Wifi your React Native in a single button press.