Settings.canDrawOverlays() allays returns ‘false’ on Android O

I was updating one of my clients app, and testing it how it behaves on Android O (API 26). The app requires permissions to draw over system windows (android.permission.SYSTEM_ALERT_WINDOW). On Android 6 (API 23) and up, you are obligated to request ‘special’ permissions while the app is running.

The ‘SYSTEM_ALERT_WINDOW’ permission is a special permission that breaks the rules set by the new permission model available on Android 6 (API 23) and up. It’s request involves calling Settings.canDrawOverlays() and if it returns ‘false‘ starting ‘Settings‘ where the user can choose to grant your app the ability to draw overlays or not.

if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
{
   // On API 23 and later ask the user to grant us permission to draw system overlay
   // windows.
   if (!Settings.canDrawOverlays(this))
   {
      Intent intent = new Intent(
             Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
             Uri.parse("package:" + getPackageName()));
 
      startActivityForResult(intent, REQUEST_PERMISSION_SYSTEM_OVERLAY_RESULT);
   }
}

There is a bug with Settings.canDrawOverlays() (only) on API 26 where it will always return ‘false’ disregarding the actual user decision. The workaround provided here is a bit ugly, but does not involves restarting the app (which will be quite annoying for the user) after the permission is granted.

The code below first checks the result of System.canDrawOverlays() if it returns ‘true’ it continues with the rest of the application flow. If it returns ‘false’ a check if we are running on Android O (API 26) is performed. If that’s the case, we are calling our ‘workaround’ method.

The ‘workaround’ method tries to add an invisible overlay window on the screen, and if that’s OK we assume that we have a permission to draw overlays, else an exception is thrown.

@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data)
    {
        super.onActivityResult(requestCode, resultCode, data);
 
        if(Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return; if(requestCode == REQUEST_PERMISSION_SYSTEM_OVERLAY_RESULT) { if(Settings.canDrawOverlays(this)) { m_permissionSystemOverlayWindowGranted = true; if(m_permissionReadPhoneStateGranted && m_permissionProcessOutgoingCallsGranted) { startService(new Intent(this, EstatePlusService.class)); m_layoutNoPermissions.setVisibility(View.INVISIBLE); m_progressBar.setVisibility(View.INVISIBLE); m_layoutLogin.setVisibility(View.VISIBLE); } } else if(Build.VERSION.SDK_INT == Build.VERSION_CODES.O) { // NOTE: This is a workaround to fix the bug in Android O where the // Settings.canDrawOverlays() will always return 'false' if(canDrawOverlays(this)) { m_permissionSystemOverlayWindowGranted = true; if(m_permissionReadPhoneStateGranted && m_permissionProcessOutgoingCallsGranted) { startService(new Intent(this, EstatePlusService.class)); m_layoutNoPermissions.setVisibility(View.INVISIBLE); m_progressBar.setVisibility(View.INVISIBLE); m_layoutLogin.setVisibility(View.VISIBLE); } } } } } /** * Workaround for Android O */ public static boolean canDrawOverlays(Context context) { try { WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); if (windowManager == null) { return false; } final View viewToAdd = new View(context); WindowManager.LayoutParams params = new WindowManager.LayoutParams( 0, 0, android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O ?
                                    WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY : WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
                            WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.TRANSPARENT);
            viewToAdd.setLayoutParams(params);
            windowManager.addView(viewToAdd, params);
            windowManager.removeView(viewToAdd);
            return true;
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
 
        return false;
    }

Fighting spammers: Removing Website URL Field from Comment Form

I’m tired of receiving massive amount of spam comments on my blog (1280 spam comments for about a month) and doing:

DELETE FROM `wp_comments` WHERE `comment_approved` = 0

Beside using SI Captcha Anti-Spam which does pretty good job in keeping some of the automated spam bots at bay, I noticed some trend in the spam comments flooding my posts, they are all full of SEO keywords and they are heavy abusing the Website field in the comment form.

Here is a small “plugin” which will remove (unset) the URL field in the comments form:

<?php
/*
Plugin Name: Remove Website field from comments.
*/
function custom_comment_fields( $fields ){
  if(isset($fields['url']))
    unset($fields['url']);
  return $fields;
}
 
add_filter( 'comment_form_default_fields', 'custom_comment_fields' );

Create a file in /wp-content/plugins/ with the code a bough. Go to the ‘Plugins’ section of the admin panel and activate the newly created plugin named “Remove Website field from comments”.

Yey, no more “Website” field in the “Leave a Reply” section 🙂

Java: Parts of the Day

A handy utility method that will return the part of the day, such as morning, afternoon, evening, etc.

public static String getPartOfTheDay(final int hour)
{
    if(hour > 4 && hour < 12)
    {
        if(hour <= 8)
        {
            return "Early Morning";
        }
        else if(hour > 8 && hour < 11)
        {
            return "Morning";
        }
 
        return "Late Morning";        
    }
    else if(hour >= 12 && hour < 17)
    {
        if(hour >= 13 && hour <= 15)
        {   
            return "Early Afternoon";
        }
        else if(hour >= 16)
        {
            return "Late Afternoon";
        }
 
        return "Afternoon";
    }
    else if(hour >= 17 && hour <= 21)
    {
        if(hour <= 19)
        {   
            return "Early Evening";
        }
 
        return "Evening";
    }
    else
    {
        return "Night";
    }
}

The method is based on the following logic, that many people would agree with:

Morning: 5 to 12

  • Early morning: 5 to 8
  • Late morning: 11 to 12

Afternoon: 12 to 17

  • Early afternoon: 13 to 15
  • Late afternoon: 16 to 17

Evening: 17 to 21

  • Early evening: 17 to 21

Night: 21 to 4

Gentoo Linux: Ugly fonts in NetBeans and how to fix them

I recently installed Gentoo GNU/Linux + KDE 5 on my dev machine. One thing that was bugging me was the crappy font rendering in NetBeans.

To relolve the problem, locate your netbeans.conf file. Usually under /etc in your NetBeans installation folder, and append to netbeans_default_options the follwing:

-J-Dswing.aatext=true -J-Dawt.useSystemAAFontSettings=lcd --laf Metal

This will enable font smoothing in SWING and use default system settings for font smoothing. The last entry –laf Metal sets the preferred UI theme for the IDE, it should be Swing based theme such as Metal or Numbus.

Happy coding 🙂

GSM Signal Monitor 1.5 out now!

1-featuredimage
GSM Signal Monitor 1.5 is out now!
This version features new app visual style, additional logging options, bug fixes and Android 5.x and up support.

Version 1.5 Change Log
* New app visual style
* Compatibility with Android 5.x and up
* Fixed bug when clicking over the app notification in the notification area
* GSM Signal monitor will now log (optional) information when the phone is entering roaming state and changes in your mobile data connectivity.
* Fixed bug when no notifications will be made on some devices
* New Google play services version

Get it on Google Play