• Lenovo Mac OS X Battery Fix

    Here is a nifty little script that I wrote a while ago that when applied to your custom extracted DSDT on the Lenovo L420, it will enable the battery percentage, not much required!

  • Samsung Galaxy S10 Nasty Surprise

    There are many reasons why everyone is excited about Samsung’s 10th-anniversary Galaxy S10. Most notably the leaked triple rear cameras, ’ultrasonic’ in-display reader, new gradient color schemes and 5G option.

  • Start using Flutter!

    Build beautiful native apps in record time Flutter is Google’s mobile app SDK for crafting high-quality native interfaces on iOS and Android in record time.

  • Android App Bundles

    What the hell is an App bundle anyway? There were a ton of exciting things announced at I/O this year — one of the things that caught my eyes the most was the new app bundle format.

  • ASUS X550LDV Mac OS X Guide

    With the purpose of running the beloved Apple Mac OS X on our Intel ASUS laptop I am writing this guide to share my experience and knowledge about this Hackintosh.

My Story by JJBA



My life story and experience as well as CV, all packed in a cool Android app made with Kotlin, using some sweet customizable gradients as well as recycler views combined with cards, with the use of DayNight theme variants, possibly supporting auto night mode in Pixel devices.


Get it on Google Play
Enjoy and learn all you can about programming in my app too!

Getting Started


These instructions will get you a copy of the project up and running on your local machine for development and testing purposes. See deployment for notes on how to deploy the project on a live system.

Prerequisites


Necessary software would be Android Studio with latest Canary Build, as well as latest Kotlin.


Installing


Just delete my iml files and make sure you have everything in your system up-to-date.

Coding Style


I have chosen the Square Java and Square Android coding style, since code becomes much more readable in my perspective, using 2 spaces as indentation instead of the default 4 , which can make some parts of your code a mess of braces. Simply check the result of my Android projects, and compare the code style with others!


override fun getCount(): Int {
    return listItemsTxt.size
  }

  /**
   * Properties of ItemRowHolder Object
   * @sample ItemRowHolder
   */
  private class ItemRowHolder(row: View?) {
    val label: TextView = row?.findViewById(R.id.txtDropDownLabel) as TextView
    val pic: ImageView = row?.findViewById(R.id.imgDropDownMenuIcon) as ImageView
  }


Deployment


App release can be found in the appropiate folder and in Play Store!

Built With

Android Studio - Integrated Development Environment
Gradle - Build Tool and Scripts
Kotlin - Chosen language of the app's core logic

Contributing


Any contribution, comment and pull request will be welcome, join me in this voyage learning Android.

Authors

Josep Jesus Bigorra Algaba - Creator - JJBA](https://github.com/Josep-Jesus-Bigorra-Algaba)

See also the list of [contributors](https://github.com/Josep-Jesus-Bigorra-Algaba/SuperConverterLite/contributors) who participated in this project.

License


This project is licensed under the GNU Affero General Public License v3.0 - see the [LICENSE](LICENSE) file for details

Acknowledgments


* Hat tip to anyone whose code was used
* Inspiration from my sweet girl
Share:

My Portfolio - Ajax paradise (not football)

I have lately been working on building my own JavaScript based websites to provide a demonstration of my programming skills, showcasing all Asynchronous Javascript, JSON and XML methods, all in small and tidy functions, that are currently still being worked on.




Obviously it supports many languages and instant translation across the most spoken languages in this world. It also has a light and dark mode that applies instantly and, also sports a custom made music player that carries on as you navigate in this page.




Supports all unicode characters without a problem, as well as all writing directions and scripts. Currently working on adding even more languages to reach a more global audience.




Currently works in English, Spanish, Portuguese, Catalan, Dutch, Latin, Telugu, Hindi, Arab, Icelandic, romanian, Chinese (Simplified), Russian and Japanese.



Even the error pages are translated hihi, this server is well protected and works with SSL and HTTPS without a problem. It will use three separate cookies, that only serve the purpose of improving your in app experience by savig the prefered language and the theme of the website.



Make sure to check the source code that makes this website run (mostly Javascript) and drop a star on my GitHub.

Share:

Is jQuery still relevant in 2018?



After GitHub announced their decision to decouple from jQuery, we had a discussion on whether the museum is calling for this legendary tool. In the poll attached to that article, 429 of you voted and the decision is final: jQuery is here to stay!

Earlier this month, we heard some opinions on how jQuery is old and irrelevant, how it makes your website unnecessarily slow and how various companies, including GitHub, have documented their decision to decouple from jQuery.

But we also saw that there are those who still believe jQuery has a lot to offer. So, we decided to settle the discussion once and for all and we launched a poll!

The vast majority of the respondents has spoken: jQuery is still very much relevant!



As we also came across some people expressing the opinion that current jQuery usage is mostly in legacy applications, we split the “yes” answer into two parts. However, the results are pretty clear. 74% of the respondents use jQuery in new projects!

 jQuery is still very much relevant  — it just isn’t getting talked about.

Sam Oldenburg

It may have been the fact that new technologies are stealing the spotlight (see more below) and no one actually discusses this legendary library that it may seem like it has become irrelevant.

But the numbers don’t lie, my friends! jQuery is still very much alive and will keep doing what it does best –help you write code faster!

The discussion so far
Recently, I came across an old discussion on the pros and cons of using jQuery and its future. The discussion had taken place back in 2016 with experts like Jen Looper, Todd Motto, and Jeremy Likness agreeing on the fact that “Angular, Knockout, React, etc. have all contributed to diminishing the need for jQuery.”

The discussion itself as well as the title of the post “Is jQuery Still Relevant?” got me thinking. Is this really happening? Is jQuery becoming redundant, for real?

After a bit of research, I found some other posts and discussions all focusing on whether jQuery is still relevant or not and if you would be better off moving away from the library.

And then… BOOM! GitHub announced that they are removing jQuery from GitHub.com frontend.


Mislav Marohnić
@mislav
 We’re finally finished removing jQuery from http://GitHub.com  frontend. What did we replace it with? No framework whatsoever:

• querySelectorAll,
• fetch for ajax,
• delegated-events for event handling,
• polyfills for standard DOM stuff,
• CustomElements on the rise.



The team wrote in a recent blog post:

We have recently completed a milestone where we were able to drop jQuery as a dependency of the frontend code for GitHub.com. This marks the end of a gradual, years-long transition of increasingly decoupling from jQuery until we were able to completely remove the library.

How long has this “moving away from jQuery” thing been going on? How did one of the most dominant tools in the JavaScript ecosystem end up withering?

Let’s take a closer look at the reasoning various sides offer on the relevance (or irrelevance) of jQuery.

How it all started
The original and most prominent feature that made jQuary a God in web development was the cross-browser compatibility that, back in the day, was still a huge issue.

Midway, jQuery added tons of extra functions and wrappers like.ajax(), .post(), event binding helpers that made it super amazing for web developers but it also made it tricky for frontend developers since, at some point, they would find it quite difficult to know what was actually going on behind the curtains.

What’s more, new tools that came along the way, like Angular or React, took away a big chunk of the spotlight.

There was another factor contributing to jQuery’s downfall and that was the team’s rather sluggish updates and releases. The last couple of years or so the team has moved to a new system with roughly two releases per year. Not to mention that these releases focus on removing features rather than adding new ones or making groundbreaking changes.

Moving to some real-time examples, even before the news bomb from GitHub dropped, there were various companies documenting their decoupling from jQuery and how they ended up with a faster platform because of that.

On the other hand, if you take a look at jQuery usage statistics you cannot really see the numbers going down. What I gathered from the discussion on the Telerik blog I mentioned earlier is that most of this usage is legacy rather than new applications.

There is always the other side of the coin
The trend of moving away from jQuery can be documented as early as 2014 (if my research is correct). But there are some developers that still keep the jQuery flag high.

In a couple of threads on Reddit and Hackernews, people have been expressing their intention to keep working with jQuery and their opinion that the whole “hate” on jQuery is rather unfair.

I think all of this recent jQuery hate is just odd. Suddenly it’s not cool to use a ‘old’ relatively lightweight javascript library just because it’s not sexy…? jQuery might not be as sexy from a developers standpoint lately. But it is from a business standpoint, code maintainability, and just basic “Get S*** Done” standpoint. I think its worth all 92ko’s in allot of cases.

Some others may recognize the withering trend of the library but strongly believe that we have not yet seen a definite downfall.

jQuery isn’t going to go anywhere until businesses can realistically assume that the vast majority of their customers are on modern browsers. So it might be dying, but, much like Adobe Flash, it’s going to be a slow death.

There may be hope yet
The jQuery team has mentioned in 2017 that they are working for some big things for the 4.0 release.

Indeed, the roadmap shows some interesting ideas the team has been working on like create a web download builder and add automated code coverage. Will this be enough for the legendary library to gain back all the lost momentum?

We will see. For now, you can let us know in the poll below if jQuery is still an important tool for you.
Share:

Encryptor 64 - Powerful Cross Platform Text Encrpytor



A new Flutter application made with love by Josep Jesus Bigorra Algaba, myself, that brings you the best of base64 encryption mechanism along with a custom way of encrypting and decrypting that guarantees the safety of your message. 



This app was made using Flutter only and is currently only available for Android since I don't have an Apple Developer Account.. If a generous soul does, please e-mail me!!!




No one except the passkey holder can ever find out what you meant, use this responsibly and enjoy it. App currently has support for english, spanish and portuguese. 

 As a side note, please remember that the passkey has to be made up of 2 or more characters, numbers, symbols, or emojis :)

Share:

Swift 4 - The powerful easy to learn programming language

Swift is a general-purpose, multi-paradigm, compiled programming language developed by Apple Inc. for iOS, macOS, watchOS, tvOS, Linux and z/OS. Swift is designed to work with Apple's Cocoa and Cocoa Touch frameworks and the large body of existing Objective-C code written for Apple products. It is built with the open source LLVM compiler framework and has been included in Xcode since version 6. On Apple platforms it uses the Objective-C runtime library which allows C, Objective-C, C++ and Swift code to run within one program.



Apple intended Swift to support many core concepts associated with Objective-C, notably dynamic dispatch, widespread late binding, extensible programming and similar features, but in a "safer" way, making it easier to catch software bugs; Swift has features addressing some common programming errors like null pointer dereferencing and provides syntactic sugar to help avoid the pyramid of doom. Swift supports the concept of protocol extensibility, an extensibility system that can be applied to types, structs and classes, which Apple promotes as a real change in programming paradigms they term "protocol-oriented programming"(similar to traits).

Swift was introduced at Apple's 2014 Worldwide Developers Conference (WWDC).It underwent an upgrade to version 1.2 during 2014 and a more major upgrade to Swift 2 at WWDC 2015. Initially a proprietary language, version 2.2 was made open-source software under the Apache License 2.0 on December 3, 2015, for Apple's platforms and Linux.

Different major versions have been released annually with incompatible syntax and library invocations that require significant source code rewrites. For larger code bases this has caused many developers to dismiss Swift until a more stable version becomes available.

Swift is an alternative to the Objective-C language that employs modern programming-language theory concepts and strives to present a simpler syntax. During its introduction, it was described simply as "Objective-C without the C".
By default, Swift does not expose pointers and other unsafe accessors, in contrast to Objective-C, which uses pointers pervasively to refer to object instances. Also, Objective-C's use of a Smalltalk-like syntax for making method calls has been replaced with a dot-notation style and namespace system more familiar to programmers from other common object-oriented (OO) languages like Java or C#. Swift introduces true named parameters and retains key Objective-C concepts, including protocols, closures and categories, often replacing former syntax with cleaner versions and allowing these concepts to be applied to other language structures, like enumerated types (enums)

Syntactic sugar

Under the Cocoa and Cocoa Touch environments, many common classes were part of the Foundation Kit library. This included the NSString string library (using Unicode), the NSArray and NSDictionary collection classes, and others. Objective-C provided various bits of syntactic sugar to allow some of these objects to be created on-the-fly within the language, but once created, the objects were manipulated with object calls. For instance, in Objective-C concatenating two NSStrings required method calls similar to this:


NSString *str = @"hello,";
str = [str stringByAppendingString:@" world"];

In Swift, many of these basic types have been promoted to the language's core, and can be manipulated directly. For instance, strings are invisibly bridged to NSString (when Foundation is imported) and can now be concatenated with the + operator, allowing greatly simplified syntax; the prior example becoming:


var str = "hello,"
str += " world"

Swift supports five access control levels for symbols: open, public, internal, fileprivate, and private. Unlike many object-oriented languages, these access controls ignore inheritance hierarchies: private indicates that a symbol is accessible only in the immediate scope, fileprivate indicates it is accessible only from within the file, internal indicates it is accessible within the containing module, public indicates it is accessible from any module, and open (only for classes and their methods) indicates that the class may be subclassed outside of the module.


Comparisons to other languages


This section is in a list format that may be better presented using prose. You can help by converting this section to prose, if appropriate. Editing help is available. (February 2017)
Swift is similar to C in various ways:


  • Most C operators are used in Swift, but there are some new operators.
  • Curly braces are used to group statements.
  • Variables are assigned using an equals sign, but compared using two consecutive equals signs. A new identity operator, ===, is provided to check if two data elements refer to the same object.
  • Control statements while, if, and switch are similar, but have extended functions, e.g., a switch that takes non-integer cases, while and if supporting pattern matching and conditionally unwrapping optionals, etc.
  • Square brackets are used with arrays, both to declare them and to get a value at a given index in one of them.
  • It also has similarities to Objective-C:
  • Basic numeric types (Int, UInt, Float, Double)
  • Class methods are inherited, like instance methods; self in class methods is the class the method was called on.
  • Similar for...in enumeration syntax.
  • Differences from Objective-C include:
  • Statements do not need to end with semicolons (;), though these must be used to allow more than one statement on a line.
  • No header files.
  • Uses type inference.
  • Generic programming.
  • Functions are first-class objects.
  • Enumeration cases can have associated data (algebraic data types).
  • Operators can be redefined for classes (operator overloading), and new operators can be defined.
  • Strings fully support Unicode. Most Unicode characters can be used in either identifiers or operators.
  • No exception handling. Swift 2 introduces a different and incompatible error-handling model.
  • Several notoriously error-prone behaviors of earlier C-family languages have been changed:
  • Pointers are not exposed by default. There is no need for the programmer to keep track of and mark names for referencing or dereferencing.
  • Assignments return no value. This prevents the common error of writing i = 0 instead of i == 0 by throwing a compile-time error.
  • No need to use break statements in switch blocks. Individual cases do not fall through to the next case unless the fallthrough statement is used.
  • Variables and constants are always initialized and array bounds are always checked.
  • Integer overflows, which result in undefined behavior for signed integers in C, are trapped as a run-time error in Swift. Programmers can choose to allow overflows by using the special arithmetical operators &+, &-, &*, &/ and &%. The properties min and max are defined in Swift for all integer types and can be used to safely check for potential overflows, versus relying on constants defined for each type in external libraries.
  • The one-statement form of if and while, which allows for the omission of braces around the statement, is unsupported.
  • C-style enumeration for (int i = 0; i < c; i++), which is prone to off-by-one errors, is unsupported (from Swift 3 onward).
  • The pre- and post- increment and decrement operators (i++, --i ...) are unsupported (from Swift 3 onward), more so since C-style for statements are also unsupported from Swift 3 onward.




Development and other implementations

Since the language is open-source, there are prospects of it being ported to the web.Some web frameworks have already been developed, such as IBM's Kitura, Perfect and Vapor.

An official "Server APIs" work group has also been started by Apple,with members of the Swift developer community playing a central role.

A second free implementation of Swift that targets Cocoa, Microsoft's Common Language Infrastructure (.NET), and the Java and Android platform exists as part of the Elements Compiler from RemObjects Software.
Share:

Samsung's Galaxy S10 Has A Nasty Surprise

There are many reasons why everyone is excited about Samsung’s 10th-anniversary Galaxy S10. Most notably the leaked triple rear cameras, ’ultrasonic’ in-display reader, new gradient color schemes and 5G option. Even Samsung is bragging about the Galaxy S10. But now there is news which will come as a nasty surprise to many…

‘Great Secret Features’ and ‘Nasty Surprises’ are my regular columns investigating the best features / biggest problems hidden behind the headlines.


Leaked by Ice Universe, arguably the industry’s top Samsung insider right now, we learn the Galaxy S10 will no longer try to compete with the iPhone’s popular Face ID system. In fact, Samsung looks to be giving up on facial recognition completely.


“The S10 cancels the iris sensor,” states Ice Universe. Why? Because Samsung believes “the ultrasonic fingerprint [sensor] is enough to replace it.”

Justifying this move, Ice Universe explains that the ultrasonic fingerprint sensor on the Galaxy S10 is unlike any in-display fingerprint reader we have seen before. It is both “faster and has a larger recognition area” with up to 30% of the screen responding to a user’s fingerprint.

This is indeed significant. Since in-display readers have no physical edges they cannot be opened with a combination of feeling and muscle memory. But being able to just touch anywhere on the bottom third of the Galaxy S10 display to unlock the phone would change that.

Still, this doesn’t fully replace an iris scanner.


Much like Apple’s decision to scrap Touch ID on the iPhone and iPad ranges, which leaves users with times when fingerprint unlocking would be more convenient (for example, peaking at your phone in a meeting or when wearing sunglasses), scrapping the Galaxy S10’s iris recognition causes problems (such as when wearing gloves).

Moreover, Samsung’s decision to support both technologies was a distinct selling point for Galaxy phones over iPhones. And with reports previously suggesting Samsung was on the verge of a technological breakthrough which would’ve seen it match the quality of Face ID, it is a shame to see the company give owners less choice.

So why is Samsung doing it?

The decision is believed to be based on the company’s desire to give the Galaxy S10 a virtually bezel-less display. Chinese manufacturers like Oppo, Vivo, Xiaomi and Lenovo have all achieved this through various design innovations. And with Samsung’s latest financial results showing it losing out to Chinese rivals, in particular, the company needs to compete head-on.

This is not the Galaxy S10’s only compromise either.

Samsung is also widely expected to remove the headphone jack from the Galaxy S10 to accommodate all its technological innovations. Most rivals have already done this, but Samsung has long been praised for its stubbornness and even used this as a marketing point.

So yes, the Galaxy S10 does look like arguably the most radical upgrade in Samsung’s smartphone history. But this 10th-anniversary flagship will also come with some controversial compromises as part of the deal… 
Share:

Microsoft finally open-sources MS-DOS!!!


After over 30 years, Microsoft is making MS-DOS fully open source as part of a “re-release” without the restrictions of the last.

Many will not have seen MS-DOS for decades, but the 1983 OS remains among the most important software ever written.

Indicating the importance of the OS, MS-DOS was added to the Computer History Museum in 2013. In doing so, the original source codes were transferred.

The clause of MS-DOS in the Computer History Museum was that people were prohibited from using it for commercial projects and distributing it elsewhere. Not really open source, then.

Microsoft is now publishing the source code under the MIT license which allows it to be modified, used, and distributed without penalty.

The company provided some interesting facts alongside its release:
  • All the source for MS-DOS 1.25 and 2.0 was written in 8086 assembly code
  • The source code for the initial release of 86-DOS dates from around December 29th 1980
  • The MS-DOS 1.25 code dates from around May 9th 1983, and is comprised of just 7 source files, including the original MS-DOS Command-Line shell - COMMAND.ASM!
  • MS-DOS 2.0 dates from around August 3rd 1983, and grew considerably in sophistication (and team size), and is comprised of 100 .ASM files
  • There are some interesting documentation (.TXT, .DOC) files interspersed with the source and object files - many are well worth a read, as are many of the source code comments!

As expected, the code is being hosted on GitHub which Microsoft acquired back in June for $7.5 billion. It’s worth noting the company will not accept pull requests and will treat it as a static copy.
Share:

Exploring the Android App Bundle

What the hell is an App bundle anyway?

There were a ton of exciting things announced at I/O this year — one of the things that caught my eyes the most was the new app bundle format. Not only does this format provide a new upload format for our applications, but it will help to influence how we build and structure our applications in a modular format. In this post I want to dive into the Android App Bundle so that we can get a thorough understanding of what it is, the way it works and how we can add support for it in our own applications.

As I mentioned above, I was pretty excited to hear about this new upload format known as the App Bundle. Whilst this bundle still contains our applications code and resource files, the big difference is that the responsibility of building APKs is passed onto Google Play. And from here, the new Dynamic Delivery can then be used to create optimized APKs that satisfy the requirements of a users device and deliver them at runtime for install.


But why should we consider using the Android App Bundle?


First of all, the approach promotes a clean and separated structure to your code base. Because of the way bundles work (and especially with dynamic delivery, which we’ll come onto later), modularization by feature will become a part of your app. This is similar to the modular approach within Instant apps or general modularize-by-feature approaches. Regardless, this helps to decouple the different parts of your app and help to make your code base easier to work with.
Where we previously may have been required to build multiple APKs to target different API versions, device types and so on — Android App Bundles means that we can now just upload the single artifact with all of our application resources and the tooling will take care of what needs to be built and delivered to our users. This essentially automates this process for us and means we can shift that focus onto other parts of our development process.

Because the App Bundle will build the APK that is targeted for a specific device and its configuration, this means that the APKs delivered will generally of a smaller size. This will really depend on your application, as the main savings will be from density / locale specific resources and any other unused code. Some of these size savings by early adopters of App Bundles show some great results:





App bundles introduces us to a new concept known as Dynamic Delivery. This allows our applications to provide new features to users and allow them to be downloaded and installed at run-time as an extension to our application. This allows us to make the initial size of our application smaller and offer these extras only to users who may actually make use of them.

And soon, the app bundle format will support instant enable on bundles — this means that users will be able to launch our feature modules instantly without installing our application, similar to the way in which instant apps currently work.


With all of this in mind, let’s take a dive into the app bundle format and all of the concepts that surround it!

Note: To follow any of the IDE parts of this article you will need to be running Android Studio 3.2.

The App bundle format

Before we get started with diving into the app bundle, it’s important to understand the format. The app bundle is made up of a zip archive that contains a collection of files that make up the bundle. Whilst these files are ones that we will find within the APKs that we are familiar with, it serves a different purpose than that of an APK.



An APK is something that we can serve directly to our users devices, whereas on the other hand an App Bundle is a publishing format that cannot be installed onto a device on it’s own. Whilst they do have their similarities, the app bundle does contain some content which we will not find within our APKs. For example, the meta data files within the bundles are used by tooling to build the APKs that will be served to our users — these files are then not included in the APKs themselves. Whilst most of the content within the app bundle you will likely already be familiar with, let’s take a look at what a typical app bundle might contain:

  • manifest.xml — Just like you will find in your APKs, there is a manifest file present per app bundle. However, unlike the APK these are not stored in a binary format — it is compiled into protocol buffer format which makes it easier for tooling to transform when required.
  • res / assets / libs — All resources, assets and native libraries are stored the same way as in an APK. The only difference here is that any resource files will also be stored in the protocol buffer format as the last point.
  • resources.pb — Similar to the resource.arac file which can be found inside of our current APK files, the resources.pb file is a resource table which states the resources and specifics for targeting which are present inside of our app. The .pb extension is due to the protocol buffer format which is used by tooling to transform the app bundle before it is converted into the binary format used within the APK.
  • assets.pb — This is the equivalent of a resource table for application assets and will only be present if you are using assets in your application.
  • native.pb — This is the equivalent of a resource table for native libraries and will only be present if you are using native libraries in your application.

The last 3 files mentioned here are a key part of the App Bundle, as these tables are used to describe the targeting of our application. This is a key concept within dynamic delivery as it used to depict what kind of device and / or user that we are serving, which allows us to deliver a specific build of resources based off of this information.

These resource, assets and native tables all use information that we are already familiar with in our applications to serve content to our users. We are familiar with using directories such as drawable-hdpi, lib/armeabi-v7a, or values-es to target specific users with certain resources — the app bundle uses the exact same approach when it comes to targeting specific resources to users and devices. So when it comes to the organisation of these things we are not required to do anything differently.

Splitting up APKs

In Android lollipop we saw a feature added to the platform called Split APKs. This allowed multiple APKs to be added to a device, whilst still behaving as though they were part of a single app. These could be installed as different combinations on different devices — whilst still appearing as a single APK.

These split APKs have the exact same format as an APK, as well as sharing the same package name and version code as one another. The App Bundle format is used to generate these split APKs which in turn can be served to our users devices. To begin with the App Bundle is used to analyse all of its resources to find the parts that are common to all device configurations — this will be the manifest file, dex files and any other parts which are the same regardless of the device, architecture or locale in use. These common parts are what will make up the base APK for our application and from there, split APKs will then be used to create splits for the different kind of configurations which are possible.

From here, configuration splits will then be generated to be able to serve users the collection of split APKs that satisfy the requirements of their device setup:


  • To begin with, each supported screen density will be analysed and a split APK will be created for each one, these will contain all of the resources which are specific to that density.
  • A different split APK will then be generated for each native architecture
  • Finally, a different split APK will be generated for each support locale for your application




So when a user is served with our application, this subset of split APKs will be delivered to their device. This is much more efficient than the current configuration of delivering every single configuration to every user, when chances are most users will not use a lot of the resources which are being delivered to their device currently. To put this into perspective, below shows three different configurations which could be served to three different users — providing only the resources that they require:



If the user changes their device configuration at any time (such as adding another choice of language), then the play store will recognize this and attempt to download the new configuration splits for all applications that use split APKs on their device. And if the device isn’t online at that time, then this will be done so at the next opportunity.

Now seeing as split APKs are only supported on Lollipop and above, the app bundle can still help to achieve size savings for devices that are using earlier versions of Android than this. Instead of their being splits generated, standalone APKs will be created that match the matrix of different combinations of architectures and device densities. In this approach all languages are included in each APK because the matrix would become too large from too many different combinations being available. For these pre-L devices, the most suitable APK will be chosen for a given device and served to the user.



As you can see from the App Bundle so far, regardless of the SDK version that we are supporting we can achieve savings when it comes to our application size. The great thing here is that as developers we don’t need to worry about any of the details that are involved with this process. We just need to upload a single app bundle and the Google Play will generate the right APK splits, followed by selecting the right APKs to be served to each device.



Building and Distributing the Android App Bundle

When it comes to building an app bundle from our project, we can do so directly from Android Studio. This can be done directly from the build menu, selecting Generate Signed Bundle / APK — from here you will be presented with the following dialog:



At this point we will be given the choice to build either an Android App Bundle or an APK. Selecting either of these options will take us to the keystore selection/creation dialog, and then from there the wizard will build our desired selection.

If we build an app bundle here then an .aab file will be generate, this is the format that represents the app bundle. As well as building an App Bundle using this wizard from within the IDE, we can also create an app bundle from the command line — this can be useful for CIs or people who just prefer working from the command line.

./gradlew modulename:assemble
./gradlew modulename:assembleVariant

When it comes to building your bundle, by default all splits will be generated. but within the android block of your build.gradle file you are able to declare which splits will be generated:

bundle {
        language {
            enableSplit = false
        }
        density {
            enableSplit = true
        }
        abi {
            enableSplit = true
        }
    }

By default these properties will be set to true. However, setting one to false will mean that the configuration for the specified bundle will not be supported, causing the resources for that property will be packaged into the base APK and any dynamic-feature APK that is served.

Once you have built your App Bundle it can simply be uploaded to the play console. In-order to be able to distribute app bundles via the Play Store you first need to be enrolled for Google Play app signing . Because the tooling will generate the different APK splits for you, it also needs the capability of signing them — this is is required and you won’t be able to use app bundles without it.

Now that we’ve built our app bundle via Android Studio (or the command line, even), we can upload it to the Play Console to prepare for distribution. If you head on over to the release page just like you would do for an APK, you’ll notice that you’ll also be able to upload an App Bundle via the same upload area:



Once the bundle has been uploaded you will be able to see the Android App Bundle added to the list of components beneath the upload area. Expanding the Android App Bundle that we just uploaded will show you all of the information that an APK does, except this time we can see a button for 

Explore App Bundle:




The Application that I’ve uploaded a bundle for only supports a single locale (it’s just for example sake), but does support a range of different screen densities. Because of this, the App Bundle Explorer shows us a breakdown of the different device configuration APKs that will be served from the given app bundle. From here we will also be able to download the different APKs for testing purposes, as well as view the devices which will be served each APK configuration.

You’ll notice that at the top we are also shown a size saving value from using an App Bundle format over the standard APK upload approach. This will vary between applications and because this is just a sample app, the savings aren’t likely to be a true representative of what you may see for your own applications.



Bundle tool

Now, before you upload the App Bundle to the Google Play Store it’s important to perform some testing of the bundle. Whilst we can use an internal test track to do this, we can also test it all locally to ensure that everything is working as intended. For this we can use the bundletool which will make this process very simple for us. This tool is the same used by our IDE and Google Play to build our bundle as well as convert it to the different configuration splits, so what we will see locally is a true representation of what users will be served.

When we run the bundle tool, it will generate a collection of APKs based on the configurations of our app. To kick things off, let’s create a set of unsigned APKs for all of the different configurations that our bundle supports:

bundletool build-apks --bundle=/Users/joebirch/releases/sample.aab --output=/Users/joebirch/releases/sample.apks

Note: If you wish to run the same task but produce signed APKs, then you can do so by adding the keystore information to the command:

bundletool build-apks --bundle=/Users/joebirch/releases/sample.aab --output=/Users/joebirch/releases/sample.apks
--ks=/Users/joebirch/some_keystore.jks
--ks-pass=file:/Users/joebirch/some_keystore.pwd
--ks-key-alias=SomeAlias
--key-pass=file:/Users/joebirch/some_key.pwd

So now that we have these APKs generated, we want to serve them to a local device — bundletool can do this for us.

bundletool install-apks --apks=/Users/joebirch/releases/sample.apks

Say we have a device connected that is running at least Android 5.0. When we run this command, Bundletool will push the base APK along with any dynamic feature and configuration APKs to the device that are specific for that device configuration— the same way which users will be served our application from the Play Store. If we connect a different device, say with a different density / locale, then a different set of configuration APKs will be served to that device. If the connected device is running under Android 5.0 then the most suitable multi-APK will be installed to the device. When dealing with multiple devices you can use the --device-id=serial-id in order to depict which device the application should be installed to.

When bundletool generates the installed content for a connected device you are able to retrieve the device specification JSON format. This can then be used to extract a specific APK from the generated APKS. To begin with we need to run the command:

bundletool get-device-spec

Now that we have this JSON file for the specific device configuration we can go ahead an use to extra a specific configuration split:

bundletool extract-apks
--apks=/Users/joebirch/releases/someApkSet.apks
--output-dir=/Users/joebirch/releases/device_APK_set.apks
--device-spec=/Users/joebirch/releases/some_configuraton.json

You can also manually create your own device configuration JSON file and use that to extract an APK for a specific configuration. This can be great for testing a device configuration that you may not have access to specifically.

{
  "supportedAbis": ["arm64-v8a"],
  "supportedLocales": ["en", "es"],
  "screenDensity": 640,
  "sdkVersion": 21
}

Dynamically serving features

Another key part when it comes to the App Bundle is what’s known as Dynamic Delivery. This functionality allows you define modules which may not be required when an application is first installed. In our project we can define these modules and then use the new Play Core Library to install on demand when they are required. This may be a piece of functionality that not all users of your application may use, or may not be a core piece of functionality. Again, this allows size savings from initial downloads and Google Play can serve the Dynamic Feature for us when they are requested.



To be able to add support for this, let’s take a quick run through at creating a Dynamic Feature Module in our application. We can begin by heading over to the Create New Module wizard by right clicking on the root module of our project and selecting New Module. From here we can select the Dynamic Feature Module and hit Next.


Now we need to select the Base module of our application — this will be the installable module that this Dynamic Feature Module will depend on. Once the desired information has been filled out we will be prompted to name out module, and from there we can finish the setup of the Dynamic Feature module where it will be added to our application.



Once you’ve created this module, it’s worth taking a quick look around. This is so that you are aware of the difference in configuration for a Dynamic Feature Module, it’s always great to know how things work and also, if you need to convert modules in future then you know what information needs to be added.


If you open the module build.gradle file, you’ll notice that a different plugin if being used:

apply plugin: 'com.android.dynamic-feature'

Slightly different from the feature module that we may see being used for instant apps, this plugin is required for your module to be classed as a dynamic feature module. Whilst in this file you should be aware that there are a few properties which a dynamic-feature build.gradle file does not use — for example the versionCode, vesionName, minification and signing properties are all taken from the base module.

Next, if you open up your base modules build.gradle file you’ll notice that our dynamic feature has been added to an array of a dynamicFeatures property:

dynamicFeatures = [":first-dynamic-feature"]

This is declares the dynamic features which are available for your application and must be updated whenever you add support for new dynamic features so that your base module is aware of them. Finally, if you open up the dynamic feature module you can open up the manifest file of that module to find the following:

<manifest xmlns:dist="http://schemas.android.com/apk/distribution"
    package="co.joebirch.first_dynamic_feature">

    <dist:module
        dist:onDemand="true"
        dist:title="@string/title_first_dynamic_feature">
        <dist:fusing include="true" />
    </dist:module>
</manifest>


  • onDemand — If the property is set to true then the module will be available for on-demand downloads. When set to false the dynamic feature will be downloaded when the user first downloads and installs the application.
  • title — The title will be used to identify the module when users are confirming the download of the module. The string resources for this should be stored in the resources of your application so that it can be translatable for the different locales that your application supports.
  • fusing include — Setting this property to true will mean that older devices (4.4 and lower) will be able to recieve these dynamic features in the form of multi-APKs. To use this functionality you must have enabled the onDemand property.


Serving features dynamically

Now that we’ve added a Dynamic Feature Module to our application, we want to actually serve it to our users when they have requested it. For this purpose, we’re going to make use of the Play Core library which provides us with the functionality to do so. This library allows the user to intend on interacting with a feature that may not be installed yet, and at this point our application will request the feature, download it and then handle the state of this once it is installed.



To be able to start making use of this functionality, we need to begin by adding the play core library to our project via the dependency:

implementation 'com.google.android.play:core:1.3.4'

Now that we have the library available for use, we need to make use of it where appropriate. To download the dynamic feature at runtime we’ll be using the SplitInstallManager class. Whilst our application is in the foreground, this will be used to request the dynamic feature and then download it for install.

val splitInstallManager = SplitInstallManagerFactory.create(this)

Now that we have this class available, we’re going to create a SplitInstallRequest instance for the downloading of our module:

val request = SplitInstallRequest
        .newBuilder()
        .addModule("someDynamicModule")
        .build()

This instance will contain the request information that will be used to request our dynamic feature module from Google Play. Within this request we can state multiple modules that we want to be request, this can be done by simply chaining on multiple addModule() calls to the request builder.

Finally, we’re going to use our install manager instance to run the request that we just created. Here we will use the startInstall() function on our manager, passing in the request that we previously created, and add callbacks for when the install completes, is successful or fails so that the UI can be handled accordingly.

splitInstallManager
        .startInstall(request)
        .addOnSuccessListener {  }
        .addOnFailureListener {  }
        .addOnCompleteListener {  }

The stateInstall function call here will trigger the install process as soon as possible. However, if you wish to defer the install process for when the app has been back-grounded then you can do so by using the deferInstall() call instead.

When you call either of these functions you will be returned with an Int value that represented the session ID for the split install. If at any point during the request for an install you want to cancel it, then you can do so by calling the cancelInstall() function, passing in the session ID for the corresponding request.

During the install process there are a collection of different errors that may occur, let’s take a quick look at what these can be:


  • ACCESS_DENIED — Given the current device circumstances, the current download is not allowed
  • ACTIVE_SESSIONS_LIMIT_EXCEEDED — There are too many running sessions for the current app
  • API_NOT_AVAILABLE — The split install API is currently not available
  • INCOMPATIBLE_WITH_EXISTING_SESSION — The session that was requested contains modules for an existing sessions as well as new modules
  • INTERNAL_ERROR — There was an error when trying to process the install of the split APK
  • INVALID_REQUEST — The request that was performed is invalid
  • MODULE_UNAVAILABLE — The module that was requested is currently unavailable
  • NETWORK_ERROR — There was a network error when trying to obtain the details for the given split
  • NO_ERROR — There was no available error
  • SERVICE_DIED — The service that was handling the split install has died
  • SESSION_NOT_FOUND — The session that was requested couldn’t be found

Now, when this request is taking place there is no form of UI overlay that we may be used to from things such as the Billing Library or other Google Play integrations. Because of this, it’s important that the user is aware what is happening in your application when a dynamic feature is being downloaded and installed — for this we can make use of the SplitInstallStateUpdatedListener which will allow us to monitor the state of our request.

val stateListener = SplitInstallStateUpdatedListener { state ->
    when (state.status()) {
        PENDING -> { }
        DOWNLOADING -> { }
        DOWNLOADED -> { }
        INSTALLED -> { }
        INSTALLING -> { }
        REQUIRES_USER_CONFIRMATION -> { }
        FAILED -> { }
        CANCELING -> { }
        CANCELED -> { }
    }
}
splitInstallManager.registerListener(stateListener)

Here you can see an instance of the listener being defined, along with the different states which the install can be in — you should use this in your app to handle the UI. For example, you may want to show some form of progress bar to let the user know that these states are taking place, but change the message used as the process propagates through each state.

There are a collection of different states that the split install can be in, let’s take a quick look at what these are:


  • CANCELED — The downloading of the split APK has been canceled
  • CANCELING — The downloading of the split APK is currently being canceled
  • DOWNLOADED — The split APK has been downloaded but not currently installed
  • DOWNLOADING — The split APK is currently being downloaded
  • FAILED — The downloading or installation of the split APK has failed
  • INSTALLED — The installation of the split APK has been completed and is available for use with the application
  • INSTALLING — The split APK is currently being installed
  • PENDING — The download of the split APK is currently pending
  • REQUIRES_USER_CONFIRMATION — The download of the split APK requires user confirmation as the size of it is too large
  • UNKNOWN — The current state is unknown


Once dynamic feature modules have been installed, there are still some operations that can be performed to manage them. For example, we can uninstall a module using the deferredUninstall() function — passing in a slight of the module names which we want to remove from the users installation of our application.

splitInstallManager
        .deferredUninstall(listOf("someDynamicModule"))
        .addOnSuccessListener {  }
        .addOnFailureListener {  }
        .addOnCompleteListener {  }

We can also retrieve a list of the installed modules names by using the getInstalledModules() function on our manager instance, this will be useful for setting up any UI in your application and checking for module install state before performing any delete requests.

val installedModules = splitInstallManager.installedModules

How much size will I actually save?

Now it’s all well and good saying that you will save application size, but it’s helpful to have some kind of guideline as to what you will actually save. According to Google, on average applications using the App Bundle format are 20% smaller in size — this means that every time your application is downloaded or updated there is 20% less data transfer involved.

Google also performed some analysis on all applications in the Play Store that had at least 1 million downloads, from this they were able to find that:


  • Language splits would achieve over 95% savings when it comes resources used by locale resources
  • Density splits would help to achieve up to 45% savings in applications that support multiple densities
  • Applications using native libraries would be able to achieve up to 20% savings when it comes to architecture supports


With all of these put together, it was found that 10PB of data per day would be saved if all of these apps were using the App Bundle format. That is an incredibly high amount of data!

There are also some sample pieces of data that Google have shared from applications who were early adopters of the app bundle format. For example, whilst Twitter for Android already previously served multi-APKs, app bundles allowed them to see a decrease in size of around 20%. The application supports many different languages and densities which is where a lot of their savings come from. The use of the App Bundle also means that they no longer need to manually create and upload separate APKs for the configurations which they wish to support, as the App Bundle tooling will handle this automatically.



The Text Plus application on the other hand were not supporting multiple APKs for different configurations. The application has a lot of resources when it comes to different density and architectures, so the App Bundle allowed them to achieve a saving of approximately 26% for their application.



And finally, the Jamo application was able to half it’s original application size when the team added support for the App Bundle. The application uses a lot of different large native libraries to be able to support different architectures — the app bundle now allows them to optimize these requirements so that smaller APKs can be served to users.



I hope from reading this article you have some understanding of what App Bundles are, how they work and how we can pair this with Dynamic Delivery to improve how we serve our application to our users. I’m excited to use App Bundles in production and learn more about how we can use them to improve our application size and delivery. Are you using app bundles or do you have any questions? Feel free to leave a response or get in touch 🙂
Share:

Flutter - Start using Dart !

Build beautiful native apps in record time 

Flutter is Google’s mobile app SDK for crafting high-quality native interfaces on iOS and Android in record time. Flutter works with existing code, is used by developers and organizations around the world, and is free and open source.




Fast Development

Hot Reload in milliseconds to paint your app to life. Use a rich set of fully-customizable widgets to build native interfaces in minutes.

Expressive and Flexible UI

Quickly ship features with a focus on native end-user experiences. Layered architecture allows full customization, which results in incredibly fast rendering and expressive and flexible designs.

Native Performance

Flutter’s widgets incorporate all critical platform differences such as scrolling, navigation, icons and fonts to provide full native performance on both iOS and Android.

Fast development

Flutter's hot reload helps you quickly and easily experiment, build UIs, add features, and fix bugs faster. Experience sub-second reload times, without losing state, on emulators, simulators, and hardware for iOS and Android.


Expressive, beautiful UIs

Delight your users with Flutter's built-in beautiful Material Design and Cupertino (iOS-flavor) widgets, rich motion APIs, smooth natural scrolling, and platform awareness.



Modern, reactive framework

Easily compose your UI with Flutter's modern reactive framework and rich set of platform, layout, and foundation widgets. Solve your tough UI challenges with powerful and flexible APIs for 2D, animation, gestures, effects, and more.

Unified app development

Flutter has the tools and libraries to help you easily bring your ideas to life on iOS and Android. If you don't have any mobile development experience, Flutter is an easy and fast way to build beautiful mobile apps. If you are an experienced iOS or Android developer, you can use Flutter for your views and leverage much of your existing Java/Kotlin/ObjC/Swift investment.
Share:

Popular Posts

Labels

Followers

Recent Posts

Back to Top