Showing posts with label Mobile. Show all posts
Showing posts with label Mobile. Show all posts

Wednesday, November 8, 2017

Mobile: React Native vs Real Native Apps



Mobile applications have traditionally been written in native languages. Lately, however, hybrid cross-platform frameworks have been gaining market share. The recent swell of React Native’s popularity has raised the question: should developers use React Native for mobile development instead of native app development? 

In the last 4 years, the React Native framework has grown to a community of over 2,000 contributors that averages 300,000+ weekly downloads through npm. Some of the largest companies in the world have embraced React Native, including Facebook, Pinterest, Skype, Uber, and Brex. Its widespread adoption is primarily driven by the convenience of its cross-platform nature and the unique technological approach used to accomplish this.

Despite React Native’s success, many people maintain that traditional native mobile apps are still the way to go. The proponents of native primarily cite its performance advantages and robustness when compared to hybrid alternatives. Tradeoffs exist between both options, and careful consideration is required when choosing between the two technologies. This article will weigh in on the matter by delving into what makes React Native so popular, and explore how it works under the hood. We’ll also look at the pros, cons, and business impacts of each option, giving you the facts worth knowing before making a choice one way or another.

Comparing React Native vs Traditional Native Apps

React Native is written primarily with JavaScript and classified as a “hybrid” framework, meaning that it’s platform-independent. This separates it from traditional apps written in native languages such as Java or Kotlin for Android, and Swift or Objective-C for Apple. Instead, hybrid apps have a single codebase that produces an app that will run on both Android and iOS devices. The benefit to this is obvious: less code and related logistics when compared to writing a pair of native apps using different languages. The drawbacks of hybrids are that they aren’t as performant as their native equivalents, and they sometimes lack the ability to make full use of a device’s resources.

Most hybrid frameworks that you may be familiar with, such as Ionic, Cordova, and Phonegap, rely on what’s known as a WebView to accomplish their cross-platform capabilities. Essentially, they embed a webpage inside a native app and hook into it to integrate with the underlying device. The problem with this is that WebViews, especially when hosting complicated apps, run into performance issues and have other limitations.  

React Native does things a little differently. It doesn’t use WebViews, but rather a system that allows it to render native components (hence the name) from its base JavaScript code. There’s a common misconception that React Native compiles JavaScript down to native languages such as Swift or Java, but that isn’t the case. To get a better understanding, let’s compare the underlying structure of a “Hello World” app featuring a labeled button written in React Native to its equivalent native iOS version:

Native iOS:



React Native:



Now it’s obvious that the native iOS version looks “cleaner”, but that isn’t really a concern here. What’s important is that we see there are no WebViews in use, instead we have a set of native components. The stack of views in the React Native example is simply forming the basic responsive layout of the app, given that React Native uses Flexbox. The performance impact of this is essentially nominal, and well worth it given that the need for WebViews has been removed.

However, there are still some performance concerns worth noting when analyzing how React Native achieves this feat.

How Does React Native Work?

In a React Native app, its JavaScript logic runs in a dedicated thread, while the rest of the app runs in what we’ll call “the native realm”. JavaScript handles the business logic of the application, while the native realm renders the UI and manages device interactions. These two domains rely on something called “the Bridge” to communicate.

The JavaScript thread and the native realm can’t have a direct conversation – they are unable to listen, respond to, or cancel events and operations happening on the opposite side. Instead, they pass serialized messages back and forth via asynchronous message queues. This system “bridges” the gap.

For example, React Native may send a message to the native realm saying “render this button”, to which upon receipt (ie. the next time it checks the message queue), native does. Later on, when the user clicks on this button, native dispatches a message to the JavaScript thread informing it of the action, triggering some associated application logic, which will then result in a UI update being pushed back into the queue for native… and so on.

Due to the disconnected and asynchronous nature of this means of communication, some performance issues can arise. Queues can get bogged down, say for example if the user is rapidly scrolling through a long and complicated list – many “user has scrolled” and “draw this new UI” updates fly back and forth. For a similar reason, animations can also be a point of concern. In reality, most of the time these kinds of performance deficits are negligible to the user; however, they are still something developers need to be aware of so they can be designed around. 

The good news is that initiatives such as the JSI (JavaScript Interface) are in development to replace the Bridge with something better. Developers can also use native modules to supplement their app with truly native code to leverage device-specific functionality or address performance issues. This means that having developers familiar with native on your React Native team can be very beneficial.

React Native continues to evolve, given its popularity and supporting community. It remains a top choice for developers, and warrants consideration for those thinking of building an app.

Comparing React Native vs Native Development

Both approaches to mobile development have notable tradeoffs. It’s important to consider the strengths and weaknesses of each option with respect to an application’s use case and your organization’s structure:

Native Frameworks

Pros

  1. Performance: This is the defining factor when compared to hybrid solutions, native development will always win out. Although React Native has sufficient performance for most use cases, native frameworks are better suited for resource-intensive apps such as those using 3D/AR/VR technology, as well as data or animation-heavy applications.
  2. Device integration: Native gets access to all the capabilities of the underlying device. This means all the abilities of the associated hardware, sensors, SDKs, and platform-specific features are in play. To be concise, it gives more power to the developers to make a better product.
  3. Access to new features: When a platform such as Android or iOS introduces a new capability, developers will have access to it straight away, often even before it makes its way into a public release. This can prove to be advantageous and even provide an edge in cases where the new feature helps to improve the appeal of your app.

Cons

  1. The downsides of native frameworks can be summed up in one word: logistics. Assuming you are targeting both Android and iOS, you have to do most things twice. Two development teams, two codebases, separate testing and deployment pipelines, and so forth. Not only is there a doubling of most work, but the two streams must be kept in sync, requiring additional oversight and planning. New features and changes have to be coordinated and timed together, and problems quickly arise if one side falls behind or diverges from the other. A solid set of processes are required to keep things running smoothly. 
  2. The bottom line is that more time, effort, and money must be expended when compared to hybrid alternatives such as React Native.

React Native Development

Pros

  1. Cross-Platform out of the box: React Native runs on both Android and iOS, allowing you to target both platforms from the output of a single development team and codebase. This means that the associated logistics around planning, development, testing, and deployment are easier. This typically translates into a lower cost and time to market when compared to native, making it the primary benefit of the technology.
  2. Native Modules: To help address performance issues or provide support for platform-specific functionality, native modules can be used to supplement a React Native app. This gives developers the capability to leverage (at least some of) the best of both worlds.
  3. Hot Reloading: React Native supports both Hot and Live Reloading, which means that developers are able to quickly see and test changes as they’re made. The ability to do this without having to manually reload an app and lose its present state is a great productivity boost during development. React’s implementation of hot reloading provides a clear advantage over the often-clunkier development and debugging workflow of native IDEs.

Cons

  1. Performance: As discussed, React Native isn’t the best choice for applications with high-performance requirements – specifically those with graphically intensive or data-heavy workloads. Although mitigations for this (such as native modules or the JSI) exist or are on the horizon, it will always remain as the primary concern.
  2. Developer Awareness: Although often pitched as an alternative to hiring native developers, React Native doesn’t exist in a vacuum. Knowledge of the Bridge versus underlying platforms is needed to avoid performance pitfalls and develop native modules. React Native also does not abstract away the submission, review, and deployment process for the associated Google and Apple stores, so having staff experienced with that procedure is still required. Robust mobile skill sets may be necessary when choosing this path, undercutting some of the purported benefits of the framework’s simplicity. 
  3. Reliance on Maintainers: Developers must wait on maintainers of React Native to address issues and provide support for new features. For example, there is currently (as of early 2020) an ongoing issue with audio recording under some circumstances – this could prove problematic for applications relying on such functionality.
  4. With those caveats under consideration, it’s worth reviewing the different situations where it makes sense to choose one approach over the other.

Picking and Choosing

When to Use Native App Development

  1. You need the performance that native frameworks provide. Particularly if you’re making a game (and not using something like Unity), making use of a device’s 3D/AR/VR capabilities, or are building an otherwise complex application.
  2. You have the resources and processes available to support the logistical demands of running two mobile development streams and keeping them in sync.
  3. You’re targeting a single platform for your app – Android or iOS only, and you don’t expect this to change.
  4. You need direct access to device capabilities that only native can provide.

When to Use React Native

  1. You want to build a cross-platform app with a fairly straightforward use case.
  2. You want to quickly make a prototype or MVP. Even if you’re considering using native development when bringing a product to market, React Native is great for putting something together quickly. This can prove to be a valuable test of the framework’s viability for your given use case – maybe native won’t be needed after all.
  3. You want the logistical benefits that a hybrid framework provides: a single codebase and supporting development process, from which typically stems a reduction in costs.

Conclusion

A mobile app is not just a bunch of lines of code, it’s a business. As such, the decision to choose one path over another is not purely a technical one. The bigger picture and associated implications must be considered when deciding whether React Native or traditional native is to be used as your foundation going forward.

On paper, it seems to make sense to develop natively instead of via an abstracted framework that sits on top of the native realm. Native provides superior performance and gives developers complete access to the capabilities of each device. It’s true that some use cases require this level of control. However, these benefits come at a cost – in the literal sense. The duplication of work and associated logistical effort can be taxing on a business that is not able to support it. With that in mind, it may be the case that an alternative approach is more well-suited to your situation.

With React Native development, in most cases, you get the best of both worlds: lower effort and associated cost and time to market, while still producing a robust and performant app that stands up against its native competition. The React Native framework is often the clear choice for rapid prototyping and the production of MVPs – a process that can serve as an evaluation of whether or not the technology meets the long-term requirements of your project. These benefits make React Native a strong option for a lot of organizations. Still, if you need pure horsepower or have a use case that requires it, native can sometimes remain the way to go.

Ultimately, there is no silver bullet. Careful consideration is required when making such a fundamental decision. Review the benefits and limitations of the choices before you.


Original Post

Tuesday, April 5, 2016

When to use map, flatMap, or for loops in Swift

Use map when you need to transform arrays

let arrayOfNumbers = [1, 2, 3, 4]
let arrayOfString = arrayOfNumbers.map { "\($0)" }

In the context of Array map get an array, applies a transformation function to every element, and returns a new array with the resulting elements. . That's the best use case for map.

Use for loops when there are "side effects"

Without going into details an operation has a side effect if it results in some kind of state changing somewhere, for example changing the value of a variable, writing to disk, or updating the UI. In such case using a for loop is more appropriate.

for number in arrayOfNumbers {
  print(number)
}

And what about flatMap?

When you need to transform the contents of an array of arrays, into a linear array use flatMap:

let users: [User] = ...
let allEmails = users.flatMap { $0.emails }

p/s: No difference about performance.

Thanks to this

Saturday, April 2, 2016

Build Apps Faster Than Ever Before

Setup an Xcode Derived Data RAM Disk

Would you prefer the time it takes to compile and link your app to be faster or slower?

If you are not using a RAM disk, then you may be choosing the latter answer. If you don’t already know how to set this up, I’ve created an easy to use script written in Swift 2.2. This one may best suit the pros but we can all appreciate a little less waiting for a computer.

As a side note, Swift may not currently be the most efficient way to write scripts, but being able to do it has a special kind of sparkle that lights up when it is done.

Using the script allows the Derived Data setting to stay the same in Xcode but runs out of RAM instead of the disk. It does this by mounting the RAM disk to the same path that is normally disk-based.

This saves wear-and-tear on solid state drives, if you are into that kind of thing. If you happen to be using a spinning disk, it’s way faster than that, too.

I’ve been running Xcode like this for years and over that time all those savings can really add up.
It’s easy to create a launch agent, simply a property list file, that allows having the script run every time your computer starts. I’ve included an example of that in the source code.
I’ve even made sure using this technique works with Instruments because there is a need for Spotlight to find symbol files during profiling and debugging.

The script is contained in an Xcode project. The file main.swift can be copied out and renamed to setupXcodeDerivedDataRAMDisk.swift and placed in a bin directory for running from the command-line or a launch agent.
Here is the link to the project.

Original post

Wednesday, October 15, 2014

[Android]Hướng dẫn sử dụng Google Cloud Messaging for Android

Logo của Google Cloud Messaging
GCM hay Google Cloud Messaging là một dịch vụ cho phép gửi dữ liệu từ máy chủ của bạn đến các thiết bị Android của người dùng, và ngược lại. GCM hoàn toàn miễn phí và không giới hạn băng thông. Dịch vụ hoạt động trên các gói dữ liệu có dung lượng nhỏ hơn 4kb và tin nhắn tới thiết bị Android là tức thời (Push-notification).
GCM là phù hợp cho việc xây dựng các ứng dụng nhắn tin tức thời hoặc tương tác giữa người dùng và nhà phát triển ứng dụng. Ví dụ: 

  • Thông báo tới thiết bị Android của người khi có một Email mới.
  • GCM gửi thông báo tới người quản lý khi có Một đơn đặt hàng trên trang Web của họ.
  • Gửi tin nhắn tới cả một cồng đồng như : cồng đồng nhân viên thuộc cùng một công ty, học sinh hoặc phụ huynh của một trường học với chi phí thấp nhất và hiệu quả nhất.

Để hiểu rõ về GCM, bài viết ngày hôm nay của Tuần Báo Ubuntu Việt sẽ giới thiệu về cách tương tác giữa Ubuntu và Android đơn giản qua GCM.

Note: Bài viết có sử dụng tài liệu hướng dẫn sử dụng của Google Dev và http://sagark.org

1) Lấy API KEY của GCM
Đầu tiên, bạn cần đăng ký Google Cloud Messaging bằng tài khoản Google của bạn. Truy cập Google Console tại: https://cloud.google.com/console/project

a. Nếu bạn chưa tạo một dự án API nào, nhấp vào “Create Project”.
b. Cung cấp một tên dự án và nhấn Create.
c. Một khi dự án đã được tạo ra, một trang xuất hiện hiển thị ID dự án của bạn và số lượng dự án. Ví dụ, số dự án: 670.330.094.152
d. Copy số ID Project này. Bạn sẽ sử dụng nó như GCM sender ID.

Sau đó, bạn cần kích hoạt GCM:
a. Trong thanh bên trên bên trái, chọn API & auth.
b. Trong danh sách hiển thị các API, phần Google Cloud Messaging for Android chuyển đổi sang ON.

kích hoạt Google Cloud Messaging trong dự án của bạn

Lấy API Key:

a. Trong thanh bên trên bên trái, chọn API & auth> Credentials.
b. Trong phần Public API access, nhấp vào Create new key.
c. Trông hộp thoại Create a new key, nhấp vào Android key.
d. Trong hộp thoại cấu hình kết quả, bạn có thể cung cấp chứng nhận SHA1 hoặc bỏ trống.
e. Nhấp vào Create.
Trong trang mới, sao chép Api Key.

Vậy là chúng ta có được ID Project và API KEY. Hãy sao chép nó, chúng ta sẽ dùng nó vào bước tiếp theo.

API Key và ID Project


2) Mã nguồn cho Server
Tải xuống mã nguồn server mà chúng ta sẽ tải lên Server tại:
 https://github.com/sagark/snapnotify-server/zipball/master
Giải nén và mở file snapserver.settings, sau đó thay thế:

* YOUR_API_KEY= số API KEY của bạn
 * YOUR_SENDER_ID = số ID Project của dự án vừa tạo

Lưu file. Chuyển đến bước 3.

3) Đăng ký Server và tải mã nguồn chương trình lên server
Trong bài viết này chúng ta sẽ sử dụng trang Heroku để lưu trữ mã nguồn và làm Server. Đăng ký một tài khoản miễn phí tại https://dashboard.heroku.com và một tài khoản GitHub tại https://github.com

a) Tải xuống và cài đặt Heroku Toolbelt – trình quản lý Heroku trên Ubuntu bằng lệnh:

wget -qO- https://toolbelt.heroku.com/install-ubuntu.sh | sh

b) Mở Terminal, chuyển về thư mục chứa mã nguồn server mà chúng ta đã tải ở bước 2. Đăng nhập Heroku bằng lệnh:

heroku login

Dùng tài khoản Heroku của bạn để đăng nhập. Chạy tiếp 3 lệnh sau:

git init
git add .
git common -m 'init'

Đăng nhập bằng tài khoản GitHub vừa đăng ký.
Tạo một ứng dụng Heroku bằng lệnh:

heroku create [name]

[name]= tên của ứng dụng của bạn. Ví dụ của tôi: heroku create ubuntu-viet-push-android
Sau bước này một ứng dụng Heroku được tạo ra có dạng địa chỉ: http://exam.herokuapp.com
Mở lại file snapserver.settings và thay thế:
* url=địa chỉ heroku app của bạn
Lưu file.
c) Tải lên mã nguồn bằng lệnh:

git push heroku master

Sau khi tải xong, kích hoạt server:

heroku ps:scale web=1

d) Kiểm tra server bằng truy cập địa chỉ server heroku của bạn. Bạn thành công trong việc thiết lập server nếu thấy có thông báo ““Welcome to snapnotify-server! Your server is now running at: http://URL_HERE:PORT_HERE””

Kiểm tra server heroku

4) Tải Client và cấu hình cho thiết bị Android
Bạn có thể dùng chương trình SnapNotify.apk. Mở chương trình:
 Server Location= tên địa chỉ server heroku của bạn+”/register'
     Sender Id= số ID Project
Lần lượt nhấn nút “Set Prefs” và nút ““Reregister”

5) Gửi tin từ Server
Để gửi tin đến thiết bị Android, mở Terminal và chạy lệnh dưới cấu trúc sau :

curl -d "Test Message, Welcome to Google Cloud Messaging. : )" "http://YOURSERVER/message"

Nếu bạn thành công, thiết bị Android của bạn sẽ có tin nhắn dưới dạng push-notification.

Thử nghiệm gửi tin tới Android qua GCM


Chúc bạn thành công @

Tuesday, October 14, 2014

[iOS] Lưu dữ liệu vào NSUserDefaults chống user có thể sửa dữ liệu.

Như ta đã biết, dùng NSUserDefaults để lưu trữ các param, setting… trong khi code rất tiện, chỉ gọi các lệnh set, get là lưu được tất cả các loại format data.
Tuy nhiên NSUserDefaults lưu data ra file, không có bảo mật, nên user có thể dễ dàng sửa file, làm game chạy sai.
Dùng class này thì sẽ chống được việc sửa data trực tiếp từ file. Nó hoạt động theo cơ chế tạo thêm data hash cho data cần lưu, rồi lưu luôn vào cùng với data trong NSUserDefaults. 
Hạn chế của cách trên là nó không che giấu được data, nó chỉ chống không cho sửa. Do vậy chỉ có thể dùng để lưu param, setting… chứ không lưu username, pass được.

https://github.com/matthiasplappert/Secure-NSUserDefaults
 
 // Configuring user defaults. It is recommended that you do this  
 // immediately after the app did launch.  
 [NSUserDefaults setSecret:@"shh, this is secret!"];  
 // Write secure user defaults  
 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];  
 [defaults setSecureBool:YES forKey:@"IsRegistered"];  
 // Read secure user defaults  
 BOOL valid = NO;  
 BOOL registered = [defaults secureBoolForKey:@"IsRegistered" valid:&valid];  
 if (!valid) {  
   // the property has been modified, handle this situation  
 } else {  
 // Valid property, do whatever you need to do  
 }  

Nguồn