Screenshot Service : Service « Network « Android






Screenshot Service

  
//package pl.polidea.asl;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.security.InvalidParameterException;
import java.util.UUID;

import android.app.Service;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.Bitmap.Config;
import android.graphics.Matrix;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.view.Display;
import android.view.Surface;
import android.view.WindowManager;

class ScreenshotService extends Service {
  
  /*
   * Action name for intent used to bind to service.
   */
  public static final String BIND = "pl.polidea.asl.ScreenshotService.BIND";  

  /*
   * Name of the native process.
   */
  private static final String NATIVE_PROCESS_NAME = "asl-native"; 

  /*
   * Port number used to communicate with native process.
   */
  private static final int PORT = 42380;

  /*
   * Timeout allowed in communication with native process.
   */
  private static final int TIMEOUT = 1000;  

  /*
   * Directory where screenshots are being saved.
   */
  private static final String SCREENSHOT_FOLDER = "/sdcard/screens/";



  
  @Override
  public void onCreate() {
    Log.i("service", "Service created."); 
  }



  /*
   * Checks whether the internal native application is running,
   */
  private boolean isNativeRunning() {
    try {
      Socket sock = new Socket();
      sock.connect(new InetSocketAddress("localhost", PORT), 10);  // short timeout
    }
    catch (Exception e) {
      return false;
    }
    return true;
//    ActivityManager am = (ActivityManager)getSystemService(Service.ACTIVITY_SERVICE);
//    List<ActivityManager.RunningAppProcessInfo> ps = am.getRunningAppProcesses();
//
//    if (am != null) {
//      for (ActivityManager.RunningAppProcessInfo rapi : ps) {
//        if (rapi.processName.contains(NATIVE_PROCESS_NAME))
//          // native application found
//          return true;
//      }
//
//    }
//    return false;
  }
  
  
  /*
   * Internal class describing a screenshot.
   */
  static final class Screenshot {
    public Buffer pixels;
    public int width;
    public int height;
    public int bpp;
    
    public boolean isValid() {
      if (pixels == null || pixels.capacity() == 0 || pixels.limit() == 0) return false;
      if (width <= 0 || height <= 0)  return false;
      return true;
    }
  }
  
  
  /*
   * Determines whether the phone's screen is rotated.
   */
  private int getScreenRotation()  {
    WindowManager wm = (WindowManager)getSystemService(WINDOW_SERVICE);
    Display disp = wm.getDefaultDisplay();
    
    // check whether we operate under Android 2.2 or later
    try {
      Class<?> displayClass = disp.getClass();
      Method getRotation = displayClass.getMethod("getRotation");
      int rot = ((Integer)getRotation.invoke(disp)).intValue();
      
        switch (rot) {
          case Surface.ROTATION_0:  return 0;
          case Surface.ROTATION_90:  return 90;
          case Surface.ROTATION_180:  return 180;
          case Surface.ROTATION_270:  return 270;
          default:          return 0;
        }
    } catch (NoSuchMethodException e) {
      // no getRotation() method -- fall back to getOrientation()
      int orientation = disp.getOrientation();

      // Sometimes you may get undefined orientation Value is 0
      // simple logic solves the problem compare the screen
      // X,Y Co-ordinates and determine the Orientation in such cases
      if(orientation==Configuration.ORIENTATION_UNDEFINED){

        Configuration config = getResources().getConfiguration();
        orientation = config.orientation;

        if(orientation==Configuration.ORIENTATION_UNDEFINED){
          //if height and widht of screen are equal then
          // it is square orientation
          if(disp.getWidth()==disp.getHeight()){
            orientation = Configuration.ORIENTATION_SQUARE;
          }else{ //if widht is less than height than it is portrait
            if(disp.getWidth() < disp.getHeight()){
              orientation = Configuration.ORIENTATION_PORTRAIT;
            }else{ // if it is not any of the above it will defineitly be landscape
              orientation = Configuration.ORIENTATION_LANDSCAPE;
            }
          }
        }
      }
      
      return orientation == 1 ? 0 : 90; // 1 for portrait, 2 for landscape
    } catch (Exception e) {
      return 0; // bad, I know ;P
    }
  }
  

  /*
   * Communicates with the native service and retrieves a screenshot from it
   * as a 2D array of bytes.
   */
  private Screenshot retreiveRawScreenshot() throws Exception {
    try {
      // connect to native application
      Socket s = new Socket();
      s.connect(new InetSocketAddress("localhost", PORT), TIMEOUT);

      // send command to take screenshot
      OutputStream os = s.getOutputStream();
      os.write("SCREEN".getBytes("ASCII"));

      // retrieve response -- first the size and BPP of the screenshot
      InputStream is = s.getInputStream();
      StringBuilder sb = new StringBuilder();
      int c;
      while ((c = is.read()) != -1) {
        if (c == 0) break;
        sb.append((char)c);
      }

      // parse it
      String[] screenData = sb.toString().split(" ");
      if (screenData.length >= 3) {
        Screenshot ss = new Screenshot();
        ss.width = Integer.parseInt(screenData[0]);
        ss.height = Integer.parseInt(screenData[1]);
        ss.bpp = Integer.parseInt(screenData[2]);

        // retreive the screenshot
        // (this method - via ByteBuffer - seems to be the fastest)
        ByteBuffer bytes = ByteBuffer.allocate (ss.width * ss.height * ss.bpp / 8);
        is = new BufferedInputStream(is);  // buffering is very important apparently
        is.read(bytes.array());        // reading all at once for speed
        bytes.position(0);          // reset position to the beginning of ByteBuffer
        ss.pixels = bytes;
        
        return ss;
      }
    }
    catch (Exception e) {
      throw new Exception(e);
    }
    finally {}

    return null;
  }

  /*
   * Saves given array of bytes into image file in the PNG format.
   */
  private void writeImageFile(Screenshot ss, String file) {
    if (ss == null || !ss.isValid())    throw new IllegalArgumentException();
    if (file == null || file.length() == 0)  throw new IllegalArgumentException();
    
    // resolve screenshot's BPP to actual bitmap pixel format
    Bitmap.Config pf;
    switch (ss.bpp) {
      case 16:  pf = Config.RGB_565; break;
      case 32:  pf = Config.ARGB_8888; break;
      default:  pf = Config.ARGB_8888; break;
    }

    // create appropriate bitmap and fill it wit data
    Bitmap bmp = Bitmap.createBitmap(ss.width, ss.height, pf);
    bmp.copyPixelsFromBuffer(ss.pixels);
    
    // handle the screen rotation
    int rot = getScreenRotation();
    if (rot != 0) {
      Matrix matrix = new Matrix();
      matrix.postRotate(-rot);
      bmp = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), matrix, true);
    }

    // save it in PNG format
    FileOutputStream fos;
    try {
      fos = new FileOutputStream(file);
    } catch (FileNotFoundException e) {
      throw new InvalidParameterException();
    }
    bmp.compress(CompressFormat.PNG, 100, fos);
  }

  /*
   * Takes screenshot and saves to a file.
   */
  private String takeScreenshot() throws IOException {
    // make sure the path to save screens exists
    File screensPath = new File(SCREENSHOT_FOLDER);
    if (!screensPath.mkdirs())  return null;
      
    // construct screenshot file name
    StringBuilder sb = new StringBuilder();
    sb.append(SCREENSHOT_FOLDER);
    sb.append(Integer.toHexString(UUID.randomUUID().hashCode()));  // hash code of UUID should be quite random yet short
    sb.append(".png");
    String file = sb.toString();

    // fetch the screen and save it
    Screenshot ss = null;
    try {
      ss = retreiveRawScreenshot();
    } catch (Exception e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
      return null;
    }
    writeImageFile(ss, file);

    return file;
  }
}

   
    
  








Related examples in the same category

1.Map Service
2.Widget Service
3.Restful web service task
4.Search with Restful service
5.Post Restful service
6.Tracker Service
7.Weather web service
8.Access a Web service using GET
9.Alarm service
10.Get Running Services Info
11.Local service demo
12.extends Service
13.Service structure
14.Clock Back Service
15.Voice Recognition Service
16.is Connected by Context.CONNECTIVITY_SERVICE
17.BeatService extends Service and Thread
18.TimeoutService (beta). Here you can register a timeout.
19.Timeout Service