Pages

Thursday, September 8, 2016

We are worms on a tree of knowledge.




I wonder, is it possible and will there be a moment in time when we (or some other being) understands everything about our universe and is completely correct in its assumptions?

I mean physics, chemistry, math, science etc.

Or at least not a being but some information bank that has all the correct information.

Imagine the beauty of this knowledge. It amazes me how everything is connected to everything. You can drop terms like math, physics, geometry, algebra, chemistry and just say "information" or "knowledge".

And humans due to their physiological limitations surely cant hold all that information at once and understand that all. That saddens me.

We are like worms crawling on a tree. A worm will never see the tree completely, only a tiny fragment around itself. But what if worms could communicate, like internet, and they would spread evenly on all the tree and build a model of a tree in some virtual space. And they would understand that there are other trees around. And there would be worms believing that they live on a wall, despise the common knowledge. Hell, some would even say that a huge bearded worm created our tree.

Thursday, March 31, 2016

android improved emulator detection

Detects droid4x, genymotion and the default android studio emulator.

   public static boolean deviceIsEmulator() {  
     int rating = 0;  
     if (Build.PRODUCT.contains("sdk") ||  
         Build.PRODUCT.contains("google_sdk") ||  
         Build.PRODUCT.contains("Droid4X") ||  
         Build.PRODUCT.contains("sdk_x86") ||  
         Build.PRODUCT.contains("sdk_google") ||  
         Build.PRODUCT.contains("vbox86p")) {  
       rating++;  
     }  
     if (Build.MANUFACTURER.equals("unknown") ||  
         Build.MANUFACTURER.equals("Genymotion")) {  
       rating++;  
     }  
     if (Build.BRAND.equals("generic") ||  
         Build.BRAND.equals("generic_x86")) {  
       rating++;  
     }  
     if (Build.DEVICE.contains("generic") ||  
         Build.DEVICE.contains("generic_x86") ||  
         Build.DEVICE.contains("Droid4X") ||  
         Build.DEVICE.contains("generic_x86_64") ||  
         Build.DEVICE.contains("vbox86p")) {  
       rating++;  
     }  
     if (Build.MODEL.equals("sdk") ||  
         Build.MODEL.equals("google_sdk") ||  
         Build.MODEL.contains("Droid4X") ||  
         Build.MODEL.equals("Android SDK built for x86_64") ||  
         Build.MODEL.equals("Android SDK built for x86")) {  
       rating++;  
     }  
     if (Build.HARDWARE.equals("goldfish") ||  
         Build.HARDWARE.equals("vbox86")) {  
       rating++;  
     }  
     if (Build.FINGERPRINT.contains("generic/sdk/generic") ||  
         Build.FINGERPRINT.contains("generic_x86/sdk_x86/generic_x86") ||  
         Build.FINGERPRINT.contains("generic_x86_64") ||  
         Build.FINGERPRINT.contains("generic/google_sdk/generic") ||  
         Build.FINGERPRINT.contains("vbox86p") ||  
         Build.FINGERPRINT.contains("generic/vbox86p/vbox86p")) {  
       rating++;  
     }  
     return rating > 4;  
   }  

Thursday, March 17, 2016

Android multiple fragments with lists, context menu uses same onContextItemSelected method

I have several fragments in one activity, each with a listview. Each listview has context menu on long click. So far all works ok. But when i select an option from the menu, only one fragments onContextItemSelected method is called, and it uses it's activity's list.

How it should work - the onContextItemSelected should return false if it is not the correct one to be used. I found the answer here:

http://stackoverflow.com/questions/25096534/context-menu-in-fragment-uses-listview-from-a-different-fragment-registerforcon

This way all the unwanted methods will return false and the one you need will be invoked.

@Override
public boolean onContextItemSelected(MenuItem item) {
    if (getUserVisibleHint()) {
            //your code
        }
    }
    return false;
}

Thursday, March 10, 2016

Rounded corners problems/error in android sdk prior to v12

So i had a problem when rounded corners were broken on lower sdk's.

For example, you made a drawable/selector/etc for your button with rounded corners on the left and not rounded on the right. Like on picture (1).


If you check how it looks on a device with sdk prior to 12 (I checked on a genymotion 2.3.7 android device), the button will look something like (2). Because, apparently, there is a bug that flips bottom corners.

The fix is very easy. Specify rounded corner values in the dimens.xml file and use them like android:padding="@dimen/attr1" this. Create a values-v12 folder and make a dimens.xml file there.

Sample contents:
<resources><dimen name="name">10dp</dimen></resources>


Here, specify the correct values for each rounded corner. For (1) it would be 0dp for top right, 0dp for bottom right, 10dp for top left, 10dp for bottom left corners.

These values will be used on devices starting with sdk lvl 12.

So in the original dimens.xml you should specify the fixed values to workaround the bug, swap places the bottom corners like this: 0dp top right, 10dp bottom right, 10dp topleft, 0dp bottom left.

This will result in a shape (1).

Oh, btw, the preview in Android Studio anyway shows gibberish with the corners, just ignore it.


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();