Easier Webhook Testing with Ngrok

Picture this scenario :

You have built a web app that has webhooks from other service. But everytime you want to test it out, you have to deploy your app, and keep a look out on your logs as the request trickles in. 

or

You are working with a mobile developer in-house, and you both want to test an API. You deploy the app, even if it is a minute change and then wait to see if all works properly. 

I am sure, as a developer, we have all been there. Deploying apps for a couple of small changes, and make it run through your entire CI/CD cycle can be exhausting. And so I was delighted, when I stumbled upon ngrok.

ngrok is a tool that allows you to access your localhost via Internet. This can save you from countless hours of frustrations by avoiding deploying code for minor changes.

Running ngrok is as simple as downloading the relevant files from the website. Once downloaded, on Mac / Linux – type

Once you have unzipped the contents, ensure your localhost is running and you know the port number. To get your server accessible via Internet, type

This would start ngrok, and now your web app is publicly accessible via the Internet. The terminal also shows the incoming request to your app

The Tunnel URL in my case is http://b3991383.ngrok.io, which points to port 8000 on my device. You can now update the tunnel URL in your webhooks, or pass it on to your client to test the app.

One cool feature of ngrok is it’s live dashboard – which allows you to inspect the status of server as well as the requests that are coming in. You can access this dashboard by navigating to http://localhost:4040/inspect/http

 

 

Apart from using ngrok for development, you can also use it to host your own webmail or other apps. ngrok also offers a paid tier with support for custom domains and other features.

ngrok has been easily one of the tools that has saved me hours of development time, and the paid plan is just worth it.

How to create a Diawi link ?

Overview

Diawi is tool for iOS and Android developers to upload and install applications to their devices. Developer can upload an .ipa file for iOS or the .apk file for Android on the website and then provide the link to the testers or users. The testers/users can open the link in their browser and install the app.

Why should i use Diawi?

  • Easy to use.
  • Faster uploading the app and providing links to the testers.

Prerequisite

Registering an App ID :-

  • Sign in to developer.apple.com/account, and click Certificates, IDs & Profiles.
  • Under Identifiers, select App IDs.
  • Click the Add button (+) in the upper-right corner.
  • Enter a name or description for the App ID in the Description field.
  • Create an explicit App ID and enter the app’s bundle ID in the Bundle ID field.
  • Select the corresponding checkboxes to enable the app services you want to use.
  • Click Continue, Review the registering information and click Done.

Registering a Device:-

To register a device using your developer account, you need to have the device name and device ID.
  • In to developer.apple.com/account, and click Certificates, IDs & Profiles.
  • Under Devices, select All.
  • Click the Add button (+) in the upper-right corner.
  • Select Register Device.
  • Enter a device name and the device ID (UDID).
  • Click Register.

Create a Provisioning Profile :-

  • In to developer.apple.com/account, and click Certificates, IDs & Profiles.
  • Under Provisioning Profiles, select All.
  • Click the Add button (+) in the upper-right corner.
  • Choose the Development method, and click Continue.
  • Choose the App ID you used for development (the App ID that matches your bundle ID) from the App ID pop-up menu, and click Continue.
  • Select the certificates, and click Continue.
  • Select the devices you wish to include in this provisioning profile
  • Enter a profile name, and click Continue.
  • Click Done.

Create .ipa file.

  • Open the Xcode, choose a Generic iOS Device.
  • Under the Project section click Archive.
  • Select the Archive, click Export and then choose Save for AdHoc Deployment.
  • Select the development team, and save .ipa file.

Upload to Diawi

  • Go to https://www.diawi.com.
  • Drag and drop the .ipa file of your app.
  • Click Send after the file is uploaded.
  • Copy the Diawi link and send it to testers/users for installation.

Android database connection using greenDAO library

greenDAO : Android ORM (Object/Relational Mapping) for SQLite database.

In Android, while dealing with big data projects we may require storing data locally. So very first thing comes in mind is SQLite.

But it may be complex to write SQL query for each transaction and it can be time-consuming.

Here is a simple solution to deal with android local database, greenDAO.

greenDAO is an object/relational mapping (ORM) tool for Android. It offers an object-oriented interface to the relational database SQLite.

Simple Guide:

Here are quick steps to start using greenDAO in our Android projects.

Add below dependencies into build.gradle(Module: app) file

apply plugin: 'org.greenrobot.greendao'

dependencies {

compile 'org.greenrobot:greendao-generator:3.2.0'
compile 'org.greenrobot:greendao:3.2.0'

}

And below code in build.gradle(Project: projectName) file

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'org.greenrobot:greendao-gradle-plugin:3.2.1'
    }
}

Let’s create a class which will handle the database creation, say DbMain.java. For better understanding, we will create a commonly used table, Users table.

public class DbMain {
    public static void main(String args[]) throws Exception {
        Schema schema = new Schema(1, 
                             "your_package_name_goes_here");

        Entity users = schema.addEntity("Users");
        users.addLongProperty("Id")
             .primaryKey()
             .autoincrement();
        users.addStringProperty("Name");
        users.addLongProperty("Phone").unique();

        DaoGenerator daoGenerator = new DaoGenerator();
        daoGenerator.generateAll(schema, "./app/src/main/java");
    }
}

Here, Schema class constructor has two parameters version and package_name. Whenever you change the database structure, add/delete/update table or table columns, you will need to increment the version by 1 and run this DbMain.java class.

 

How to create a table using greenDao?

Very simple, use Entity class, provide the table name in addEntity(table_name) method as a parameter, this will automatically create a table for you. Use the instance of it to add columns in the table. You can update it anytime, just remember to increment the version value by 1.

Entity users = schema.addEntity("Users");

The class DbMain.java not only creates a table but also it generates few more classes automatically.

  • DaoMaster.java: This class has the operations for the overall database. It is Auto Generated by greenDao and don’t edit this class.
  • DaoSession.java: This class creates a session for each table. It is Auto Generated by greenDao and don’t edit this class.
  • UsersDao.java: For each table, there is a separate Dao class which will operate only on the table. It is Auto Generated by greenDao and don’t edit this class.
  • Users.java: This is just a model class (POJO class), which helps to bind the data to operate on the table. It is Auto Generated by greenDao and don’t edit this class.

 

How to run the DbMain.java class?

Right click on DbMain.java class, click on Run “DbMain.main()” or simply press ctrl+shift+F10. By running this class means, recreating the data structure. Refer below screen shots for quick understanding.

android_db

android_db1

Now, whenever you click on Run button in the toolbar, you might end up with running DbMain.java class each time. You will need to change Run Configuration to run your application.

Go to Run —> Edit Configurations —> from left panel select Android App —> app folder —> click on Ok. That’s it!

android_db2

android_db3

Now click on Run button, you will be able to run your project’s default configuration.

Till now we just created an environment to play and now it’s time to play!

CURD using greenDao

Create a data entry in a table.

 DaoSession daoSession = AppController.getInstance()
                                      .getDaoMaster()
                                      .newSession();
 UsersDao usersDao = daoSession.getUsersDao();
 Users user = new Users();
 user.setName("Qice");                   
 user.setPhone(9000000000);
 usersDao.insert(user); //This will add a row in the Users table.

Update data entry in a table.

 DaoSession daoSession = AppController.getInstance().getDaoMaster().newSession();
 
 UsersDao usersDao = daoSession.getUsersDao();
 try{
     User> user = usersDao.queryBuilder()
                      .where(UsersDao.Properties.Id.eq(1))
                      .uniqueOrThrow();

     user.setName("Qice Technologies");
     user.setPhone(9000000001);
     usersDao.update(user); // this line will update the data

 } catch(Exception e) {
  //catch the exception, if there is no row available for the id.
 }

Read the data from a table.

 DaoSession daoSession = AppController.getInstance()
                                      .getDaoMaster()
                                      .newSession();
 UsersDao usersDao = daoSession.getUsersDao();

 List<Users> users =  usersDao.queryBuilder().list(); 

 // This line gets all the row from the table, 
 //you can add  where clause to add constraints.

Delete data entry from a table.

DaoSession daoSession = AppController.getInstance().getDaoMaster().newSession();
 
 UsersDao usersDao = daoSession.getUsersDao();
 try{
 User> user = usersDao.queryBuilder()
                      .where(UsersDao.Properties.Id.eq(1))
                      .uniqueOrThrow();

 usersDao.delete(user); //this line will delete the data entry for the id.

 } catch(Exception e) {
    // catch the exception, if there is no row available for the id.
 }

You can find a complete sample of the Android project using greenDao in our GitHub repository.

 

How to use Dagger 2 in Android

Dagger 2: One of the efficient dependency injection framework.

What is dependency injection?

Wiring classes together. That is one class is dependent on other is a dependency. Passing the object to the class rather than letting it create is Dependency Injection.

Why dependency injection?

It is good for testing. It makes code loosely coupled and easy to move anywhere across the application.

Why Dagger 2?

It is easy and efficient to use. Annotation based. An important aspect of Dagger 2 is that the library generates code for classes annotated with the @Component interface. You can use a class prefixed with Dagger. e.g. TestComponent interface can be used as DaggerTestComponent class. Dagger 2 relies purely on using Java annotation processors and compile-time checks to analyze and verify dependencies.

It is useful to avoid NullPointerException in activity/fragment/service over objects.

How to use dependency injection using Dagger 2?

Dagger 2 is an annotation based dependency injection framework, so everything is wrap up with annotation.

There are some annotations defined to use on different things like @Module annotation on class, @Component on an interface, @Provides on methods, @Inject on variables, parameters, constructors, etc.

Let’s have an example!

Very first thing we will require in our project to start is dependencies. So let’s put it in the build.gradle file of project’s app module.

dependencies {
    //dagger2 dependecies
    compile "com.google.dagger:dagger:2.9"
    annotationProcessor "com.google.dagger:dagger-compiler:2.9"
    provided 'javax.annotation:jsr250-api:1.0'

    //Retrofit dependencies useful to do network calls
    compile 'com.squareup.retrofit2:retrofit:2.0.2'
    compile 'com.squareup.retrofit2:converter-gson:2.0.2'
}

@Module: It signals to Dagger to search within the available methods for possible instance providers.

Now, create a class say, AppModule.java

@Module
public class AppModule {
    Application application;

    public AppModule(Application application){
        this.application = application;
    }

    @Provides
    @Singleton
    Application provideApplication(){
        return application;
    }

}

We will create one more class say NetModule.java

@Module
public class NetModule {

    String mBaseUrl;

    // Constructor needs one parameter to instantiate.
    public NetModule(String baseUrl) {
        this.mBaseUrl = baseUrl;
    }
    //Remember, Dagger will only look for methods annotated with
    //@Provides
    @Provides
    @Singleton
    // Application reference must come from AppModule.class
    SharedPreferences providesSharedPreferences(Application 
                                        application) {
        return PreferenceManager
               .getDefaultSharedPreferences(application);
    }

    @Provides
    @Singleton
    Gson provideGson() {
        GsonBuilder gsonBuilder = new GsonBuilder();
        gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy
                                  .LOWER_CASE_WITH_UNDERSCORES);
        return gsonBuilder.create();
    }

    @NonNull
    @Provides
    @Singleton
    Retrofit provideRetrofit(@NonNull Gson gson) {
        Retrofit retrofit = new Retrofit.Builder()
               .addConverterFactory(
                 GsonConverterFactory.create(gson))
                .baseUrl(mBaseUrl)
                .build();
        return retrofit;
    }
}

Now you might get clear idea that what will be the use of the first module. AppModule class provides the Application object which will useful in NetModule class in a provideSharedPreference() method as a parameter.

@Provides: It denotes to Dagger that the method defined just below to the @Provides annotation is the constructor for the return type. In a method with @Provides annotation, all the parameters should come from outside no matter how many parameters you will require. This method will return the object based on Scope.

@Singleton: It is the scope for the objects returned by the method. @Singleton annotation signals to the Dagger compiler that the instance should be created only once in the application.

@Component: Now let’s see how to use @Component annotation,

@Singleton
@Component (modules = {AppModule.class, NetModule.class})
public interface NetComponent {

    void inject(MainActivity activity);
    
    /* Create different inject() method for different         
    activities/fragent/service */
   
    void inject(MyFragment fragment);
    void inject(MyService service);

}

This is nothing but an interface annotated with @Component. It assigns references in our activities, services, or fragments to have access to singletons we earlier defined.

Note that the activities, services, or fragments that can be added should be declared in this interface with individual inject() methods. We can name the method something else but it is recommended to use as it is.

Next step is, build the component. We should do all this work within a Application class since these instances should be declared only once throughout the entire lifespan of the application, remember we have given the Singleton scope.

public class MyApp extends Application {
   private final String TAG = getClass().getSimpleName();
   private static NetComponent netComponent;
    
    @Override
    public void onCreate() {
         super.onCreate();
         /*Add all the list of modules that are part of the 
           component here */
         netComponent = DaggerNetComponent.builder()
                .appModule(new AppModule(this))
                .netModule(new NetModule("http://google.com"))
                .build();

        Log.e(TAG, "onCreate: netComponent = "+netComponent );
    }

    public static NetComponent getNetComponent() {
        return netComponent;
    }
}

DaggerNetComponent is an auto-generated class, Dagger will generate it at compile time.

If a Dagger 2 component does not have any constructor arguments for any of its modules, we can use .create() as a shortcut instead:

netComponent = DaggerNetComponent.create();

How to get the object in Activity/Fragment?

Here is a MainActivity.java class which will call to the Dagger component and gets the injected objects.

public class MainActivity extends AppCompatActivity {
    @Inject
    SharedPreferences sharedPreferences;
    private final String TAG = getClass().getSimpleName();

    @Inject
    InjectConstructor injectConstructor;

    @Inject
    Retrofit retrofit;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        MyApp.getNetComponent().inject(this);

        // Here we will get all the injected class's objects here
        Log.e(TAG, "onCreate: sharedPreferences = 
                   "+sharedPreferences );
        Log.e(TAG, "onCreate: injectConstructor = 
                   "+injectConstructor );
        Log.e(TAG, "onCreate: retrofit = "+retrofit );

        /* We are getting InjectConstructor class object without 
         calling its constructor with new keyword and can 
         access its methods too. */
      
        injectConstructor.testIt();

    }

}

Note that Dagger does not support injection into private fields.

public class InjectConstructor {
    private final String TAG = getClass().getSimpleName();

    @Inject
    public InjectConstructor (){
        Log.e(TAG, "InjectConstructor: Inside of Constructor");
    }

    public void testIt(){
        Log.e(TAG, "testIt: Inside a method of 
                 InjectConstructor");
    }
}

If you see, InjectConstructor class is used in above MainAcitivity. What is it? A simple class whose constructor is annotated with @Inject annotation.

If you want to create an instance of a class without calling its constructor with a new keyword, you can just add @Inject annotation above the class’s constructor. Doing this Dagger gets a signal that needs to create an instance for the class, it will create automatically.  You need to add @Inject annotation over the class object declaration while using it in Activity/Fragment/any other classes.

 

Android network call using Retrofit library

Retrofit : A type-safe HTTP client for Android and Java.

Nowadays, a Smart phone becoming a trend. And hence the scope of Android is increasing continuously. But we also need security while transferring our data on the network. So here is a type-safe library which takes care of the security while making network calls in Android programming.

Retrofit is used to make network calls (REST). This is an annotation based library by Square.

It reduces the long code and makes server calls in few lines of code, which also reduces the time and efforts of a developer.

There are five built-in annotations in Retrofit GET, POST, PUT, DELETE, and HEAD. We will see few of them in brief later.

 Let’s see a sample first

Very first thing, add below dependencies in your project build.gradle(Module: app) file,

compile 'com.google.code.gson:gson:2.6.2'
compile 'com.squareup.retrofit2:retrofit:2.0.2'
compile 'com.squareup.retrofit2:converter-gson:2.0.2'

Second, add an internet permission in AndroidManifest.xml file because we are dealing with network,

<uses-permission android:name="android.permission.INTERNET"/>

Now, Create a new class to create an instance of Retrofit with base Url of your backend API.

public class ApiClient implements Constant {
private static Retrofit retrofit = null;

public static Retrofit getClient() {
if (retrofit==null) {
retrofit = new Retrofit.Builder()
.baseUrl(BASE_BACKEND_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
}

Next, create an interface which will have an actual call to the server, let’s called it ApiInterface.java

public interface ApiInterface {
  @GET("endpoint/user/get_all/")  //this is the rest api url
   Call<Response> getAllUsers(@Query("api_key") String apiValue);

    /* You can also specify query parameters in the URL.
      The response of above and this below query will be same. */
    
    @GET("endpoint/style/all/?api_key=apiValue")
    Call<RegionResponse> getAllUsers();

}

 

Next, create another class, which will hold the response returned by the API.
Here, @SerializedName(“response”) is a key of the response object.

public class Response {

@SerializedName("response")
private ArrayList<ResponseModel> results;

public ArrayList<ResponseModel> getResults() {
return results;
}
public void setResults(ArrayList<ResponseModel> results) {
this.results = results;
}
}

Create a model class(pojo class) to hold the response for each object. @SerializedName holds the key of the field.

public class ResponseModel {

@SerializedName("id")
private String id;
@SerializedName("name")
private String name;
@SerializedName("image")
private String imageUrl;

public ResponseModel (String id, String name, String imageUrl){
super();
this.id = id;
this.name = name;
this.imageUrl = imageUrl;

}

public String getId(){
return id;
}
public void setId(String id){
this.id = id;
}
public String getImageUrl(){
return imageUrl;
}
public void setImageUrl(String imageUrl){
this.imageUrl = imageUrl;
}
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}

}

Now finally, lets make a call from the activity. Let’s create it!

public class MainActivity extends AppCompatActivity{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Create instance of get Retrofit instance and connect with the network call methods.
ApiInterface apiService = ApiClient.getClient().create(ApiInterface.class);

// Make a call to specific server API
Call<ResponseObject> call = apiService.getAllUsers(API_KEY);
call.enqueue(new Callback<ResponseObject>() {
@Override
public void onResponse(Call<ResponseObject> call, retrofit2.Response<ResponseObject> response) {
// Here you will get the response.
int statusCode = response.code();
ArrayList<ResponseModel> responseModel = response.body().getResults();
Log.e(TAG, "onResponse: statusCode = "+statusCode+" responseModel = "+responseModel);
// Now you can set your adapter for RecyclerView etc...
}

@Override
public void onFailure(Call<com.ilandmusic.retrofit.Response> call, Throwable t) {
// Log error here since request failed
Log.e(TAG, t.toString());
}
});
}
}

Give a try to above code and I hope you will be able to make the first request of server API using the Retrofit library!

 

Understand use of Retrofit

Retrofit supports
* query parameter support
* Object conversion to request body (e.g., JSON, protocol buffers)
* Multipart request body and file upload

Built-in annotations :

GET Method
Lets see how we can get list of all users just by writing couple of lines.

@GET("endpoint/user/get_all/")
Call<Response> getAllUsers(@Query("api_key") String apiValue);

You can also specify query parameters in the URL. The response of above and this below query will be same.

@GET("endpoint/user/get_all/?api_key=apiValue")
Call<Response> getAllUsers();

Also can specify the path, as shown below example,

@GET("endpoint/user/{id}")
Call<Response> getUserDetails(@Path("id") int id, @Query("api_key") String apiValue);

You can send headers by defining @Headers annotation on request call method or as a parameter to the request call method with @Header annotation. Below example explain itself.

@Headers({
"api_key: Api-value",
"token: Tokan-value"
})
@GET("endpoint/user/{id}")
Call<Response> getUserDetails(@Path("id") int id);

POST Method
An object can be specified for use as an HTTP request body with the @Body annotation. Below example shows how we can make a POST server call,

@POST("endpoint/user/create")
Call<User> createUser(@Body User user);

If you are using converter on Retrofit instance, the object user will be converted using it. If no converter is added, only RequestBody can be used as a object. Above query can be,

@POST("endpoint/user/create")
Call<User> createUser(@Body RequestBody user);

If you want to send sensitive data but without @Body, like user details over a network, no worries, Retrofit has the @FormUrlEncoded annotation. @FormUrlEncoded this will encode the data in form of key-value pair which will be annotated with @Field containing the name and the object providing the value.

@FormUrlEncoded
@POST("endpoint/user/edit")
Call<User> updateUser(@Field("first_name") String first, @Field("last_name") String last);

PUT Method
You can send Multipart requests by using @Multipart annotation on the request call method. Parts are declared using the @Part annotation.

@Multipart
@PUT("endpoint/user/image")
Call<User> updateUser(@Part("image") RequestBody image, @Part("description") RequestBody description);

Create your own Custom Input View

While working on a client project, we had to build a custom input view which allowed users to respond back soon.

UIKit allows apps to customize input views for the system keyboard, it will allow customizing the selection for the input view

After figuring out input views, I found it is easy to create your own custom input view

Let’s get started how to build a sample app to use custom input view

Final_Sample

This is how it will look after building

Creating a custom input view

Let’s create a Custom Input view named Keyboard To get started, Create a new Xcode project or open an existing project. Select File\New\File choose View in User Interface Section name the File as Keyboard, it will create a new file as Keyboard.xib

Here we can use any UI element, we have to display list of message template, we will use collection view for that

  • Drag a Collection View to view give 4 constraint to its margin
  • Make a class for keyboard xib, File\New\File in iOS section choose Cocoa Touch and subclass as UIView name it as Keyboard.swift
  • Set the nibs file owner as Keyboard.swift, please take a note that we have to set File owner as our custom class Keyboard.swift not, and make sure that the custom class for the root view is blank

file_owner

  • Make a new collection view cell
  • In xib add a textview, set its editable false and add 4 constraint to view and take a reference of it in Keyboard.swift

now put the following code in Keyboard.swift

import UIKit
protocol KeyboardDelegate: class {
    //Called when keyboard button tapped
    func keyWasTapped(character: String)
}

protocol KeyboardDataSource: class {
    //Data array for keyboard
    func dataForKeyboard()-> [String]
}

class Keyboard: UIView {
    @IBOutlet var dataCollectionView: UICollectionView!
    static let collectionViewIdentifier = "DataSelectionCell"
    fileprivate let sectionInsets = UIEdgeInsets(top: 10.0, left: 10.0, bottom: 10.0, right: 10.0)
    // This variable will be set as the view controller so that
    // the keyboard can send messages to the view controller.
    weak var delegate: KeyboardDelegate?
    // This variable will ask for data to the view controller.
    weak var dataSource: KeyboardDataSource?

    // MARK:- keyboard initialization
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        initializeSubviews()
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
        initializeSubviews()
    }
    // 1
    func initializeSubviews() {
        let xibFileName = "Keyboard" // xib extention not included
        let view = Bundle.main.loadNibNamed(xibFileName, owner: self, options: nil)?[0] as! UIView
        self.addSubview(view)
        view.frame = self.bounds
        //Register collection view cell
        let cellNib = UINib(nibName: Keyboard.collectionViewIdentifier, bundle: nil)
        dataCollectionView.register(cellNib, forCellWithReuseIdentifier: Keyboard.collectionViewIdentifier)
        dataCollectionView.delegate = self
        dataCollectionView.dataSource = self
    }
    // 2
    func viewTapped(gestureReconizer: UITapGestureRecognizer) {
        let point = gestureReconizer.location(in: dataCollectionView)
        let indexPath = dataCollectionView.indexPathForItem(at: point)
        // Trigger delegate for tap action
        dataCollectionView.delegate?.collectionView!(dataCollectionView, didSelectItemAt: indexPath!)
    }

}
// MARK:- UICollectionViewDelegate
extension Keyboard: UICollectionViewDelegate {
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        // delegate (ie, the view controller)
        let dataArray = dataSource?.dataForKeyboard()
        let message = dataArray?[indexPath.row]
        self.delegate?.keyWasTapped(character: message!) // Inform delegate
    }
}
// MARK:- UICollectionViewDataSource
extension Keyboard: UICollectionViewDataSource {
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        if let dataArray = self.dataSource?.dataForKeyboard(){
            return dataArray.count
        }
        return 0
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = dataCollectionView.dequeueReusableCell(withReuseIdentifier: Keyboard.collectionViewIdentifier, for: indexPath) as! DataSelectionCell
        let dataArray = dataSource?.dataForKeyboard()
        // Add tap gesture to TextView to send tap event, as TextView will cover entire cell
        let tap = UITapGestureRecognizer(target: self, action: #selector(viewTapped(gestureReconizer:)))
        cell.dataTextView.addGestureRecognizer(tap)
        cell.dataTextView.text = dataArray?[indexPath.row] //Set text for TextView
        return cell
    }
}
// MARK:- UICollectionViewDelegateFlowLayout
extension Keyboard : UICollectionViewDelegateFlowLayout {

    func collectionView(_ collectionView: UICollectionView,
                        layout collectionViewLayout: UICollectionViewLayout,
                        sizeForItemAt indexPath: IndexPath) -> CGSize {
        //Setup grid like view
        //Device screen width
        let width = UIScreen.main.bounds.size.width
        //calculation of cell size
        return CGSize(width: ((width / 2) - 15), height: (collectionView.frame.height/2) - 20 )
    }

    func collectionView(_ collectionView: UICollectionView,
                        layout collectionViewLayout: UICollectionViewLayout,
                        insetForSectionAt section: Int) -> UIEdgeInsets {
        return sectionInsets
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
        return sectionInsets.left
    }
}

The only method in the delegate which notifies when input view button tapped. KeyboardDelegate:

func keyWasTapped(character: String)

DataSource has only one method which accepts [String] for data KeyboardDataSource

func dataForKeyboard()-> [String]
  1. Here we will initialize subviews and configure DataSource and delegate for collection view
  2. This is UITapGestureRecognizer receiver action depending on the tap it calculate selection for collection view
  3. We have added UITapGestureRecognizer to the TextView to get the selection

Usage

Use of this input view is pretty simple as we use other input views

    var keyboardView: Keyboard? //Custom view refrence
    override func viewDidLoad() {
        super.viewDidLoad()
        exampleTextView.layer.borderColor = UIColor.lightGray.cgColor
        exampleTextView.layer.borderWidth = 1
        //1
        keyboardView = Keyboard(frame: CGRect(x: 0, y: 0, width: 0, height: 216)) //Intialize custom input view
        keyboardView?.delegate = self //delegate
        keyboardView?.dataSource = self //datasource
        //2
        exampleTextView.inputView = keyboardView //Assign input view
        //Dismiss keyboard tap recognizer
        let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(ViewController.dismissKeyboard))
        view.addGestureRecognizer(tap)
    }
  1. Initialize keyboard view with frame and set its delegate and dataSource to self
  2. Assign Keyboard view to TextView inputView

We will have to implement KeyboardDelegate method confirm the protocol

    extension ViewController: KeyboardDelegate {
        func keyWasTapped(character: String) {
            //3
            //Insert charaters to the TextView
            exampleTextView.insertText(character)
        }
    }
  1. Here we will add selected text to our textview

if you want to toggle input views then you should add IBAction for the button

    //4
    //Toggle between system and custom input view
    @IBAction func chatButtonDidTapped(_ sender: AnyObject) {
        if(exampleTextView.inputView == nil){
            // replace system keyboard with custom keyboard
            exampleTextView.inputView = keyboardView
        }
        else{
            exampleTextView.inputView = nil
        }
        exampleTextView.becomeFirstResponder()
        exampleTextView.reloadInputViews()
    }
  1. This is button action to toggle between system and custom keyboard.

This is how we have built custom input view, the final output will look like as Final_Sample_gif

You can customize it with TableView, replace with images to select the image.

You can download complete sample from Here

Custom Picker

screenCustom Picker is an easy to use and customizable alternate to UIPickerView. It is written in Swift language. The Custom Picker started as normal UIPicker but it was to limited in its design and methods. Also, I want to achieve a flat-picker with selected area background customizable which was not possible with default UIPicker.

So I made a use UITableView and customize its scroll to get the look and feel of UIPickerView. With the use of UITableView, I have made the picker flat. Now the second limitation of UIPickerView i.e. non-customizable selected area, for this I used an overlay view and customize it according to my need.

Requirements

It requires Xcode 7.0+ and Swift 2.3.

Application Usage

Custom Picker includes a sample of the project of Unit Conversion where a user can select the to and from units and input the number in one UITextField and the output will be shown in other UITextField.

Create a new picker

To use this picker you have to instantiate the CutomPickerView like instantiate any normal UIPickerView and implements it CustomPickerViewDelegate and CustomPickerViewDataSource methods

    let leftPickerView = CustomPickerView(frame: CGRectMake(0.0, 0.0, self.contentViewOfLeftpicker.frame.width,  self.contentViewOfLeftpicker.frame.height))

    leftPickerView.delegate = self
    leftPickerView.dataSource = self

    self.contentViewOfLeftpicker!.addSubview(leftPickerView)

Implement the Delegate and DataSource

The delegate methods that needs to be overridden are

func customPickerView(customPickerView: CustomPickerView, titleForRow row: Int, forLabel label: UILabel) -> String

 func customPickerView(customPickerView: CustomPickerView, didSelectRow row: Int)

func rowHeightForCustomPickerView(customPickerView: CustomPickerView) -> CGFloat

func labelStyleForCustomPickerView(customPickerView: CustomPickerView, forLabel label: UILabel)

func imageStyleForCustomPickerView(customPickerView: CustomPickerView, forImageView imageView: UIImageView)

Firstly you must rowHeightForCustomPickerView(_:)

func rowHeightForCustomPickerView(customPickerView: CustomPickerView) -> CGFloat {
        return 50.0
    }

Then you have to implement titleForRow method it sets the title for each row in a picker

func customPickerView(customPickerView: CustomPickerView, titleForRow row: Int, forLabel label: UILabel) -> String {

        return (label.tag == -1) ? pickerDataFullForm[row] as! String : pickerDataShortForm[row] as! String
    }

Next is the method that provides the didSelectRow

func customPickerView(customPickerView: CustomPickerView, didSelectRow row: Int) {

        leftPickerView.labelUnitFull.text = pickerDataFullForm[row] as? String
        leftPickerView.labelUnitShort.text = pickerDataShortForm[row] as? String

    }

Next method is labelStyleForCustomPickerView method this method is used to give custom style to UILabel in CustomPickerView

func labelStyleForCustomPickerView(customPickerView: CustomPickerView, forLabel label: UILabel) {
        if (label.tag == -1) {

            label.textColor = UIColor.blackColor()
            label.font = UIFont(name: "HelveticaNeue-Bold", size: 20.0)
        }else{

            label.textColor = UIColor.lightGrayColor()
            label.font = UIFont(name: "HelveticaNeue-Bold", size: 15.0)
        }
    }

And the last delegate method is imageStyleForCustomPickerView this is used to give any background image to the overlay view.

    func imageStyleForCustomPickerView(customPickerView: CustomPickerView, forImageView imageView: UIImageView) {
        if customPickerView == leftPickerView {
            leftPickerView.arrowImage.image = UIImage(named: "LeftArrow")
        }
    }

CustomPickerViewDataSource

The CustomPickerView consists of only one data source method. This method returns the number of rows in that picker:

 func numberOfRowsInCustomPickerView(customPickerView: CustomPickerView) -> Int

Using Testfairy for an Android App

TestFairy is a beta testing platform for mobile apps allowing developers to see videos showing users behavior. It allows Android apps as well as iOS apps.

This includes App Distribution, Video Recording, Logs, Crash Reports, User feedback on shake, Community Pages. It gives 2 months free trial.

After that, you have to choose the plan, according to the plan they will provide the features. In basic plan, they have given, App Distribution and Crash Reports features.

Also, they have provided the SDKs for Android and iOS as well. You can refer this link for Testfairy SDK implementation in Android and this link for Testfairy SDK implementation in iOS.

For developer level testing you can use Genymotion and for tester level testing you can use Testfairy.

Using Genymotion in Android

Let’s get familiar with Genymotion.

Genymotion is the most powerful Android emulator for app developers & testers.

Developers can install the plugin of Genymotion in Android Studio plugin with few simple steps:

  1. Click File–> Settings
  2. Click on Plugins tabs left side on Settings window.
    settings
  3. Click Browse Repositories and search for Genymotion.
    genymotion_plugin
    On the right side of Browse Repositories pop up, there will be a button with name “Install”.
  4. Click on install button.
  5. Restart your Android Studio IDE. Now you can see, Genymotion is installed in Android studio.


How to use the Genymotion for the app?

  • After installation of Genymotion plugin, there will be a phone like an icon on the toolbar of Android Studio.
  • After clicking that icon Genymotion Device Manager will open, where you can see the list of available Genymotion virtual devices.
  • Select one of them or you can create the virtual device by clicking on New button.
  • Creating new virtual device will show a popup shown below,virtual_device_creation_wizard
    Where you have options to choose Android versions and Device model after that click on Next button.

    • You can choose the name for the virtual device shown as below,virtual_device_name
    • Click Next and download and install will start for the virtual device.That’s all. Now you can click on start button to start Genymotion virtual device.Now you can run your App on this device. Just hit Run button on your Android Studio’s toolbar, choose your virtual device from Available Virtual Devices and it will run your project on it.
    • To avoid the issues in your android app you can follow Do’s and Don’ts for Android this blog.

Do’s and Don’ts for Android Apps

There are few things most of the new android developers face. To avoid these issues while developing one should be following best practices to improve the functionality of the android app and to attain optimum results.

Do’s  for Android App Development

  • Prefer ConstraintLayout while making designs in xml file of android. It is more flexible. If necessary, look for others.
  • Give meaningful id name for each view in xml. For example, If you are using EditText for username and password then their names should be editTextUsername and editTextPassword.
  • If any group of views is repeatable in more than one xml file, make a different file with that group of views and include it where you want. Eg. <include layout=“@layout/toolbar”/> : toolbar is a different layout which has the design for common toolbar used in the app.
  • Write all the texts, used in the app, in string.xml file and give reference of that string in layout xml file. Also, all the messages should be defined in string.xml file. Later on, it will be easier to modify it.
  • Write all the dimensions, used in the app, in dimen.xml file and give reference of that dimensions in layout xml file.
  • Write all the colors, used in the app, in color.xml file and give reference of that color in layout xml file.
  • Try using style.xml file for custom view design instead of doing it programmatically.
  • All constants should be declared in separate java file say, Constants.java, Each constant should be static(it will allocate memory only one time and can be reusable) and final(not changeable).
  • Define all commonly used methods in one class say, Utils.java.
  • If code lines are exceeding 15-20 lines, put the code in a method.
  • The naming of variables, objects, methods, classes, interfaces, etc should be self-explanatory.
  • It’s better to write a separate class for any reusable functionality.
  • Project code should be divided into different modules. According to the module, you can put the java files in different packages under the main package.
  • The module can be Login, DrawerItems (if an app has the drawer, list out all the main files of drawer items), etc.. and it will depend on the project’s features.
  • Use fragment, if you want to show more than one screen in single Activity. A fragment is nothing but the part, part of design. It is totally dependent on Activity.
  • Interfaces can be used to pass the data of one class to other class(it can be Activity, Fragment, Service, or simple Java class) on any triggered event.
  • Service: It is used as a background task. Eg. To do network call, to play music in the background, etc.
  • Use Glide/Picasso library to load image URLs.
  • Use Retrofit library to make network calls. See this blog how to use it in android.
  • Use GreenDAO library to do local database transactions.
  • Use Genymotion virtual device to run the android app.
  • You can use Testfairy to distribute your android app remotely.

 

Similarly, you should know what are bad practices in android development, what to avoid while developing an android app. Below are some points developers should avoid.

Don’ts for Android App Development

  • Try to avoid using Relative layout, if it is not necessary.
  • Avoid using nested Linear layout it affects the UI performance.
  • Never use ‘my’ prefix in naming conventions. Also never use shortcut names. Eg tvNm, etPwd, etc.
  • Your code length for a class should not exceed 1000 lines. If possible try to add a supporting class.
  • Avoid using hard-coded values in Activity/Fragment as much as possible.
  • Avoid using libraries as a project module, instead, add dependencies in build.gradle file of app Module of the project.
  • Don’t use too many libraries.