Saturday, October 27, 2012

Show Dialog in Android After Device Boot Is Finished

What to do if you want to show an alert dialog right after the device boot is finished? You receive ACTION_BOOT_COMPLETED but you can't show an alert dialog from the broadcast receiver if you don't have any activities. Thus, what you need is to create one. But if you want your users to see only the dialog, your activity must be completely transparent.

1. Transparent activity style.
First, you need to create a transparent activity. Add this style to styles.xml:

Any activity that has this style as a theme will be transparent.

2. Activity with a simple dialog.
Now lets create an activity that will show a simple dialog:
public class MainActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setMessage("Message")
               .setTitle("Title")
               .setCancelable(false)
               .setPositiveButton("OK", new DialogInterface.OnClickListener()
               {
                   public void onClick(DialogInterface dialog, int id) 
                   {
                       MainActivity.this.finish();
                   }
               });
  
  
        AlertDialog alert = builder.create();
        alert.show();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }
}
3. Broadcast receiver.
Obviously you need a broadcast receiver that handles ACTION_BOOT_COMPLETED broadcast (note that you need a permission to receive the broadcast):
public class OnBootReceiver extends BroadcastReceiver
{
    @Override
    public void onReceive(Context context, Intent intent)
    {  
        Intent startIntent = new Intent(context, MainActivity.class);
        startIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(startIntent);
    }
}
4. Android manifest
In your manifest you must assign the created style for your activity and register the broadcast receiver. It should look something like this (note that you need a permission to receive the broadcast):


    
    

    
        
            
                

                
            
        
        
        
            
                
            
        
    


That's pretty much all you need to show a dialog after the device's boot is complete. Source code can be obtained from Github.

Monday, October 22, 2012

Get the APK's Code Size in Android

In the early version of my DELTA Statistics application for Android I collected code size of an installed application. When a lot of statistics about an installed application is easy to get, code size slightly more complicated.

 Step by step:
  1. Download IPackageStatsObserver.aidl and PackageStats.aild. You can get them from here.
  2. Create new package in your project and name it android.content.pm.
  3. Add IPackageStatsObserver.aidl and PackageStats.aild to the created package. You can do it by right-clicking on the package name and choosing Import option. Then select File System and click Next. Browse to the folder where you downloaded .aidl files, check the files you need and click Finish.
  4. Check that Eclipse automatically generated IPackageStatsObserver.java in gen.android.content.pm. Mine has some warning but trying to fix them is just a waist of time.
  5. Now we can get code size of application. In the example below I collect code size of all the installed applications. When I first wrote it I got a weird bug. Sometimes code size was 0 for the last N applications. N was different practically all the time, so, I though that it was a concurrency issue. As I understand, getPackageSizeInfo() method is invoked in another thread and because of that for loop can end before all the values of code size have been computed. To solve this problem I included a semaphore that is acquired at each loop iteration and is released after code size has been computed. It guarantees that getPackageSizeInfo() will finish before the next loop iteration will start.
    context = getApplicationContext();
    final PackageManager packageManager = context.getPackageManager();
    List<ApplicationInfo> installedApplications = 
        packageManager.getInstalledApplications(PackageManager.GET_META_DATA);
    
    // Semaphore to handle concurrency
    final Semaphore codeSizeSemaphore = new Semaphore(1, true);
    
    // Code size will be here
    long codeSize = 0;
    
    for (ApplicationInfo appInfo : installedApplications)
    {
        try
        {
            codeSizeSemaphore.acquire();
        }
        catch (InterruptedException e)
        {
            e.printStackTrace(System.err);
        }
        
        // Collect some other statistics
        
        // Collect code size
        try 
        {
            Method getPackageSizeInfo = 
                packageManager.getClass().getMethod("getPackageSizeInfo", 
                                                    String.class,
                                                    IPackageStatsObserver.class);
            
            getPackageSizeInfo.invoke(packageManager, appInfo.packageName, 
                                      new IPackageStatsObserver.Stub()
            {
                // Examples in the Internet usually have this method as @Override.
                // I got an error with @Override. Perfectly works without it.
                public void onGetStatsCompleted(PackageStats pStats, boolean succeedded) 
                    throws    RemoteException
                {
                    codeSize = pStats.codeSize;
                    codeSizeSemaphore.release();
                }
            });
        }
        catch (Exception e)
        {
            e.printStackTrace(System.err);
        }
    }
    

Tuesday, October 16, 2012

Skype Icon Missing (Windows Default Icon Instead)

Finally got my hands on this annoying problem with the Skype's icon. Instead of Skype logo icon I had an ugly default Windows icon in the taskbar (I have Skype pinned to the taskbar). When I unpinned Skype, the icon came back but no for a long time. Default Windows icon appeared after the next right click on the taskbar icon.

It happened to be not a Skype's problem but a problem with Windows icon cache. I rebuilt it, restarted the computer and the problem was solved. So, that's what you need to do to rebuild the icon cache:
  1. Open Command Prompt (how? ehhh, type cmd in the search box in start menu).
  2. Type this commands (the last one will reboot the machine)
    taskkill /IM explorer.exe /F
    cd /d %userprofile%\AppData\Local
    del IconCache.db /a
    shutdown /r /f /t 00
After that your machine will reboot and the issue should be fixed.

Sunday, October 14, 2012

Delete Space After Link in HTML

Have you noticed that sometimes you have white space included in your link in the end when you use <a href=""><a/> tag?

Here is an example: Weird Link .

If you look closer you will see white space after the link although I didn't include any in HTML (sorry for the link formatting, it is probably hard to see). I wanted to fix it using CSS but after 15 minutes recognized that it goes away if you put the closing tag </a>  right after the text and not on the next line.

So, this is the same link but with the closing tag on the same line: OK Link.

May be it is intended to be like that but it is still strange that Next Line character is treated like a Space character.

Change Boot Order in GNU GRUB

If you installed Ubuntu then you probably got GNU GRUB 2 with it. It is this thing that allows you to choose what operating system (or tool) you want to boot. Default option is usually your new Ubuntu installation and you have 10 seconds by default to boot something else.

In case if you want to use Windows as your primary operating system and just got Ubuntu for some special case (e.g. I just wanted to play with EXT4 file system), booting Ubuntu by default is not the best option for you. Sometimes you are just not near your computer to choose another OS during this 10 seconds period (happened kind of a lot with me). So, let's change that.

  1. Count the number of the entry you want to boot by default (its row number in GNU GRUB) when you machine starts. 
  2. Load Ubuntu and start Terminal.
  3. Type sudo gedit /etc/default/grub.
  4. Change GRUB_DEFAULT to the number of the entry you want to boot by default (0 is the first entry (row), 1 is the second, etc.). I have 7 entries and want to load the last one, so  GRUB_DEFAULT=6.
  5. You can change GRUB_TIMEOUT to change how much time (in seconds) the system will wait before loading the default option.
  6. Type sudo update-grub in terminal to update GRUB configuration.
  7. Restart Ubuntu and enjoy.

Thursday, October 4, 2012

UNIX Permissions (chmod Tips)

Some basic useful stuff on UNIX permissions and chmod command:
  1. 'ls' command outputs permissions for the specified file. It outputs permissions for all the files and directories in the current directory if you don't specify FILE_NAME:
    ls -lg FILE_NAME
  2. If you want to set permission for particular files or directories then you can use find + exec. The first command will change permission of all the directories. The second one specifies the search pattern - all .HTM files.
    find . -type d -exec chmod 755 {} \;
    find . -type f -name '*.htm*' -exec chmod 755 {} \;
    755 here is the permissions code.