Tuesday, August 18, 2015

Why Google why


Tuesday, March 3, 2015

How to CORRECTLY take a screenshot using Android MediaProjection API

With the MediaProjection API in Android 5.0 it is possible to: 
capture the contents of the main screen (the default display) into a Surface object, which your app can then send across the network
The process to capture the screen contents is described in MediaProjection API Demo. This demo uses a SurfaceView to show a miniature version of the device's screen creating a Droste effect. But the surface view is not very helpful to actually use the captured screen i.e you can not get the screen capture as an image or a video. If you need to capture the screen as an image you can use and ImageReader object and pass its surface to createVirtualDisplay() method.

The problem is that it is not very straight forward to get the captured screen from ImageReader object either. The image that you get from ImageReader is raw i.e it has stride pixels in the image buffer and you need to take care of them your self. There are many people out there having difficulties getting the image from an ImageReader e.g here, here and here. The solution described in some of these Stackoverflow posts does work but it reduces the image quality significantly and also it is a lot more work and therefore it is slow. 

Below I describe a simpler method to get the image from ImageReader once you have created a virtual display using the ImageReader's surface. For completeness sake I describe the steps for creating a virtual display as well but if you are familiar with them just skip to step 3.

Step 1
To capture the screen contents you need a MediaProjection object. But first you need the user's permission to capture the screen using following code:
MediaProjectionManager projectionManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);startActivityForResult(projectionManager.createScreenCaptureIntent(), PERMISSION_CODE);
This will start a dialog activity to ask user for permission to capture the display contents. 

Step 2
Once user allows screen capture, we can get a MediaProjection object in the onActivityResult() method using the following code.
MediaProjectionManager projectionManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);
mProjection = projectionManager.getMediaProjection(resultCode, data);
The "data" passed to getMediaProjection() call is the intent data passed to onActivityResult() method. 

Step 3
The call to create a virtual display takes width and height of the virtual display and a surface object which will be used to save the device's screen. To the capture the screen as an image or a series of images we use surface of an ImageReader object. Create an ImageReader object as follows:
mImageReader = ImageReader.newInstance(mWidth, mHeight, ImageFormat.RGB_565, 2);
Step 4
Once we have the MediaProjection and ImageReader objects, we can start capturing screen by creating a virtual display using following code:
mProjection.createVirtualDisplay("screen-mirror", mWidth, mHeight, mDensity, flags, mImageReader.getSurface(), null, null);
Step 5
Now we can get the screen capture as image using the following code.
final Image.Plane[] planes = image.getPlanes();
final ByteBuffer buffer = planes[0].getBuffer();
int offset = 0;
int pixelStride = planes[0].getPixelStride();
int rowStride = planes[0].getRowStride();
int rowPadding = rowStride - pixelStride * mWidth;
// create bitmap
Bitmap bmp = Bitmap.createBitmap(mWidth+rowPadding/pixelStride, mHeight, Bitmap.Config.RGB_565);
bmp.copyPixelsFromBuffer(buffer);
image.close();
now the bitmap object bmp has the your screen capture in correct format and you can simply use Bitmap.compress() method to convert it to JPEG, PNG or WEBP format. 
The error that most people make here is that they create bitmap of the wrong size, they create bitmap of same width and height as the virtual display but the problem is that the image you get from ImageReader has some extra pixels in there on each line. So you need to account for those as well when creating the bitmap to copy the pixel data. Therefore when creating bitmap I am passing "mWidth+rowPadding/pixelStride" as width. This is for sake of clarity so it is easy to understand otherwise you can instead pass "rowStride/pixelStride".

Thursday, November 6, 2014

Three parts of a web page

As far as I see there are three components of a web page:

1. HTML
2. CSS
3. Javascript

There are different libraries, frameworks and gems dealing with these three aspects. So far, in each of these three areas, I have identified following things that I need to learn, step by step:

HTML: HTML5
CSS: Sass, bootstrap
Javascript: jquery, coffee script

I will keep adding other stuff to this list as I realize or as I come across them.

Tuesday, November 4, 2014

Re learning RoR

I did web development using RubyOnRails for a year after I graduated in 2006. Back then there was not a lot of documentation about it and we had to learn lot of stuff using trial and error. I havent lot of development in RoR since then but now I want to do some serious web development and RoR seems an obvious choice since it is very popular and because I know it a little. So I have started re-learning it. I am going through Ruby On Rails Tutorial book and I intend to finish it. Many things are new and at times it feels too much to even remember all the different frameworks/libraries that keep poping (Saas, bootstrap, coffee script, jquery and etc) not to mention all these gems being used but hopefully I will get the hang of it soon. 

Monday, September 8, 2014

Common RVM commands


  • Installing RVM

$>​ curl -L https://get.rvm.io | bash -s stable
$> rvm autolibs packages
          If you dont have curl you can install it using
$> sudo apt-get update
$> sudo apt-get install curl

  • Install specific ruby version:

          Installing version 2.0.0
$> rvm install 2.0.0
          Installing version 1.9.2
$> rvm isntall 1.9.2

  • Use a specific ruby version

$> rvm use 2.0.0

  • Use a specific ruby version and make it the default

$> rvm use --default 1.9.2

Thursday, June 12, 2014

Android: Open Facebook official app from your own app with different intents

Opening Facebook's official android app from your own app is really easy. You just need to create an intent with correct uri and start and activity with that intent. The app will open with the right page, group, picture, video or etc.

Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(uri));
startActivity(intent);

where uri could be any of the following:

fb://root
fb://feed
fb://feed/{userID}
fb://profile
fb://profile/{userID}
fb://page/{id}
fb://group/{id}
fb://place/fw?pid={id}
fb://profile/{#user_id}/wall
fb://profile/{#user_id}/info
fb://profile/{#user_id}/photos
fb://profile/{#user_id}/mutualfriends
fb://profile/{#user_id}/friends
fb://profile/{#user_id}/fans
fb://search
fb://friends
fb://pages
fb://messaging
fb://messaging/{#user_id}
fb://online
fb://requests
fb://events
fb://places
fb://birthdays
fb://notes
fb://places
fb://groups
fb://notifications
fb://albums
fb://album/{%s}?owner={#%s}
fb://video/?href={href}

Thursday, June 5, 2014

Android game engines

I want to try my hand at game development for smart phones. I am familiar with Android and own 4-5 Android devices so the platform choice is straight forward. But I cant seem to decide which game engine to start with. I have tried googling a lot and there is no clear winner. The most popular game engines seem to be Unity, Corona and Cocos2D. Cocos2D is the only one of these which is totally free. So I think I will start with Cocos2D. If someone has other suggestions please let me know.