Showing posts with label Android. Show all posts
Showing posts with label Android. Show all posts

Tuesday, 24 January 2017

Handle special numbers not handled by libphonenumber.

libphonenumber is Google's common Java, C++ and JavaScript library for parsing, formatting, and validating international phone numbers. 

Project on GitHub is here - https://github.com/googlei18n/libphonenumber

to add it to your android project use -

 compile 'com.googlecode.libphonenumber:libphonenumber:8.0.1'

Use :

public static boolean isSpecialNumber(PhoneNumber number) {
    if (number.getCountryCode() == 31) {
        // handle special M2M numbers: 11 digits starting with 097[0-8]        
        final Pattern regex = Pattern.compile("^97[0-8][0-9]{8}$");
        Matcher m = regex.matcher(String.valueOf(number.getNationalNumber()));
        return m.matches();
    }
    return false;
}


public void handleSpecialCases(Phonenumber.PhoneNumber phoneNumber) {
    PhoneNumberUtil util = PhoneNumberUtil.getInstance();

    // Argentina numbering rules
    int argCode = util.getCountryCodeForRegion("AR");
    if (phoneNumber.getCountryCode() == argCode) {
        // forcibly add the 9 between country code and national number
        long nsn = phoneNumber.getNationalNumber();
        if (firstDigit(nsn) != 9) {
            phoneNumber.setNationalNumber(addSignificantDigits(nsn, 9));
        }
    }
}

private int firstDigit(long n) {
    while (n < -9 || 9 < n) n /= 10;
    return (int) Math.abs(n);
}

private long addSignificantDigits(long n, int ds) {
    final long orig = n;
    int count = 1;
    while (n < -9 || 9 < n) {
        n /= 10;
        count++;
    }
    long power = ds * (long) Math.pow(10, count);
    return orig + power;
}

Sunday, 8 January 2017

conquer the asynchronous behavior of callbacks.

Hey, I'm writing after a long time. Okay so why am I writing here? (even I don't know).

Anyways, one of the pains in my ass has been controlling the asynchronous behavior of callbacks and synchronizing it with my code control statements.

Example : Using addValueEventListener in firebase. What happens actually Firebase loads and synchronizes data asynchronously. Now you know what all difficulties may be faced due to this. Consider one example:



private boolean checkQuizStartTime()
{
    FirebaseDatabase database = FirebaseDatabase.getInstance();

    final int[] flag = {0};

    DatabaseReference mainDbRef = database.getReferenceFromUrl("https://....com/");

    DatabaseReference quizStartTime = mainDbRef.child("quiz_start");

    quizStartTime.addValueEventListener(new ValueEventListener() {
        @Override        public void onDataChange(DataSnapshot dataSnapshot) {

            String value = dataSnapshot.getValue(String.class);
            if (value.equals("yes"))
                flag[0] = 1;
            else                flag[0] = 0;
        }

        @Override        public void onCancelled(DatabaseError databaseError) {

        }
    });

    return flag[0] == 1;
}

The Method I wrote above always returns false no matter what value is present at key "start_quiz". Again the reason is the asynchronous execution of the callback. By the time the value of flag[0] gets updated the methods returns.

Anyways there as much trivial (jugadu in Hindi) solutions to it. Previously when I use to encounter such situation I use this trivial method only. The example in this situation you can use SharedPreference when you store the value inside the onDataChanged method and later you can access the value stored inside the SharedPreference file.


Another way can be waiting for few seconds until the asynchronous call gets completed and updated the value written inside the onDataChanged method. You can use Handler like this:



new android.os.Handler().postDelayed(
        new Runnable() {
    public void run() {
    }
}, 2000);


But doing all these things may work for some particular test instances. But this is not going to make our application scalable. So let us try to understand the reason behind this and learn proper concepts for it.



You have two choices for dealing with the asynchronous nature of this loading:
  1. squash the asynchronous bug (usually accompanied by muttering of phrases like: "it was a mistake, these people don't know what they're doing")
  2. embrace the asynchronous beast (usually accompanied by quite some hours of cursing, but after a while by peace and better behaved applications)

make the asynchronous call behave synchronously


For this we can use Semaphore class, we can create its object before the callback and use release method on its object inside the onDataChagned method.

Semaphore semaphore = new Semaphore(0);
....callback
onDataChanged()
....semaphore.release();


But there are problems I faced on my android. It blocked my app however it worked fine on JVM.

A more Ideal way is to 

embrace the asynchronous nature of data synchronization in Firebase


If you instead choose to embrace asynchronous programming, you should rethink your application's logic.
You currently have "First load the bookmarks. Then load the sample data. And then load even more."
With an asynchronous loading model, you should think like "Whenever the bookmarks have loaded, I want to load the sample data. Whenever the sample data has loaded, I want to load even more." The bonus of thinking this way is that it also works when the data can be changed and thus synchronized multiple times: "Whenever the bookmarks change, I want to also load the sample data. Whenever the sample data changes, I want to load even more."
In code, this leads to nested calls or event chains:
private boolean checkQuizStartTime()
{
    FirebaseDatabase database = FirebaseDatabase.getInstance();

    final int[] flag = {0};

    DatabaseReference mainDbRef = database.getReferenceFromUrl("https://-.,,.com/");

    DatabaseReference quizStartTime = mainDbRef.child("quiz_start");

    quizStartTime.addValueEventListener(new ValueEventListener() {
        @Override        public void onDataChange(DataSnapshot dataSnapshot) {

            String value = dataSnapshot.getValue(String.class);
            myMethod(value);
        }

        @Override        public void onCancelled(DatabaseError databaseError) {

        }
    });

    return flag[0] == 1;
}
In the above code, we don't just wait for a single value event, we instead deal with all of them. This means that whenever the bookmarks are changed, the isonDataChange executed and we (re)load the sample data (or whatever other action fits your application's needs).

Tuesday, 10 May 2016

Bug removed for fedora : Unable to run mksdcard SDK tool

If you are directly installing Android Studio on Fedora or any other Linux system then while installing SDK it gives an error message : 

Unable to run mksdcard SDK tool

This is one big bug and people can easily find its solution for ubuntu but for fedora you need to different libraries to install .
Just copy paste the command below in your terminal and this will solve your problem :

sudo dnf install compat-libstdc++-296 compat-libstdc++-33 glibc libgcc nss-softokn-freebl libstdc++ ncurses-libs zlib-devel.i686 ncurses-devel.i686 ant

Tuesday, 12 April 2016

My First Android app activity_main.xml file


<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="@dimen/padding"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.aupadhyay.myfirstapp.MainActivity">


    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:text="Enter Details"
        android:layout_marginTop="10dp"
        android:id="@+id/textView"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true" />

    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/editTextName"
        android:hint="Enter Name"
        android:layout_below="@+id/textView"
        android:layout_marginTop="42dp"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true" />

    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/editTextPhone"
        android:hint = "Enter Phone Number"
        android:layout_below="@+id/editTextName"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_marginTop="46dp" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Submit"
        android:id="@+id/button"
        android:layout_below="@+id/editTextPhone"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="46dp" />
</RelativeLayout>

My First Android app MainActivity.java file


package com.aupadhyay.myfirstapp;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
import android.widget.Button;
import android.widget.EditText;

public class MainActivity extends AppCompatActivity {

    EditText editTextName, editTextPhone;
    Button btnSubmit;

    void initViews()
    {
        editTextName = (EditText)findViewById(R.id.editTextName);
        editTextPhone = (EditText)findViewById(R.id.editTextPhone);

        btnSubmit = (Button)findViewById(R.id.button);

        btnSubmit.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) { // v = btnSubmit;
                String strName = editTextName.getText().toString().trim();
                String strPhone = editTextPhone.getText().toString().trim();

                Toast.makeText(MainActivity.this, "You Entered : "+strName+" : "+strPhone, Toast.LENGTH_LONG).show();

            }
        });
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initViews();
        Toast.makeText(this, "MainActivity - onCreate",Toast.LENGTH_SHORT).show();
    }

    @Override
    protected void onStart() {
        super.onStart();
        Toast.makeText(this, "MainActivity - onStart",Toast.LENGTH_SHORT).show();
    }

    @Override
    protected void onResume() {
        super.onResume();
        Toast.makeText(this, "MainActivity - onResume",Toast.LENGTH_SHORT).show();
    }

    @Override
    protected void onPause() {
        super.onPause();
        Toast.makeText(this, "MainActivity - onPause",Toast.LENGTH_SHORT).show();
    }

    @Override
    protected void onStop() {
        super.onStop();
        Toast.makeText(this, "MainActivity - onStop",Toast.LENGTH_SHORT).show();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Toast.makeText(this, "MainActivity - onDestroy",Toast.LENGTH_SHORT).show();
    }

    @Override
    protected void onRestart() {
        super.onRestart();
        Toast.makeText(this, "MainActivity - onRestart",Toast.LENGTH_SHORT).show();
    }
}

Saturday, 9 April 2016

Example to understand Life Cycle of an Activity in different stages

Below I have written the MainActivity.java file :

package com.aupadhyay.myfirstapp;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toast.makeText(this, "MainActivity - onCreate",Toast.LENGTH_LONG).show();
    }

    @Override
    protected void onStart() {
        super.onStart();
        Toast.makeText(this, "MainActivity - onStart",Toast.LENGTH_LONG).show();
    }

    @Override
    protected void onResume() {
        super.onResume();
        Toast.makeText(this, "MainActivity - onResume",Toast.LENGTH_LONG).show();
    }

    @Override
    protected void onPause() {
        super.onPause();
        Toast.makeText(this, "MainActivity - onPause",Toast.LENGTH_LONG).show();
    }

    @Override
    protected void onStop() {
        super.onStop();
        Toast.makeText(this, "MainActivity - onStop",Toast.LENGTH_LONG).show();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Toast.makeText(this, "MainActivity - onDestroy",Toast.LENGTH_LONG).show();
    }

    @Override
    protected void onRestart() {
        super.onRestart();
        Toast.makeText(this, "MainActivity - onRestart",Toast.LENGTH_LONG).show();
    }
}

You need to register this MainActivity.java file in your manifest file (AndroidManifest.xml) with the MAIN action and LAUNCHER category.

You need to see the sequence of the output and then you can get to know about the way of order of execution of the different API's on creation and destruction of the activity.