All posts by admin

Why we can’t receive push notifications from expo after using ‘expo eject’ for iOS standalone

Originally, we wanted to see if using ‘expo eject’ (with option ‘use Expo SDK’) will be able to eject an iOS standalone app where it can successfully receive Expo notifications.

Our trial indicates that is not possible.

In the original RN code where we have Expo API attached, right after we log in, we use Notifications.getExpoPushTokenAsync (imported from expo), to get a valid push token. That is how the Expo Notification server can push towards iOS and Android devices.

However, in the expo ejected iOS client, we ran into an error while trying to get this push token. Specifically the error says “unsupported URL”. This is probably because it does not recognize the url of our iOS client.

Hence, in order to apply native receive push notifications, and then pass that data into RN, we must use:

1) ‘expo detach’
2) use RCTPushNotificationManager for iOS client
3) use PushNotificationIOS library from React Native to retrieve notification data

Security Issues for iOS

Security Issues

2.1.1 (User refresh token located in manifest.json)

All the sensitive data have to be stored in secure manner, for example using encrypted SQL storages, keychain or Secure Enclave.
done in React Native.

2.1.2 (Authentication response cached in database in plain text)

All the sensitive data have to be stored in secure manner, for example using encrypted SQL storages, keychain or Secure Enclave.

not done

2.1.3 (SSL pinning is not implemented)

done

2.1.4 (App screenshot information disclosure)

To protect sensitive data, block caching of application snapshots using API configuration or code.

done

2.1.5 (App Transport Security (ATS) is disabled)


done

2.1.6 Application does not clear cached data after logout

Caching functionality helps to operate application with data more reliable in terms of performance, but have to clear it in certain scenarios, one of them is logout.

done

2.1.7 (Application permissions have to be reviewed)
2.1.8 (Application contains DEV setting plist)

should be done when EXPO is removed

2.1.9 (No source code obfuscation)
2.1.10 (can run on jailbroken phones)

not sure

Remove data in your Cache folder

First let’s look at the contents of your cache folder. Notice the use of NSCachesDirectory macro.

[0] [15:12:53] fsCachedData
[0] [15:12:53] Users
[0] [15:12:53] Cache.db-shm
[0] [15:12:53] Cache.db-wal
[0] [15:12:53] Cache.db

and they are located in:

/Users/rickytsao/Library/Developer/CoreSimulator/Devices/F19D977F-B37C-4DA5-98DA-6C1B2ADCD500/data/Containers/Data/Application/44CF2644-6491-4A4A-9A5C-9DA0F405A45E/Library/Caches/com.rocktree.app/

source code to do this:

Device.h

Device.m

Call the code in React Native

ProfilesDetailsScreen/index.js

Import NativeModules from react native

In the log out handler, call the bridge function.

Thus, when you log out, it bridges to the iOS module. the iOS module manages to access its cached data and remove whatever was saved there.

Snapshots

snapshots:
https://stackoverflow.com/questions/7520076/prevent-ios-from-taking-screen-capture-of-app-before-going-into-background

place overlay image when the app is about to resign. and remove this overlay when its about to become active.

Pros, cons, and hows of React Native

ref – https://hackernoon.com/understanding-react-native-bridge-concept-e9526066ddb8

Does not depend on Webview, uses native APIs

React Native is often presented as a game changer that allows to run JavaScript code inside a mobile environment. Its main strength is that it doesn’t rely on Webviews like other competitors (Phonegap, Ionic, Cordova…), but on the actual real materials provided by the different platforms.

In other words, unlike Cordova, PhoneGap, and other cross-platform frameworks that render code via WebView, React Native renders certain code components with native API’s.

It has built-in access to all the native views and components, and to about 70 specific device APIs by default (you can extend it).

When writing React Native apps, we build native UIs. And that’s the key point, we create UIView instances just like we would have with the iOS platform.

Uses existing compilers to create apps for specific platforms

Currently, there are compilers that target their own specific platform. For example, we have compilers that accept Java / Kotlin code and target Android platform, or Obj-C / Swift targeting iOS platform.

There exists many compilers for different languages and targets. React Native is built in such a way that it uses these existing compilers to create apps for that specific platform.

No only can React Native create apps for mobile platforms such as Android and iOS, it can also use compilers to create apps for Desktop, Virtual Reality, and much more.

How was it done?

React Native deals with two realms, the JavaScript one and the Native one. Both of them are able to share information. They communicate using a “bridge”, which is definitely the very heart of the React Native architecture, the part that offers so much flexibility.

The bridge is the concept that provides a way for bidirectional and asynchronous communications between these two universes. What’s important here is that they are completely written in different technologies, but they are able to communicate.

When two services written in different languages communicate, they do so by using interoperable languages, such as JSON or XML, and relied on an async protocols and a message queue. Service A pushes some commands inside the queue and service B has to execute these commands when possible.

If we want these two services to communicate, we rely on a message queue. The first service pushes some commands inside the queue and the other one has to execute these commands when possible.

React Native behaves the same way. The JavaScript realm sends asynchronous JSON messages describing the action the Native part is supposed to accomplish.

For example, the JavaScript side will send information concerning the views that must be created by the Native side. When the Native side is ready, it will effectively create the views:

In React Native, the bridge endorses the message broker role, handling asynchronous commands between the two different worlds.

The bridge is built in C/C++ and thus, can be run on multiple platforms, OS etc…

It embeds the Apple JavaScriptCore framework in, which exposes APIs for your code to access the actual
Javacript Core VM capabilities.

With this in mind, React Native can inject variables, functions and declare globals to enhance the JavaScript existing code as shown at the first 3 steps here:

Then once the JS code is injected into the API, the C++ platform then queues them for deliver.

On the other side, you’ll see that we have our compiler/platform combinations. As long as the JS code is injected into the C++ platform, and then gets queued, we can switch out the compiler/platform like a puzzle in order to different type of apps.

Other advantages

– Maximum code reuse & cost saving. React Native’s component-based structure allows developers to build apps with a more agile, web-style approach to development than most hybrid frameworks, and without any web at all.

– If you know JavaScript, React Native will be easy to pick-up, allowing most front-end web developer to be a mobile developer. All you need to know is JavaScript, platform APIs, some native UI elements, and any other platform-specific design patterns and you’re set.

– Native look and feel of the app.

– Performance measurements between React Native exported app and the native app are very similar (https://medium.com/the-react-native-log/comparing-the-performance-between-native-ios-swift-and-react-native-7b5490d363e2)

– Native app development usually means inefficiency, slower time to deployment, and less developer productivity. React Native is all about bringing high speed, responsiveness, and agility of web app development along with effectual processing and best user experience to the hybrid space, to provide your users with a native app experience.

Disadvantages

It Lacks the Security Robustness

We know that React Native is a JavaScript library and open-source framework, which creates a gap in the security robustness.

But at times, you need to provide extra security specifically if you are creating banking and financial apps where data is highly confidential. So, in that cases, experts advice not to choose React Native.

React Native is Still New and Immature

React Native is newbie as compared to other Android and iOS programming languages. It is still in its improvement stages.

One of the areas where it lacks consistency is regarding the release of the frequent updates, which at times are confusing for the developers. This is because every time a new update is released, the developers have to make a lot of changes and make regular upgrades. Popular app Airbnb faced a lot of problems in the upgrading.

Latest Native code

Native developers are sometimes required to write the latest native code that we were not updated for that version of React Native.

Modules

Despite the constant advancement of RN technology, it does not provide ready-to-use modules that give access to iOS or Android APIs. This forces developers to create so-called Native Modules themselves or develop “bridges” using Java/Kotlin (Android) or Swift/Objective-C (iOS) and severely increases software development time. Native technologies require no such thing. The same goes for native frameworks, libraries or SDKs — if you want to employ Augmented Reality, voice assistants or SDK for mobile payments, again, you’ll need the aforementioned bridges. This will require you to hire three developers instead of two as it was in the case of Airbnb that had to learn about it the hard way.

Recommended Usage

Distribute IPA file to the Apple app store

ref – https://appmanager.io/blog/tips-and-tricks/uploading-an-ios-app-to-the-app-store-updated/
https://help.swiftic.com/hc/en-us/articles/201697821-Install-the-Application-Loader-on-Your-Computer

Client Side upload app to the Store

…after receiving the IPA file from your developer, go to your Apple account.

Log in, and choose the Agreements, Tax, and Banking section. Before publishing an app you’ll have to accept some of those agreements and set up your banking info so you can get paid. You’ll also need to set up tax info, depending on your country.

If you already have an App Store Connect account, make sure that your role is Admin, Technical, App Manager, or Developer. Only those roles can upload a build.

When your app is ready to upload, you can add the app to App Store Connect. (You should probably tag it in your version control first.)

In App Store Connect go to the My Apps section and hit the plus sign on the left side to create a new app. You’ll get a little form to fill out with your app’s info:

Hit Create andApp Store Connect will create a record for your app. Look on the left hand side and select the 1.0 release under iOS App. Scroll down to the build section. This is where you’ll be able to see your uploaded app.

You can use Application Loader to submit your app for review if you’re getting a build from a developer (in ipa format) and don’t have Xcode installed. You’ll still need a Mac since that’s the only operating system Application Loader runs on.

If you want to try out Application Loader and don’t have Xcode installed, get it from Resources and Help section of App Store Connect.

When you have found the Application Loader from the Resources > Help Section, simply install it and upload your ipa file. Then, you are done.

However, if you do have Xcode installed, you can access Application Loader under the Xcode -> Open Developer Tool menu.

Uploading the Build – Since we already set up the app in App Store Connect and Xcode knows about our dev account, it’ll know where to put it when we upload it.

Open your project in Xcode. Select Archive in the Product menu. Choose Save for iOS App Store Distribution. That’ll create the build to be submitted.

To upload your app, click on the big blue Upload to App Store button on the right side. You’ll have to confirm for Xcode that it’s going to upload the app to the right place. If you’re on multiple iOS dev teams, you’ll have to pick the one it should use. When Xcode has it all figured out, it’ll show you a summary screen. Click the Upload button.

Developer upload app

Another way to upload the app is through a developer.

First make sure to create an archive. After that you should see the archive on your list. Select the archive from the list and click the Upload to App Store… button on the right. The application binary is then uploaded to Apple’s servers.

During this process, your application is also validated. If an error occurs during the validation, the submission process will fail. The validation process is very useful as it will tell you if there is something wrong with your application binary that would otherwise result in a rejection by the App Store review team.

Just go with the default values…

Certificate

If the certificate associated with the app does not align with your computer, there will be an error. You can request from that user to get a public certificate for you to use.

If you want to create your own certificate from your computer and generate your own provisioning profile, then on:

In your Apple account, when you get provisioning profiles, you need to register a certificate first. Certificates are files generated by your computer’s Key chain.

You will need to create this Certificate (CSR file) to give to Apple.

To manually generate a Certificate, you need a Certificate Signing Request (CSR) file from your Mac. To create a CSR file, follow the instructions below to create one using Keychain Access.

Create a CSR file, copy and pasted from wizard page
In the Applications folder on your Mac, open the Utilities folder and launch Keychain Access.

Within the Keychain Access drop down menu, select Keychain Access > Certificate Assistant > Request a Certificate from a Certificate Authority.

In the Certificate Information window, enter the following information:
In the User Email Address field, enter your email address.
In the Common Name field, create a name for your private key (e.g., John Doe Dev Key).
The CA Email Address field should be left empty.
In the “Request is” group, select the “Saved to disk” option.
Click Continue within Keychain Access to complete the CSR generating process.

Once, you’ve successfully created it, save the .certSigningRequest file on your computer.

On the next screen, then you will see Generate your Certificate page. Upload the .certSigningRequest file, and click Generate.

You will then see that your Certificate is ready.

Name: Apple Development iOS Push Services: com.rtsao.deleteTestPush
Type: APNs Development iOS
Identifier ID: deleteTestPush
Expires: Dec 01, 2016

Click download and you should see a .cer file

That’s about it. When you’ve reached to the end of the wizard, you’ll have a chance to turn the app in and then wait about 2 weeks for the approval.

How to create an component

https://facebook.github.io/react-native/docs/navigation
https://reactnavigation.org/docs/en/stack-navigator.html
https://reactjs.org/docs/react-component.html
https://flaviocopes.com/react-state-vs-props/

The Navigation Stack

In App.js, we create a bottom navigator. It takes a parameter of an object where each key is the string title of the tab.
In our case, it is ‘Home’, ‘Contracts’, ‘Schedule’, ‘Reports’.

the keys matches to an object value returned by function createStackNavigator.
createStackNavigator creates a stack navigator where one screen can navigate to the next.

Inside the createStackNavigator, we have two important parameters. One is an object of all the components you want to add to the navigation stack. That way you can navigate from one component to the the next. The other parameter is for styling.

Hence, in our example, for the tab ‘Contracts’, we give is a stack of components, along with a styling called stackDefaultNavigationOptions.

In this stack of components, its first page is ContractScreen. Notice CCTVScreen on the bottom. That is the name of our custom cctv component that we want to navigate from other components.

we import cctv component like so:

Navigating to CCTV

First let’s implement the navigating part. We simply create a handler function. In the implementation, we destructure navigation property from this.props.

Then we use ‘navigate’ and give it the string of the component name ‘CCTVScreen’. Finally, we give it an object of transshipment. Now, this object is written like so: {‘transshipment’ : transshipment}, to designate that the property name is ‘transshipment’, and the value is of object transshipment. We all shorthand it into {transshipment}

Somewhere else, you can have a button or some click UI, and then attach this handler function onCCTVclick to it.

CCTV component

Now we see how the component is implemented.

The only method you must define in a React.Component subclass is called render(). All the other methods described on this page are optional.

When called, it should examine:

1) this.props
2) this.state

Using de-structuring, we extract data from these two objects and use them for display.

In the below example, you can see that we extracted cameraViews from this.props. Then used it in a ScrollView to display Images.

In a React component, props are variables passed to it by its parent component. like this:

In this case, FullPerson component will have these properties in its prop object:

this.prop.firstName
this.prop.lastName
this.prop.age
this.prop.color

State on the other hand is still variables, but directly initialized and managed by the component.

Props can be used to set the internal state based on a prop value in the constructor, like this:

Props should never be changed in a child component, so if there’s something going on that alters some variable, that variable should belong to the component state.

Props are also used to allow child components to access methods defined in the parent component. This is a good way to centralize managing the state in the parent component, and avoid children to have the need to have their own state.

for example, in your ParentComponent, you have a centralized place to process data.

Basically, all data must be processed in function processDataHereOnly. Even when your ChildComponent has data, it should process it in your ParentComponent. In order for us to allow child components to access methods defined in the parent component, we pass in the parent component’s function interface using props property processIt.

Then in your ChildComponent, simply pass in data as a parameter into this.prop.processIt, and execute it.

or

in other words, you are also passing data from the child back to the parent.

To pass data from parent to child, use prop.
To pass data from child to parent, pass a callback to the child via prop. In the child component, pass data as a parameter into the callback, then execute it.

How do you consume API in React Native?

https://redux.js.org/api/applymiddleware
https://redux.js.org/api/combinereducers
https://stackoverflow.com/questions/35622588/how-to-reset-the-state-of-a-redux-store
https://react-redux.js.org/using-react-redux/connect-mapstate
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment
https://redux.js.org/api/store

We consume data the web API and retrieve data through utility function request. We then pass the data through actions and reducers, which are hooked up to our singleton store. This ensures consistency. We finally use and expose this data in our components.

Intro

We use React Redux to store data into a singleton store.
We do this through createStore, which takes two parameters: reducer and a Thunk Middleware.

The idea is that middleware is the suggested way to extend Redux with custom functionality. middleware lets you wrap the store’s dispatch method for custom use. Multiple middleware can be combined together, where each middleware requires no knowledge of what comes before or after it in the chain.

Thunk as Middleware

The most common use case for middleware is to support asynchronous actions. It does so by letting you dispatch async actions in addition to normal actions. In our case, we use a Redux Think as middleware.

First, a thunk is a subroutine used to inject an additional calculation into another subroutine. In the case of a
Redux Thunk, they are functions that wrap expressions in order to delay their evaluation.

This delay is achieved in when an action is called it returns a function. This function that is returned can then be called at a later time.

Here is an example of a thunk action.

A higher order function is just a function that either
1) returns a function
OR
2) takes a function as one of its arguments.

Because this function returns another function that takes dispatch as an argument this is an example of a higher order function. When called at a later time, it passes in dispatch, which the inner function uses.

Hence, when we apply thunk as middleware, and pass this into createStore to signify that when we execute an action, we can have it be applied to the store asynchronously via higher order functions via Redux Thunk.

rootReducers

Now, the thing you’ll see is the rootReducer.
Basically we use the redux function combineReducers to combine all of our reducers into one.

The combineReducers helper function turns an object whose values are different reducing functions into a single reducing function you can pass to createStore.

The resulting reducer calls every child reducer, and gathers their results into a single state object. The state produced by combineReducers() namespaces the states of each reducer under their keys as passed to combineReducers()

The combineReducers function returns a function. That function is a reducer that invokes every reducer inside the reducers object, and constructs a state object with the same shape.

Resetting the store:

store

Hence, this is what our store code looks like.

1) We import what we need from redux
2) We import our custom reducer cctv
3) We group our reducers into combineReducers
4) Then as long as the action type is not ‘USER_LOGOUT’, then we return the appReducer for standard action onto the store state.
5) We apply think to our middleware
6) Then pass everything into createStore.

src/store.js

Custom Action for CCTV

We first start at the action functions. Action functions are imported into Component classes to be executed at certain points. Say you want to read data from an API during the loading up of the component, you’ll execute an action function in its componentDidLoad. You want to do an action after a button press, you’ll execute that action function in the button press’s handler.

The action function is just a function so that it does an action. Let’s take a look at action getCCTV. You’ll see that it takes a parameter transshipment object. We want to manipulate the store asynchronously so we use thunk’s dispatch function. We do this through a higher order function where we return an object. This object is called at a later time by Redux where it executes our commands asynchronously.

We import the function request. We also define macros.

src/services/api/CCTV/action.js

Then we define functions that return action objects, with type property.

src/services/api/CCTV/action.js

In getCCTV, we take a transhipment object first, then we return a function definition with parameter dispatch. This dispatch is provided by Redux, and in which we use it to do asynchronously manipulation in our function definition.

1) Thus, we first pass an action object to signify that we’re loading. We call dispatch on this action object.

Our reducer will receive this action object, where action.type is CCTV_DATA_IS_LOADING.
Then it would update the store state’s property in need.

2) Then, we request data from the web api by calling request.
When it comes back with the result, we create an action object with the retrieved data and then define type to be CCTV_DATA. We call dispatch to apply this data to the store via the reducer object.

In this case, our action.type is CCTV_DATA, and action.data is Data from the web API retrieval. This is what will be sent to the Reducer.
Our reducer checks action.type. Once it matches, it will take care of processing that action. It updates the store on the action.data provided.

src/services/api/CCTV/action.js

Custom Reducer for CCTV

Basically our reducer receives an action object from the action file.
We then check action.type, it will have a string macro.
For every string macro, we take care of that case by updating the store.

src/services/api/CCTV/reducer.js

The return means it updates the store object, which then will be used by our component.

Component

ref – https://react-redux.js.org/api/connect#connect

So we import the CCTV action and then assign it to prop object’s property getCCTVAction.
But first, let’s talk about the connect function.

The connect() function connects a React component to a Redux store.

It provides its connected component with the pieces of the data it needs from the store, and the functions it can use to dispatch actions to the store.

Hence, we first define CCTVScreen component as so:

src/scenes/App/CCTVScreen/index.js

You’ll see that we pass CCTVScreen into the connect function via currying.

The connect function does not modify the component class passed to it; instead, it returns a new, connected component class that wraps the component you passed in.

where definition of connect is:

mapDispatchToProps

first look at the object for the parameter mapDispatchToProps?
We basically define dispatch actions to our prop object. These are basically functions you can call.

mapStateToProps

Now let’s look at mapStateToProps.

It is defined as so:

So it needs to pass in a property, which we de-structure from the store object. Since we’re working with cctv, we de-structure property “cctv” from the store. This is because cctv is the name of the reducer we used in the combineReducers function.

Remember in our reducer we have property cameras and isCCTVLoading, so we access them through the variable cctv.

Putting it all together

Thus, we put all of this together, which brings us to a connect function that
1) maps state to your props object
2) maps dispatch actions to your props object
3) connects all of that to your component

Using your actions and state

Remember that our cameraViews property in our props object is cctv.cameras.
Hence we extract that property via destructuring.

our cameraViews is cctv.cameras, where cameras is an array of camera data.
Each camera data contains URL to the camera image, and so forth.

Hence, now that we have our cameraViews array, we’ll use Javascript’s map function to iterate through this array and display the information.

As each camera is processed, we display an Image, and give the URL of the image to the key. Thus, this will successfully display the camera image.

double arrow functions (curry + closure)

When working with es6 js, you’ll see arrow functions like this:

Let’s break it down and see what’s happening.

Let’s process from left to right.

We first have a temp variable add that takes on a function with parameter x and a return expression.

Then we see that the return expression is (y) => x + y, which is a function.
Hence, this usage is a curry function. We return a partial function for continual external use.

In our curry function, the y is a parameter.

Hence, we we combine the two, we get:

The es6 way: