Pages

Thursday, February 18, 2016

some emojis not showing on old android skd/api's

(also check out how i show country flags for androids, instead of huge letters, where should be emoji flags Android regional indicator symbols)

Easy fix. For example i need men/woman 🚺🚹.

Lol they show as <?> here, heres the image:



But on lower sdks they show up as a unknown symbol.

The general idea is to get the char codes behind these symbols, and if the string contains them, then put a image from the raw folder in place of the emoji in a spannable string.

You can get emoji images from emojipedia http://emojipedia.org/mens-symbol/

In a string these characters come in a format of two characters:
man symbol - '\uD83D','\uDEB9'
woman symbol - '\uD83D','\uDEBA'


So, i cycle through string with a for loop and check if charAt(i) == '\uD83D' and if next char is '\uDEB9' or '\uDEBA' then continue with the image stuff. Btw on newer java sdk you can use a String/char in a switch:

 SpannableString ss = new SpannableString(input);  
 if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {  
   int ssl = ss.length();
   for (int i = 0; i < ssl; i++){  
     char c = ss.charAt(i);  
     if (c == '\uD83D' && i < ssl - 1){  
       char next = ss.charAt(i + 1);  
       float k = 1f;  
       switch (next){  
         case '\uDEB9'://man emoji
           Bitmap man = getBitmapFromRaw("man", context);  
           if (man != null) {  
             Drawable d = new BitmapDrawable(context.getResources(), man);
             float scale = context.getResources().getDisplayMetrics().density * k;
             float w = d.getIntrinsicWidth() / scale;
             float h = d.getIntrinsicHeight() / scale;
             d.setBounds(0, 0, (int) w, (int) h);
             ImageSpan is = new ImageSpan(d, ImageSpan.ALIGN_BASELINE);
             ss.setSpan(is, i, i + 2, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);          }  
           break;  
         case '\uDEBA'://woman emoji
           Bitmap woman = getBitmapFromRaw("woman", context);  
           if (woman != null) {  
             Drawable d = new BitmapDrawable(context.getResources(), woman);
             float scale = context.getResources().getDisplayMetrics().density * k;
             float w = d.getIntrinsicWidth() / scale;
             float h = d.getIntrinsicHeight() / scale;
             d.setBounds(0, 0, (int) w, (int) h);
             ImageSpan is = new ImageSpan(d, ImageSpan.ALIGN_BASELINE);
             ss.setSpan(is, i, i + 2, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);          }  
           break;  
         default: break;      }  
     }  
   }  
 }  


The getBitmapFromRaw method:
   public static Bitmap getBitmapFromRaw(String filename, Context context) {  
     return getBitmapFromRaw(filename, context, false);  
   }  
   public static Bitmap getBitmapFromRaw(String filename, Context context, boolean reduceQuality) {  
     int identifier = context.getResources().getIdentifier(filename, "raw", context.getPackageName());  
     Bitmap bmp = null;  
     if (identifier != 0) {  
       InputStream is = context.getResources().openRawResource(identifier);  
       BufferedInputStream bis = new BufferedInputStream(is);  
       BitmapFactory.Options options = null;  
       if (reduceQuality) {  
         options = new BitmapFactory.Options();  
         options.inSampleSize = 2;  
         options.inPreferredConfig = Bitmap.Config.RGB_565;  
       }  
       bmp = BitmapFactory.decodeStream(bis, null, options);  
     }  
     return bmp;  
   }  




Wednesday, February 10, 2016

parse.com current user returning null sometimes

A cool way of dealing with this problem i have found. In the activity, where current user is needed, i have a private field currentUser;


  1. Current user is set to a static helper class on login/registration or autologin
  2. Where needed in activity onCreate i get currentUser from my helper class by a getter.
  3. If after that currentUser is null, then i call the helper class initCurrentUser method, passing the activity instance as "this". 
  4. The method accepts anything that implements my custom UserCallback like this:public static <T extends CustomUserCallback> void initUser(final T t)
  5. In it i try to get user from parse by ParseUser.getCurrentUser(); If ok then return the value via callback's method setUser(user) that sets the currentUser in the calling activity.
  6. If parse returns null user, then i try to login the user with saved auth data in shared preferences, and return the user via callback.
  7. If even the login fails, that means, most likely, that password was changed, then app goes to the login screen.

And in the activity i dont initialize views in onCreate method. The method initializing views is called when activity has a valid currentUser, from onCreate or from the setUser from the callback.

Monday, February 1, 2016

Android Thread vs Handler/Runnable vs AsyncTask

There are several ways to use these classes. I do like this:

1) Handler/Runnable:

new Handler().post(new Runnable() {
    @Override    public void run() {
        ...
    }
});

  • The code runs on UI thread, therefore it can access Views. 
  • If you put a breakpoint inside the run method, the UI will be frozen, so this code can freeze UI and cause ANRs. 
Currently i don't see any real advantage of using a Handler.

2) Thread:

new Thread(new Runnable() {
    @Override    public void run() {
        ...
    }
}).start();

  • Runs in background thread. Accessing views will throw an exception. 
  • When stopped on breakpoints inside run() the UI is operational.
Views can be accessed like this from inside the run method (this particular code is from a Fragment, thats why there is a getActivity() in front. From an Activity just call runOnUiThread): 

getActivity().runOnUiThread(new Runnable() {
    @Override    public void run() {
        ...
    }
});

Code inside run() runs on UI thread. 

This is the way to go, when performance is at stake. For example IO operations and ect.

3) AsyncTasks:

  1. You create a class that  extends AsyncTask
  2. Implement doInBackground and onPostExecute (if needed) methods
  3. I usually use a constructor to pass needed variables.
Then you invoke your AsyncTask: 
new MyAsyncTast(param1).execute();

What happens here:
  • The doInBackground methods runs on separate thread, exactly like the Thread's run();
  • The onPostExecute method runs on UI thread, just like if you call runOnUiThread with a Thread approach.
As I understand AsyncTask is the same as using the new Thread approach. You could actually create your own AsyncTask class by using the new Thread methods. 

Advantages of using AsyncTask is reusability. If the code runs only in one place, then i'd use Thread.
A disatvantage is a bit harder way of getting back to calling activity. For example to call a View's method inside onPostExecute you have invent some additional logic, if compared to Thread method.

What you can do here:

  1. Pass an activity instance and call a public method. (Not the best way)
  2. Pass an activity that implements an interface, and overrides needed methods.
  3. The callback method: as a parameter pass an abstract class, and implement needed methods. Something like this:
The Callback class:

public abstract class CustomCallback {

    public void successCallback(){

    }
}


The AsyncTask call:


new AsyncDBSizeManager(param1, new CustomCallback(){
    @Override    public void successCallback() {
        ...
    }
}).execute();


Then call the callback from onPostExecute:


customCallback.successCallback();