<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ana Bujan</title>
    <description>The latest articles on DEV Community by Ana Bujan (@anabujan).</description>
    <link>https://dev.to/anabujan</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1337835%2F9d24282e-2986-4a6c-a14a-2a12ec72e632.jpeg</url>
      <title>DEV Community: Ana Bujan</title>
      <link>https://dev.to/anabujan</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/anabujan"/>
    <language>en</language>
    <item>
      <title>How to Install React Native Skia with Expo for Web and Native</title>
      <dc:creator>Ana Bujan</dc:creator>
      <pubDate>Mon, 22 Apr 2024 12:15:13 +0000</pubDate>
      <link>https://dev.to/anabujan/how-to-install-react-native-skia-with-expo-for-web-and-native-5fob</link>
      <guid>https://dev.to/anabujan/how-to-install-react-native-skia-with-expo-for-web-and-native-5fob</guid>
      <description>&lt;p&gt;This post features a really simple skia graphics but details instructions for installing react native skia on the expo go and expo web. Guide builds on top of the &lt;a href="https://docs.expo.dev/router/advanced/tabs/"&gt;expo router tabs demo&lt;/a&gt; app and saves you time and frustration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Intros, what’s what?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Skia&lt;/strong&gt; is a powerful open source graphics engine and library. It’s widely used in systems like Google Chrome, Android, iOS and many others.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expo&lt;/strong&gt; is a platform for building native apps for Android, iOS and the web with javascript/typescript and React Native. When devs go with expo instead of react native, they usually choose managed workflow. Managed workflow means most or all of the native code is hidden from you, you don’t need to worry about that, just type your React code and you’re done.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expo Go&lt;/strong&gt; is a mobile client app which lets you open and test projects while developing them. When you make changes to your code, those changes are immediately visible in the Expo Go app on your mobile device without needing a full reload of the app, preserving the current state. I believe other word for this feature is &lt;strong&gt;hot reload&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expo Router&lt;/strong&gt; is a file-based router for React Native and web applications. It allows you to manage navigation between screens in your app. Architecture of the routes and layout is very similar, if not the same as &lt;a href="https://nextjs.org/docs/app"&gt;next.js app router&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Requirements
&lt;/h2&gt;

&lt;p&gt;Configured Android SDK on your machine. Take a look at &lt;a href="https://www.amarjanica.com/configure-android-sdk-environment-on-windows-11"&gt;windows&lt;/a&gt;or &lt;a href="https://www.amarjanica.com/manually-install-android-sdk-on-ubuntu"&gt;linux&lt;/a&gt;instructions if you need step by step guide (also recorded on Youtube).&lt;/p&gt;

&lt;h2&gt;
  
  
  Initialize the project
&lt;/h2&gt;

&lt;p&gt;You can skip this step if you already have setup an expo project. I’m using the expo tabs template which includes a basic tab navigator setup, providing a structured layout and navigation system right from the start.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx create-expo-app@latest --template tabs@50
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Install Skia
&lt;/h2&gt;

&lt;p&gt;When installing dependencies on expo, usually you would install with &lt;code&gt;npx expo install&lt;/code&gt; instead of &lt;code&gt;npm&lt;/code&gt;or &lt;code&gt;yarn&lt;/code&gt;. &lt;em&gt;Reason for this approach is compatibility and automatic configuration.&lt;/em&gt; When issuing expo install, expo will pull the version which is known to work correctly with the version of sdk you are using. Also, expo will sometimes modify the native code or configuration files accordingly.&lt;/p&gt;

&lt;p&gt;In an ideal world, right?&lt;/p&gt;

&lt;p&gt;From my experience, this is not always the case. In the case of skia as authors mention:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Metro and expo-router support is available from v0.1.240 and onwards. If you are using v0.1.221 (recommended version for Expo SDK 50), you can use &lt;a href="https://github.com/Shopify/react-native-skia/files/14357144/%40shopify%2Breact-native-skia%2B0.1.221.patch"&gt;this patch&lt;/a&gt; (using &lt;a href="https://www.npmjs.com/package/patch-package"&gt;&lt;code&gt;patch-package&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;cite&gt;&lt;a href="https://shopify.github.io/react-native-skia/docs/getting-started/web/#expo"&gt;https://shopify.github.io/react-native-skia/docs/getting-started/web/#expo&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Version of sdk 50 will install 0.1.221 which does not work without an additional patch.&lt;/p&gt;

&lt;p&gt;My solution is to use a newer version and ignore expo-doctor warnings.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i --save @shopify/react-native-skia@0.1.240
npx expo install react-native-reanimated
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Skia depends on &lt;code&gt;react-native-reanimated&lt;/code&gt;, which is not installed without explicitly declaring it in &lt;code&gt;package.json&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configure Skia
&lt;/h2&gt;

&lt;p&gt;React native skia does not work without canvaskit.wasm, which needs to be stored somewhere in the expo app. Since I’m using the expo router setup, static files can be stored in public directory.&lt;/p&gt;

&lt;p&gt;Adding &lt;code&gt;”postinstall”: “npx setup-skia-web public”&lt;/code&gt; makes the wasm file accessible.&lt;/p&gt;

&lt;p&gt;There’s one fun error that occurs after the setup. I’ve lost an hour trying to debug and polyfill:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The package at “node_modules\canvaskit-wasm\bin\full\canvaskit.js” attempted to import the Node standard library module “fs”.&lt;br&gt;&lt;br&gt;
It failed because the native React runtime does not include the Node standard library.&lt;/p&gt;

&lt;p&gt;&lt;cite&gt;&lt;a href="https://docs.expo.dev/workflow/using-libraries/#using-third-party-libraries"&gt;https://docs.expo.dev/workflow/using-libraries/#using-third-party-libraries&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Self explanatory message, react native needs a workaround for standard node library like fs and path.&lt;/p&gt;

&lt;p&gt;React Native does not include Node.js’s standard library. Usual solution would be to polyfill the standard library. But the real culprit here is the &lt;code&gt;canvaskit-wasm&lt;/code&gt; module setup and not the lack of the standard Node library. Thanks to &lt;em&gt;&lt;a href="https://github.com/kimchouard/rn-skia-metro-web-example/blob/main/path-fs-canvaskit-postinstall.js"&gt;kimchouard&lt;/a&gt;&lt;/em&gt;, there’s a workaround for this issue (just copying the piece here to see what’s going on):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/**
 * Original code by https://github.com/kimchouard/rn-skia-metro-web-example/blob/main/path-fs-canvaskit-postinstall.js
 */
const fs = require('fs');
const path = require('path');

const packageJsonPath = path.join(__dirname, 'node_modules', 'canvaskit-wasm', 'package.json');
const packageJson = require(packageJsonPath);

packageJson.browser = {
    fs: false,
    path: false,
    os: false,
};

fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;canvaskit-wasm has no place using fs in native and web since we point to wasm file and also run &lt;code&gt;npx setup-skia-web public&lt;/code&gt; as part of postinstall.&lt;/p&gt;

&lt;p&gt;Create or modify &lt;em&gt;metro.config.js&lt;/em&gt; and add the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const { getDefaultConfig } = require('expo/metro-config');

const config = getDefaultConfig(__dirname, {
    isCSSEnabled: true,
});

config.resolver.assetExts.push('wasm');
config.transformer.getTransformOptions = async () =&amp;gt; ({
    transform: {
        experimentalImportSupport: false,
        inlineRequires: true,
    },
});

module.exports = config;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code customizes the Metro bundler configuration by adding support for WebAssembly (.wasm) files as assets. It also improves performance by inlining &lt;code&gt;require()&lt;/code&gt; calls and disables experimental import features. I don’t know why it doesn’t work without custom transform rules.&lt;/p&gt;

&lt;h2&gt;
  
  
  Making it work for the Web
&lt;/h2&gt;

&lt;p&gt;This is where &lt;code&gt;LoadSkiaWeb&lt;/code&gt; comes handy. I’d recommend adding this code in the root _layout if you need it accessible in your entire app.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;_layout.ts
useEffect(() =&amp;gt; {
    if (Platform.OS === 'web') {
      LoadSkiaWeb({ locateFile: () =&amp;gt; '/canvaskit.wasm' })
        .then(() =&amp;gt; {
          setLoaded(true);
        })
        .catch((err) =&amp;gt; console.error(err));
    } else {
      setLoaded(true);
    }
  }, []);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Sometimes expo acts fishy for no apparent reason (like the &lt;code&gt;Cannot read properties of undefined (reading ‘Matrix’)&lt;/code&gt;). Then the only solution is to &lt;a href="https://docs.expo.dev/troubleshooting/clear-cache-windows/"&gt;clear the bundler cache&lt;/a&gt; and reinstall/rebuild the app. Anyway, all source code to install and configure react native skia on web and on native &lt;a href="https://github.com/amarjanica/react-native-skia-expo-demo"&gt;is available at my github repo&lt;/a&gt;. Also I recorded a YT tutorial to make it easier to follow the setup.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>reactnative</category>
      <category>skia</category>
      <category>expogo</category>
    </item>
    <item>
      <title>Manually install Android SDK on Ubuntu</title>
      <dc:creator>Ana Bujan</dc:creator>
      <pubDate>Tue, 26 Mar 2024 18:25:18 +0000</pubDate>
      <link>https://dev.to/anabujan/manually-install-android-sdk-on-ubuntu-35k1</link>
      <guid>https://dev.to/anabujan/manually-install-android-sdk-on-ubuntu-35k1</guid>
      <description>&lt;p&gt;I’ve been a long time only Ubuntu user and just recently formatted my desktop computer and bought a Windows 11. Point being, I made a tutorial on &lt;a href="https://www.amarjanica.com/configure-android-sdk-environment-on-windows-11"&gt;how to configure android sdk on windows&lt;/a&gt; too.&lt;/p&gt;

&lt;p&gt;Instead of using Android studio, I’ll show you how you can install android sdk from the terminal.&lt;/p&gt;

&lt;h2&gt;
  
  
  Install Java
&lt;/h2&gt;

&lt;p&gt;This is the first requirement, I prefer the &lt;a href="https://www.oracle.com/java/technologies/downloads/#java17"&gt;Oracle version&lt;/a&gt;, but feel free to use openjdk if you like.&lt;/p&gt;

&lt;p&gt;Verify the installation with &lt;code&gt;java -version&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;java version "17.0.10" 2024-01-16 LTS
Java(TM) SE Runtime Environment (build 17.0.10+11-LTS-240)
Java HotSpot(TM) 64-Bit Server VM (build 17.0.10+11-LTS-240, mixed mode, sharing)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you happen to get a different java version than the currently installed, you can always fix it by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo update-alternatives --config javac
sudo update-alternatives --config java
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And I also suggest setting up the JAVA_HOME. Edit &lt;code&gt;.profile&lt;/code&gt; and set:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export JAVA_HOME="/usr/lib/jvm/jdk-17-oracle-x64"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save file, run&lt;code&gt;source ~/.profile&lt;/code&gt; to update your current environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Get just the command line tools&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;These tools will help you do anything you need just from the command line, most importantly installing the sdk. Go to &lt;a href="https://developer.android.com/studio"&gt;https://developer.android.com/studio&lt;/a&gt; and scroll down to command line tools, download.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DZ7r1VlD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.amarjanica.com/wp-content/uploads/2024/03/commandlinetools-1024x440.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DZ7r1VlD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.amarjanica.com/wp-content/uploads/2024/03/commandlinetools-1024x440.png" alt="command line tools, manual sdk install" width="800" height="344"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Install the SDK
&lt;/h2&gt;

&lt;p&gt;Extract your tools somewhere, and first run a small configuration as suggested by &lt;a href="https://stackoverflow.com/a/71331807"&gt;https://stackoverflow.com/a/71331807&lt;/a&gt; to avoid the “could not determine SDK root” error.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;unzip commandlinetools-linux-&amp;lt;your_version&amp;gt;.zip 
mv cmdline-tools ~/android-sdk/latest
cd ~/android-sdk/latest/cmdline-tools
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run this command from the cmd line tools to install version 34 of api and tools:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;./sdkmanager "platform-tools" "platforms;android-34" "build-tools;34.0.0"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can always see what’s available to install with &lt;code&gt;sdkmanager --list&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Declare paths and environment variables
&lt;/h2&gt;

&lt;p&gt;To be able to access platform-tools and cmdline-tools from anywhere, set up the env variables.&lt;/p&gt;

&lt;p&gt;Edit .profile and add:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export ANDROID_HOME=$HOME/&amp;lt;location-of-sdk&amp;gt; # where did you extract the sdk?
export PATH=$PATH:$ANDROID_HOME/cmdline-tools/latest/bin
export PATH=$PATH:$ANDROID_HOME/platform-tools
export PATH=$PATH:$ANDROID_HOME/emulator
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save file and run source .profile to propagate the changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Verify Installation
&lt;/h2&gt;

&lt;p&gt;If everything went smoothly, &lt;code&gt;adb version&lt;/code&gt; should give you something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Android Debug Bridge version 1.0.41
Version 34.0.1-9979309
Installed as /usr/bin/adb
Running on Linux 5-15-0-97-generic (x86_64)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Last Part&lt;/p&gt;

&lt;p&gt;If you need an emulator, install system images and create an AVD (Android Virtual Device):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sdkmanager "system-images;android-34;default;x86_64"
avdmanager create avd -n testDevice -k "system-images;android-34;default;x86_64"

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check that your testDevice is in the list and run the emulator&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;emulator -list-avds
emulator @testDevice
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Fun with Ubuntu
&lt;/h2&gt;

&lt;p&gt;I said at the beginning of the article, things don’t go as smooth as they should.&lt;/p&gt;

&lt;h3&gt;
  
  
  NoClassDefFoundError
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://stackoverflow.com/questions/46402772/failed-to-install-android-sdk-java-lang-noclassdeffounderror-javax-xml-bind-a"&gt;Failed to install android-sdk: “java.lang.NoClassDefFoundError: javax/xml/bind/annotation/XmlSchema”&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This SO provides a solution, I just wanted to add this kind of thing happens when sdk is downloaded via Android Studio and the included avdmanager is deprecated. You will not have this issue if you installed this manually.&lt;/p&gt;

&lt;h3&gt;
  
  
  Deprecated Java Version
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;has been compiled by a more recent version of the Java Runtime (class file version 61.0), this version of the Java Runtime only recognizes class file versions up to 55.&lt;/strong&gt;0&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This error only occurs if you have multiple java versions installed and have not configured the system properly. In my case it was java compiler pointing to the oracle java 8 version.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# this is correct
&amp;gt; java -version
openjdk version "11.0.21" 2023-10-17
OpenJDK Runtime Environment (build 11.0.21+9-post-Ubuntu-0ubuntu122.04)
OpenJDK 64-Bit Server VM (build 11.0.21+9-post-Ubuntu-0ubuntu122.04, mixed mode, sharing)
&amp;gt; javac -version
javac 1.8.0_171
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can fix it by running the command below and picking the newer version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo update-alternatives --config javac
There are 2 choices for the alternative javac (providing /usr/bin/javac).

  Selection Path Priority Status
------------------------------------------------------------
* 0 /usr/lib/jvm/java-11-openjdk-amd64/bin/javac 1111 auto mode
  1 /usr/lib/jvm/java-11-openjdk-amd64/bin/javac 1111 manual mode
  2 /usr/lib/jvm/java-8-oracle/bin/javac 1081 manual mode

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  INSTALL_FAILED_UPDATE_INCOMPATIBLE
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;adb: failed to install .apk: Failure [INSTALL_FAILED_UPDATE_INCOMPATIBLE: Package your.package signatures do not match previously installed version; ignoring!]&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Error message is explanatory enough, solution is to uninstall your.package. This error might happen if you’re running expo android on your actual device, which had another version of your.package installed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;adb uninstall your.package
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Extra
&lt;/h2&gt;

&lt;p&gt;I’ve already covered setting up the SDK and troubleshooting common issues. This is just an extra section which applies to any OS platform: be it Linux, Windows or MacOS.&lt;/p&gt;

&lt;p&gt;While you’re developing you’ll want to run your app on the emulator and real device, be able to communicate with other api services, debug…&lt;/p&gt;

&lt;h3&gt;
  
  
  Communicating with services
&lt;/h3&gt;

&lt;p&gt;While you’re developing your app and testing either on your emulator or your device, you might need to access your local api. Localhost won’t do. Check that you’re on the same wifi, that your api is on 0.0.0.0 or more restrictive 192.x.x.x (whatever ip is written in your network settings).&lt;/p&gt;

&lt;p&gt;Other solution would be to use a service like &lt;a href="https://ngrok.com/"&gt;ngrok&lt;/a&gt;, but then your api is open to the world if they manage to guess your ngrok url.&lt;/p&gt;

&lt;h3&gt;
  
  
  Adb device permission issues
&lt;/h3&gt;

&lt;p&gt;Check that you have enabled development mode and usb debugging. Connected device should use usb for data transfer.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Try a different usb port&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;adb usb&lt;/code&gt; command restarts the adb server and forces it to listen for USB connections, which can also help in resetting the USB interface for ADB.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Debugging Logs
&lt;/h3&gt;

&lt;p&gt;Very useful when you’re running your app on an emulator or the device, expo logs will not be enough at times. Their errors are sometimes too cryptic. You can use &lt;code&gt;adb logcat -e your.pack&lt;/code&gt;age to see what’s actually going on.&lt;/p&gt;

&lt;h3&gt;
  
  
  Running the emulator from virtualbox
&lt;/h3&gt;

&lt;p&gt;While I was recording my youtube video, I was running Ubuntu from Virtualbox. I tried running the emulator from virtualbox, but error kept saying “missing hardware acceleration”.&lt;/p&gt;

&lt;p&gt;You can run the emulator, just add “–no-accel”. No reason why you would want that because it’s extremely slow, but just pointing it’s doable.&lt;/p&gt;

</description>
      <category>uncategorized</category>
    </item>
    <item>
      <title>Have I Been Hacked?</title>
      <dc:creator>Ana Bujan</dc:creator>
      <pubDate>Thu, 07 Mar 2024 16:24:35 +0000</pubDate>
      <link>https://dev.to/anabujan/have-i-been-hacked-4kon</link>
      <guid>https://dev.to/anabujan/have-i-been-hacked-4kon</guid>
      <description>&lt;p&gt;I’ve been interested in this topic for a while, that is how secure my data on the cloud is.&lt;/p&gt;

&lt;p&gt;I always assume it’s hard to hack me. I’m a professional developer, not naive, not lazy, I don’t even know my own passwords, I rotate them, use 2FA…&lt;/p&gt;

&lt;p&gt;Nonsense! Actually, anyone who uses the internet is at risk of having some of their data taken without their knowledge and sold to interested parties.&lt;/p&gt;

&lt;p&gt;Actually I got inspired to finally write this post after getting a phishing call from a representative of a popular Croatian health insurance company, speaking in bad Croatian, asking me why am I not paying my bills. This was a funny and short call, but got me thinking…&lt;/p&gt;

&lt;h2&gt;
  
  
  Is my Phone Eavesdropping on me?
&lt;/h2&gt;

&lt;p&gt;It must have occurred to you at one point of your life that your phone is listening to your conversations or at least your friends and relatives have a theory about that.&lt;/p&gt;

&lt;p&gt;Let’s forget that Google knows too much about you, and imagine a scenario where you’re in a café, watching someone across drinking some interesting beverage, and you decide to google what it is… But no, advertisements have already beat you, they know what you want before you’ve even typed in the search term.&lt;/p&gt;

&lt;p&gt;I won’t go too much into this topic, as I’m not an expert. Maybe your phone really is “eavesdropping” on you, or maybe the systems have such advanced algorithms that they can predict what you want better than you can yourself.&lt;/p&gt;

&lt;p&gt;As soon as you use a phone and the internet, some of your data is already shared. After all, do you ever read the terms of use of an application? What did you agree to when you logged into Facebook?&lt;/p&gt;

&lt;h2&gt;
  
  
  The Double-Edged Sword of Complex Authentication
&lt;/h2&gt;

&lt;p&gt;I’m talking about classic data theft: email, password, phone number, firstname/lastname.&lt;/p&gt;

&lt;p&gt;For instance, I never use the same password, and I don’t even know it myself. But what does that mean? These passwords that I don’t know are stored somewhere on a remote server, that’s a potential issue isn’t it?&lt;/p&gt;

&lt;p&gt;If you’re serious about authentication, you’ll enable what’s called a two factor authentication (2FA) everywhere.&lt;/p&gt;

&lt;p&gt;The problem with 2FA authentication is that those details are temporarily stored on some remote server. If you’ve chosen SMS for your 2FA, you should be aware that 2FA authentication might be outsourced to an external company. You might have heard about the recent leak of 2FA databases &lt;a href="https://www.forbes.com/sites/daveywinder/2024/03/06/millions-of-google-whatsapp-facebook-2fa-security-codes-leak-online/"&gt;https://www.forbes.com/sites/daveywinder/2024/03/06/millions-of-google-whatsapp-facebook-2fa-security-codes-leak-online/&lt;/a&gt;. The news might be a bit exaggerated since after all, 2FA codes are short-lived. It requires a combination of factors for a hacker to have your password, access to the fresh 2FA database, you are interesting enough for them to spend their time on you, and the stars align for them to access your data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sale of personal data
&lt;/h2&gt;

&lt;p&gt;But what else can happen, your data gets sold to shady characters who want to sell you something or extract something from you, at best, money or even more data about you.&lt;/p&gt;

&lt;p&gt;Take me, for example, I haven’t changed my phone number in like forever.&lt;/p&gt;

&lt;p&gt;Maybe I should treat my phone number the same way as passwords, rotate it periodically.&lt;/p&gt;

&lt;p&gt;What’s the problem? Among the hacked data, there often is the mobile number. If you’ve ever entered your mobile number on any account, it’s possible that there will be a data leak, and you’ll start receiving strange calls from abroad.&lt;/p&gt;

&lt;p&gt;Maybe it’s “just happening to me”, but occasionally I get calls where the person only knows my name and wants to sell me something. Sometimes these calls come from local numbers 091, 095, etc. But don’t be fooled that it’s a local number; the number can still be from abroad. It’s masked to appear as a local number.&lt;/p&gt;

&lt;p&gt;What can you do in that case?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Report the incident to your mobile network provider? Good luck! I’ve done that several times. They don’t know what to say. The best answer is to try to ignore it. Even checking the mobile number makes no sense because often the call is not made from that number, it just appears to be.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Install an app that blocks known spammers &lt;a href="https://www.truecaller.com/"&gt;https://www.truecaller.com/&lt;/a&gt;? I have it, the paid version. It works decently, the database is constantly updated. It won’t stop all the calls though.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Change the number?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Data breach registry
&lt;/h2&gt;

&lt;p&gt;This website might be of interest to you &lt;a href="https://haveibeenpwned.com/"&gt;https://haveibeenpwned.com/&lt;/a&gt; to see how much of your data has leaked out. You might wonder what if this website also stores your email. Read &lt;a href="https://haveibeenpwned.com/Privacy"&gt;https://haveibeenpwned.com/Privacy&lt;/a&gt; and decide for yourself. This site has been checking for security breaches since 2013.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recognizing phishing and saving the nigerian prince
&lt;/h2&gt;

&lt;p&gt;I assume that most of the phishing attacks are very easy to recognize. But it’s only the case I’ve been trained well and years of experience.&lt;/p&gt;

&lt;p&gt;I remember in the 2000’s I’d get emails from nigerian princes promising me large sums of money. I’d find them funny and thought how anyone would get fooled by these silly emails. That was the old era.&lt;/p&gt;

&lt;p&gt;What hasn’t changed is that at one point they’ll all ask you for money by promising you things or threatening you, whatever works.&lt;/p&gt;

&lt;h3&gt;
  
  
  Email and web phishing
&lt;/h3&gt;

&lt;p&gt;Usually websites and emails have grammar errors. This will improve in future, scammers know how to use ChatGPT too. Scam websites are often good copies of the real deal, and average Joe won’t think to look at the funky url or funky email, or know how to check the “show original” in the email he’s received.&lt;/p&gt;

&lt;h3&gt;
  
  
  Phone phishing calls
&lt;/h3&gt;

&lt;p&gt;This is easy to spot in my case. One tell sign is if the caller speaks english or very bad croatian. I work with foreign clients, but all means of communication are over slack, google meet, zoom…you get the picture. One exception to the rule, I’ve noticed people from UK I’ve communicated with prefer phone calls.&lt;/p&gt;

&lt;p&gt;Other tell sign is, caller introduces him and asks me how am I?&lt;/p&gt;

&lt;p&gt;Like how dare he?! Asking me how am I doing. But seriously, I’d expect introduction who’s calling, why he’s calling, and then they can ask me “how are you”. Otherwise, it’s going to be a short call.&lt;/p&gt;

&lt;p&gt;Third tell sign is, the short connection pause, maybe 2 seconds after I answer the call, before the caller starts talking. I’ve noticed it so far on all calls. It’s like they’re doing many calls at once, so first fool that answers will be routed to the scamming agent. I think there’s some automation going on here, if you get these kinds of calls try not answering for 2 seconds. See what happens.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;There’s no smart conclusion here, just sharing some of my thoughts. I remember, long ago at a company where I worked, they were quite serious about security: everything was done through a VPN and emails were sent exclusively in encrypted form.&lt;/p&gt;

&lt;p&gt;Maybe encrypting emails seemed a bit too much to me back then, but now I see it really isn’t.&lt;/p&gt;

&lt;p&gt;When you use a service, you’re not just using it alone; your data goes through several different services. Ideally, all this should be mentioned in the terms of use and privacy.&lt;/p&gt;

&lt;p&gt;Don’t be lazy, don’t use the same password everywhere. Don’t enter your mobile number unless it’s absolutely necessary. Read the privacy terms.&lt;/p&gt;

&lt;p&gt;Thank you for reading!&lt;/p&gt;

</description>
      <category>phishing</category>
      <category>privacyprotection</category>
      <category>datasecurity</category>
    </item>
    <item>
      <title>Frontend for the email adventures</title>
      <dc:creator>Ana Bujan</dc:creator>
      <pubDate>Mon, 03 Jul 2023 13:40:36 +0000</pubDate>
      <link>https://dev.to/anabujan/frontend-for-the-email-adventures-57np</link>
      <guid>https://dev.to/anabujan/frontend-for-the-email-adventures-57np</guid>
      <description>&lt;p&gt;If you stumbled upon this article and have to do frontend for the email, my deep condolences.&lt;/p&gt;

&lt;p&gt;Take a deep breath and try not to lose it because world of email design feels like the Upside Down to the rest of the web.&lt;/p&gt;

&lt;p&gt;I’m really new to this world, and I’m just posting what I’ve learned when playing with email templates.&lt;/p&gt;

&lt;p&gt;I could be wrong, and please correct me in the comments.&lt;/p&gt;

&lt;p&gt;Frontend for the email wasn’t my first choice, I tried Mandrill first as I needed transactional emails. But Mandrill wasn’t very useful when it comes to email templates and advanced use with handlebars. I did manage to make it work, but decided to do my own because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;it’s easy to make a mistake and you won’t know it, mailchimp will sanitize your placeholders&lt;/li&gt;
&lt;li&gt;mandrill html editor is not user friendly. I can’t use the pretty mailchimp because it doesn’t do much for me when I need to mess with html.&lt;/li&gt;
&lt;li&gt;versioning problem – ok, you’ve got your production, you tell your colleague to do a change, he makes a mistake. It doesn’t work. Of course this is not a mandrill fault, but something to consider where you’re willing to spend your resources.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And when ditching mailchimp and mandrill, I’ve come to know wonderful world of frontend for the email.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Guess what? Rendering html in your browser and email clients is a completely different story. There are more limitations for the email client.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Web Fonts
&lt;/h2&gt;

&lt;p&gt;Buggy, stick with web safe fonts. That will be the least of your issues and here’s a good comparisment article &lt;a href="https://www.litmus.com/blog/the-ultimate-guide-to-web-fonts/"&gt;https://www.litmus.com/blog/the-ultimate-guide-to-web-fonts/&lt;/a&gt;. You can still use web fonts like google fonts, but be aware that some email clients will render the fallback font.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Ibc1Cl-b--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.amarjanica.com/wp-content/uploads/2023/07/Screenshot-from-2023-07-03-14-37-03-1024x570.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Ibc1Cl-b--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.amarjanica.com/wp-content/uploads/2023/07/Screenshot-from-2023-07-03-14-37-03-1024x570.png" alt="" width="800" height="445"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Html &amp;amp; Css
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Stylesheets&lt;/strong&gt; might work, or email client might strip it from the head. Using ugly inline styles is a sure bet.&lt;/p&gt;

&lt;p&gt;Forget about some css selectors you’re used to, absolute positioning and negative margins.&lt;/p&gt;

&lt;p&gt;As for &lt;strong&gt;html&lt;/strong&gt; , you will mostly have to deal with table tags as standard css positioning in email clients just won’t work or mail client might strip your positioning css instructions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Responsive design&lt;/strong&gt; will require more testing, not covered in some email clients. &lt;a href="https://www.caniemail.com/search/?s=media"&gt;https://www.caniemail.com/search/?s=media&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I’d suggest you take a look at &lt;a href="https://www.caniemail.com/"&gt;https://www.caniemail.com/&lt;/a&gt; to know exactly which limitations are there for your email template.&lt;/p&gt;

&lt;h2&gt;
  
  
  Images
&lt;/h2&gt;

&lt;p&gt;If you wanted to render an image in your email template, would you:&lt;/p&gt;

&lt;p&gt;a) Try to inline a base64 image with data uris&lt;/p&gt;

&lt;p&gt;b) Embed an image from email attachment&lt;/p&gt;

&lt;p&gt;c) Link to external source&lt;/p&gt;

&lt;h3&gt;
  
  
  a) Images as data uris
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;img src="data:image/png;base64,..."/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I can tell you right now, this option will not work in most of email clients. I’ve seen some hacks that should work where base64 is included as a background. Tried it, gmail striped everything in the url. Gmail also doesn’t like base64 in img src attribute.&lt;/p&gt;

&lt;h3&gt;
  
  
  b) Inline attachment images
&lt;/h3&gt;

&lt;p&gt;Option b can be ok if you don’t have a lot of images, and it will work. There are issues with it that I’ll address after posting a cheat sheet on sending email with ses client in node.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const client = new SESClient({});
const composer = new MailComposer({
        subject: 'my subject,
        html: `&amp;lt;!doctype html&amp;gt;
&amp;lt;html&amp;gt;&amp;lt;body&amp;gt;&amp;lt;img src="cid:att"/&amp;gt;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;`,
        attachments: [
          {
            contentDisposition: "inline",
            cid: "&amp;lt;uniqueid@somedomain.com&amp;gt;", // any kind of unique id, but has to be followed by `@yourdomain`
            encoding: "base64",
            contentType: "image/png",
            content: fs.readFileSync(
                path.join(__dirname, "attachment.png")
              )
              .toString("base64"),
          },
        ],
      });
      const rawMessage = await composer.compile().build();

      const command = new SendRawEmailCommand({
        Destinations: ["dest@example.com"],
        RawMessage: {
          Data: rawMessage,
        },
        Source: ["from@example.com"],
        SourceArn: "&amp;lt;&amp;gt;",
      });

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This technique is often used to include images in HTML emails where the image data is sent along with the email itself, instead of being loaded from an external URL. The advantage of this approach is that the image can be displayed even if the recipient’s email client blocks external images or if the recipient is offline when they open the email.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you are not referencing the cid in the html, email client will show your attachment in the attachments list.&lt;/strong&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  More bandwidth usage
&lt;/h4&gt;

&lt;p&gt;Problem with this technique is that it uses more bandwidth. This can be an issue if you’re sending a large number of emails with attachments or if your recipients have limited or metered internet connections.&lt;/p&gt;

&lt;p&gt;If you use aws services, where you know aws charges everything, there will be more cost introduced with more bandwidth usage.&lt;/p&gt;

&lt;h4&gt;
  
  
  Email size Limit
&lt;/h4&gt;

&lt;p&gt;Email has a size limit, its 25mb. You probably won’t get there, but keep this in mind.&lt;/p&gt;

&lt;h4&gt;
  
  
  Choosing a CID has to be in a particular format!
&lt;/h4&gt;

&lt;p&gt;This part is important because it will save you nerves when you discover that your images don’t render in all email clients! That’s because Content-ID has to be an RFC 2822 compliant, e.g:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;uniqueid@domain.com&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Otherwise some mail clients might choose not to display your image.&lt;/p&gt;

&lt;h3&gt;
  
  
  c) External Images
&lt;/h3&gt;

&lt;p&gt;Problem with option c is that most email clients initially block external images, but you’ll save on bandwidth and get original image quality (I’ve read somewhere that mail client might decide to compress your attachments). Also, images in solution b are visible offline, while external will not be visible. Pro for using external images is that you won’t lose quality, while attached images may be compressed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rendering Emails
&lt;/h2&gt;

&lt;p&gt;Rendering emails feels like rendering in different kinds of browsers a decade ago.&lt;/p&gt;

&lt;p&gt;Your email won’t necessarily render the same in each email client and you will have to tinker with your template.&lt;/p&gt;

&lt;p&gt;I recommend previewing your emails in &lt;a href="https://www.litmus.com/"&gt;Litmus&lt;/a&gt;, where you can send and test your email previews in every single email client. If you’ll have issues rendering inline attached images for iOS in Litmus, I think Litmus has a bug or a rendering timing issue. Images do render on the real device, and Litmus ios emulator still won’t load them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This is just a small intro into html design pitfalls, I am not an expert in anyway. 2 weeks of research, trial and error. I hope some of my insights help.&lt;/p&gt;

&lt;p&gt;Recommended links:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.litmus.com/blog/the-ultimate-guide-to-web-fonts/"&gt;The ultimate guide to web fonts&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.caniemail.com/"&gt;Can I email&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.litmus.com/"&gt;Render email template in different email clients&lt;/a&gt;&lt;/p&gt;

</description>
      <category>emaildesign</category>
    </item>
  </channel>
</rss>
