Android AIDL 实现两个APP之间的跨进程通信实例

 

Android AIDL 实现两个APP之间的跨进程通信实例

1 Service端创建

首先需要创建一个Android工程然后创建AIDL文件,创建AIDL文件主要为了生成继承了Binder的Stub类,以便应用Binder进行进程间通信

servier端结构如下 
Server端结构

AIDL代码如下


// IBookManager.aidl
package com.example.bookserver.aidl;

// Declare any non-default types here with import statements
import com.example.bookserver.aidl.Book;
interface IBookManager {
    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
            double aDouble, String aString);

    List<Book> getBook();
    boolean addBook(in Book book);

}

之后创建一个实现了Parcelable的Book.java类用来传递数据

package com.example.bookserver.aidl;

import android.os.Parcel;
import android.os.Parcelable;

/**
 * Created by SAMSUNG on 2016-09-07.
 */
public class Book implements Parcelable {
    private int id;
    private String name ;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Book{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(this.id);
        dest.writeString(this.name);
    }

    public Book() {
    }

    protected Book(Parcel in) {
        this.id = in.readInt();
        this.name = in.readString();
    }

    public static final Parcelable.Creator<Book> CREATOR = new Parcelable.Creator<Book>() {
        @Override
        public Book createFromParcel(Parcel source) {
            return new Book(source);
        }

        @Override
        public Book[] newArray(int size) {
            return new Book[size];
        }
    };
}
最后我们来写一个Service用于客户端绑定


package com.example.bookserver.service;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;

import com.example.bookserver.aidl.Book;
import com.example.bookserver.aidl.IBookManager;

import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;


public class BookService extends Service {
    private CopyOnWriteArrayList<Book> boookList = new CopyOnWriteArrayList<Book>();
    public BookService() {

    }
    Binder binder = new IBookManager.Stub(){

        @Override
        public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {

        }

        @Override
        public List<Book> getBook() throws RemoteException {
            return boookList;
        }

        @Override
        public boolean addBook(Book book) throws RemoteException {
            return boookList.add(book);
        }
    };
    @Override
    public IBinder onBind(Intent intent) {
      return binder;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Book book = new Book();
        book.setId(12345);
        book.setName("Book 1");
        boookList.add(book);
    }
}

这样Server端就搞定了,接下来就该进行Client端的代码编写了

2 Client端

扫描二维码关注公众号,回复: 632769 查看本文章

Client端结构如下

Client端结构 
首先我们要讲AndroidStudio 通过AIDL生成的Binder导入到Client中并将Book.java也导入到Client中 
然后写进行Service的绑定


package com.example.bookclient;

import android.app.Service;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.IBinder;
import android.util.Log;

import com.example.bookserver.aidl.IBookManager;

import java.util.List;

/**
 * Created by SAMSUNG on 2016-09-07.
 */
public class BookServiceManager {
    Context mContext = null;
    IBookManager mService = null;
    private static BookServiceManager bsm ;
    public static BookServiceManager getInstance(Context context){
        if(bsm==null){
            bsm = new BookServiceManager(context);
        }
        return bsm;
    }
    public IBookManager getBookServie(){
        if(mService==null){
            Log.d("BookServiceManager", "getBookServie: ");
            this.connectService();

        }
        return mService;
    }

    public BookServiceManager(Context mContext) {
        this.mContext = mContext;
    }

    ServiceConnection scc = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.d("BookServiceManager", "getBookServie: 2 ==> Bind ");
            mService = IBookManager.Stub.asInterface(service);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            mService = null;
        }
    };
    public boolean connectService(){
        if(mService == null){
            Log.d("BookServiceManager", "getBookServie: 2");
            Intent intent = new Intent("com.example.bookserver.service.BookService");
            final Intent eintent = new Intent(createExplicitFromImplicitIntent(mContext,intent));
            mContext.bindService(eintent,scc, Service.BIND_AUTO_CREATE);
        }
        return true;
    }

    public static Intent createExplicitFromImplicitIntent(Context context, Intent implicitIntent) {
        // Retrieve all services that can match the given intent
        PackageManager pm = context.getPackageManager();
        List<ResolveInfo> resolveInfo = pm.queryIntentServices(implicitIntent, 0);

        // Make sure only one match was found
        if (resolveInfo == null || resolveInfo.size() != 1) {
            return null;
        }

        // Get component info and create ComponentName
        ResolveInfo serviceInfo = resolveInfo.get(0);
        String packageName = serviceInfo.serviceInfo.packageName;
        String className = serviceInfo.serviceInfo.name;
        ComponentName component = new ComponentName(packageName, className);

        // Create a new intent. Use the old one for extras and such reuse
        Intent explicitIntent = new Intent(implicitIntent);

        // Set the component to be explicit
        explicitIntent.setComponent(component);

        return explicitIntent;
    }
}

最后对设置Button进行调用

package com.example.bookclient;

import android.os.Bundle;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;

import com.example.bookserver.aidl.Book;
import com.example.bookserver.aidl.IBookManager;

public class MainActivity extends AppCompatActivity {
    IBookManager mBookService ;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button button = (Button) findViewById(R.id.button);
        Button addButton = (Button) findViewById(R.id.button3);
        Button findButton = (Button) findViewById(R.id.button2);
        BookServiceManager.getInstance(getApplication()).connectService();
        button.setOnClickListener(new View.OnClickListener(){

            @Override
            public void onClick(View v) {

                mBookService = BookServiceManager.getInstance(getApplication()).getBookServie();

            }
        });

        addButton.setOnClickListener(new View.OnClickListener(){

            @Override
            public void onClick(View v) {
                Book book = new Book();
                book.setId(2345);
                book.setName("add book!!");
                try {
                    mBookService.addBook(book);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }

            }
        });

        findButton.setOnClickListener(new View.OnClickListener(){

            @Override
            public void onClick(View v) {

                try {
                     Log.d("MainActivity", mBookService.getBook().toString());
                } catch (RemoteException e) {
                    e.printStackTrace();
                }

            }
        });
    }
}


1)截屏接口、2)静默安装接口、3)按键控制接口、4)关机/重启控制接口、5)关闭应用接口、

6)未知来源开关接口、7)控制应用使用接口、8)控制推送通知接口、9)控制SD/TF卡接口、10)控制USB口接口、

11) 网址/IP白名单接口、12)APK安装白名单接口、13)应用卸载接口、14)护眼模式开关接口、15)应用联网控制接口、

16)启动Service或Activity接口、17)控制无障碍服务接口、18)控制设备管理器接口、19)控制访问使用记录接口、

20)联系人白名单接口、21)获取联系人白名单接口

package com.prize.txInterface.util;

import com.prize.txInterface.application.TXApplication;

import android.util.Log;

public class TXLog {

	public static int d(String tag, String msg) {
        if (TXApplication.DEBUG) {
            return Log.d(tag, msg+getFunctionName());
        } else {
            return 0;
        }
    }
    public static int i(String tag, String msg) {
        if (TXApplication.DEBUG) {
            return Log.d(tag, msg+getFunctionName());
        } else {
            return 0;
        }
    }
    
    public static int e(String tag, String msg) {
        if (TXApplication.DEBUG) {
            return Log.e(tag, msg+getFunctionName());
        } else {
            return 0;
        }
    }
    /**
     * 方便日志定位
     * add by mafei 
     * @param tag 标签
     * @return
     */
    private static String getFunctionName()  
    {  
        StackTraceElement[] sts = Thread.currentThread().getStackTrace();  
        if(sts == null)  
        {  
            return null;  
        }  
        for(StackTraceElement st : sts)  
        {  
            if(st.isNativeMethod())  
            {  
                continue;  
            }  
            if(st.getClassName().equals(Thread.class.getName()))  
            {  
                continue;  
            }  
            if(st.getClassName().equals(TXLog.class.getName()))  
            {  
                continue;  
            }  
            return "[" + Thread.currentThread().getName() + ": "  
                    + st.getFileName() + ":" + st.getLineNumber() + " "  
                    + st.getMethodName() + " ]";  
        }  
        return null;  
    }  

}

package com.prize.txInterface.provider;

import com.prize.txInterface.util.TXLog;

import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.net.Uri;

public class PrizeWhiteListProvider extends ContentProvider{

	public static final String TAG = "snail_PrizeWhiteListProvider";
	public static final String DB_NAME = "whitelist.db";
	public static final int DB_VESION = 1;
	public static Uri CONTENT_URI_INSTALL = null;
	public static Uri CONTENT_URI_IP = null;
	public static Uri CONTENT_URI_CONTACT = null;
	private static UriMatcher sUriMatcher;
	
	
	public static final String TABLE_NAME_INSTALL = "install";
	public static final String TABLE_NAME_IP = "ip";
	public static final String TABLE_NAME_CONTACT = "contact";
	private static final int _INSTALL = 1;
	private static final int _IP = 2;
	private static final int _CONTACT = 3;
	
	private ContentResolver mContentResolver; 
	static DatabaseHelper mOpenHelper;

	static SQLiteDatabase db;
	
	public static SQLiteDatabase getDbInstance(Context context){
		TXLog.i(TAG, "--whitelist.db-----onCreate----getDbInstance---- ");
		if(db==null)
		{
			mOpenHelper = new DatabaseHelper(context);
			db = mOpenHelper.getReadableDatabase();
		}
		return db;
	}
	@Override
	public boolean onCreate() {
		// TODO Auto-generated method stub
		TXLog.i(TAG, "--whitelist.db-----onCreate-- ");
		String db_auth = getContext().getPackageName() + ".provider";
		CONTENT_URI_INSTALL = Uri.parse("content://" + db_auth + "/"+ TABLE_NAME_INSTALL);
		CONTENT_URI_IP      = Uri.parse("content://" + db_auth + "/"+ TABLE_NAME_IP);
		CONTENT_URI_CONTACT = Uri.parse("content://" + db_auth + "/"+ TABLE_NAME_CONTACT);
		sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
		sUriMatcher.addURI(db_auth, TABLE_NAME_INSTALL, _INSTALL);
		sUriMatcher.addURI(db_auth, TABLE_NAME_IP, _IP);
		sUriMatcher.addURI(db_auth, TABLE_NAME_CONTACT, _CONTACT);
		getDbInstance(this.getContext());
		mContentResolver = getContext().getContentResolver(); 
		return true;
	}

	@Override
	public Cursor query(Uri uri, String[] projection, String selection,String[] selectionArgs, String sortOrder) {
		// TODO Auto-generated method stub
		Cursor cur = null;
		String tableName = getTableName(uri);
		TXLog.i(TAG, "--whitelist.db-----query tableName = " + tableName+ "   selection = " + selection);
		cur = db.query(tableName, projection, selection, selectionArgs, null,null, sortOrder);
		return cur;
	}

	@Override
	public String getType(Uri uri) {
		// TODO Auto-generated method stub
		throw new IllegalArgumentException("Uri IllegalArgument:" + uri);
	}

	@Override
	public Uri insert(Uri uri, ContentValues values) {
		// TODO Auto-generated method stub
		long id = -1;
		String tableName = getTableName(uri);
		TXLog.i(TAG, "--whitelist.db-----insert tableName = " + tableName);
		id = db.insert(tableName, "Content is empty", values);
		if (id == -1) {
			return null;
		}
		return Uri.parse("" + id);
	}

	@Override
	public int delete(Uri uri, String selection, String[] selectionArgs) {
		// TODO Auto-generated method stub
		int num = 0;
		String tableName = getTableName(uri);
		TXLog.i(TAG, "--whitelist.db-----delete tableName = " + tableName+ "selection = " + selection);
		num = db.delete(tableName, selection, selectionArgs);
		return num;
	}

	@Override
	public int update(Uri uri, ContentValues values, String selection,
			String[] selectionArgs) {
		// TODO Auto-generated method stub
		int num = 0;
		String tableName = getTableName(uri);
		TXLog.i(TAG, "--whitelist.db-----update tableName = " + tableName+ "selection = " + selection);
		num = db.update(tableName, values, selection, selectionArgs);
		return num;
	}
	
	public String getTableName(Uri uri) {
		switch (sUriMatcher.match(uri)) {
		case _INSTALL://
			return TABLE_NAME_INSTALL;
		case _IP:// 
			return TABLE_NAME_IP;
		case _CONTACT:// 
			return TABLE_NAME_CONTACT;
		default:
			return null;
		}
	}
	public static class DatabaseHelper extends SQLiteOpenHelper {

		public DatabaseHelper(Context context) {
			super(context, DB_NAME, null, DB_VESION);
		}

		private static final String SQL_CREATE_TABLE_INSTALL = "CREATE TABLE IF NOT EXISTS "
				+ TABLE_NAME_INSTALL
				+ " ("
				+ "id"
				+ " INTEGER PRIMARY KEY AUTOINCREMENT,"
				+ "package"
				+ " TEXT,"
				+ "isActive"+ " TEXT" + ");";

		private static final String SQL_CREATE_TABLE_IP = "CREATE TABLE IF NOT EXISTS "
				+ TABLE_NAME_IP
				+ " ("
				+ "id"
				+ " INTEGER PRIMARY KEY AUTOINCREMENT,"
				+ "host"
				+ " TEXT,"
				+ "isActive" + " TEXT"+ ");";

		private static final String SQL_CREATE_TABLE_CONTACT = "CREATE TABLE IF NOT EXISTS "
				+ TABLE_NAME_CONTACT
				+ " ("
				+ "id"
				+ " INTEGER PRIMARY KEY AUTOINCREMENT,"
				+ "phonenum"
				+ " INTEGER,"
				+ "isActive" + " TEXT"+ ");";

		
		@Override
		public void onCreate(SQLiteDatabase db) {
			String sql_install = SQL_CREATE_TABLE_INSTALL;
			db.execSQL(sql_install);

			String sql_ip = SQL_CREATE_TABLE_IP;
			db.execSQL(sql_ip);

			String sql_contact = SQL_CREATE_TABLE_CONTACT;
			db.execSQL(sql_contact);
		}

		@Override
		public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
			TXLog.i(TAG, "--whitelist.db------onUpgrade oldVersion = " + oldVersion+ "newVersion = " + newVersion);
			 onCreate(db); 
		}
	}	
}

1) 截屏接口


public static String takeScreenshot(final Context context,String path_name) {
    	mContext = context;
    	final String mImageFileName;
        synchronized (mScreenshotLock) {
            if (mScreenshotConnection != null) {
                return "";
            }
            Intent intent = new Intent();
            intent.setPackage("com.prize.txInterface");
            if(TextUtils.isEmpty(path_name)){
            	long mImageTime  = System.currentTimeMillis();
                String imageDate = new SimpleDateFormat("yyyyMMdd-HHmmss").format(new Date(mImageTime));
                String default_dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getAbsolutePath()+File.separator
    					+"Screenshots/";
                mImageFileName = default_dir+String.format("Screenshot_%s", imageDate);
                TXLog.d(TAG, "----takeScreenshot-------path_name==null-------mImageFileName=="+mImageFileName);
            }else {
            	mImageFileName =path_name;
            	 TXLog.d(TAG, "----takeScreenshot---path_name!!!!==null------------mImageFileName=="+mImageFileName);
			}
            intent.setClass(context, TakeScreenshotService.class);
            ServiceConnection conn = new ServiceConnection() {
                @Override
                public void onServiceConnected(ComponentName name, IBinder service) {
                    synchronized (mScreenshotLock) {
                        if (mScreenshotConnection != this) {
                            return;
                        }
                        TXLog.d(TAG, "----takeScreenshot--------onServiceConnected------ComponentName=="+name.toString());
                        Messenger messenger = new Messenger(service);
                        Message msg = Message.obtain(null, 1);
                        final ServiceConnection myConn = this;
                        Handler h = new Handler(TXApplication.getInstance().getHandler().getLooper()) {
                            @Override
                            public void handleMessage(Message msg) {
                                synchronized (mScreenshotLock) {
                                    if (mScreenshotConnection == myConn) {
                                    	TXLog.d(TAG,"---Handler---ServiceConnection--------------handleMessage----------------");
                                    	Intent intent = new Intent();
                                    	intent.setAction("screenshot.path");
                                    	intent.putExtra("path", mImageFileName);
                                    	context.sendBroadcast(intent);
                                    	context.unbindService(mScreenshotConnection);
                                        mScreenshotConnection = null;
                                        TXApplication.getInstance().getHandler().removeCallbacks(mScreenshotTimeout);
                                    }
                                }
                            }
                        };
                        msg.replyTo = new Messenger(h);
                        msg.arg1 = msg.arg2 = 0;
                        msg.obj  =mImageFileName;
                        try {
                        	TXLog.d(TAG,"------ServiceConnection---------------messenger.send-----------------");
                            messenger.send(msg);
                        } catch (RemoteException e) {
                        }
                    }
                }
                @Override
                public void onServiceDisconnected(ComponentName name) {
                	
                }
            };
            TXLog.d(TAG, "-----takeScreenshot----bindServiceAsUser-----------");
            if (context.bindService(intent, conn, Context.BIND_AUTO_CREATE)) {
            	TXLog.d(TAG, "----takeScreenshot---bindServiceAsUser-----start------");
                mScreenshotConnection = conn;
                TXApplication.getInstance().getHandler().postDelayed(mScreenshotTimeout, 10000);
            }else {
            	TXLog.d(TAG, "-----takeScreenshot----bindServiceAsUser---else--------");
			}
        }
        TXLog.d(TAG, "-----takeScreenshot--------return=="+path_name);
        return mImageFileName;
    }
	
final static Runnable mScreenshotTimeout = new Runnable() {
        @Override public void run() {
            synchronized (mScreenshotLock) {
                if (mScreenshotConnection != null) {
                	 TXLog.d(TAG, "----takeScreenshot--------mScreenshotTimeout------unbindService-------------");
                	 if(mContext != null){
                		 mContext.unbindService(mScreenshotConnection); 
                	 }
                    mScreenshotConnection = null;
                }
            }
        }
    };
	
/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.prize.txInterface.screenshot;

import com.prize.txInterface.util.TXLog;

import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;

public class TakeScreenshotService extends Service {
    private static final String TAG = "snail_TakeScreenshotService";

    private static GlobalScreenshot mScreenshot;
    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
        	TXLog.d(TAG, "---------------onBind--handleMessage-----");
            switch (msg.what) {
                case 1:
                    final Messenger callback = msg.replyTo;
                    if (mScreenshot == null) {
                        mScreenshot = new GlobalScreenshot(TakeScreenshotService.this);
                    }
                    mScreenshot.takeScreenshot(new Runnable() {
                        @Override public void run() {
                            Message reply = Message.obtain(null, 1);
                            try {
                                callback.send(reply);
                            } catch (RemoteException e) {
                            }
                        }
                    }, msg.arg1 > 0, msg.arg2 > 0,(String) msg.obj);
            }
        }
    };

    @Override
    public IBinder onBind(Intent intent) {
    	TXLog.d(TAG, "---------------onBind-------");
        return new Messenger(mHandler).getBinder();
    }
}


/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.prize.txInterface.screenshot;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.app.Notification;
import android.app.Notification.BigPictureStyle;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.PointF;
import android.media.MediaActionSound;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Environment;
import android.os.Process;
import android.os.IBinder;
import android.provider.MediaStore;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.SurfaceControl;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.animation.Interpolator;
import android.widget.ImageView;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import android.content.ComponentName;
import android.util.Log;
import com.mediatek.storage.StorageManagerEx;
import com.prize.txInterface.R;
import com.prize.txInterface.R.string;
import com.prize.txInterface.util.TXLog;

/**
 * POD used in the AsyncTask which saves an image in the background.
 */
class SaveImageInBackgroundData {
    Context context;
    Bitmap image;
    Uri imageUri;
    Runnable finisher;
    String mImagePath;
    int iconSize;
    int result;
    int previewWidth;
    int previewheight;

    void clearImage() {
        image = null;
        imageUri = null;
        iconSize = 0;
    }
    void clearContext() {
        context = null;
    }
}

/**
 * An AsyncTask that saves an image to the media store in the background.
 */
class SaveImageInBackgroundTask extends AsyncTask<SaveImageInBackgroundData, Void,
        SaveImageInBackgroundData> {
    private static final String TAG = "snail_SaveImageInBackgroundTask";

    private static final String SCREENSHOTS_DIR_NAME = "Screenshots";
    private static final String SCREENSHOT_FILE_NAME_TEMPLATE = "Screenshot_%s.png";
    private static final String SCREENSHOT_SHARE_SUBJECT_TEMPLATE = "Screenshot (%s)";

    private final int mNotificationId;
    private final NotificationManager mNotificationManager;
    private final Notification.Builder mNotificationBuilder, mPublicNotificationBuilder;
    private File mScreenshotDir;
    private final String mImageFileName;
    private final String mImageFilePath;
    private final long mImageTime;
    private final BigPictureStyle mNotificationStyle;
    private final int mImageWidth;
    private final int mImageHeight;

    // WORKAROUND: We want the same notification across screenshots that we update so that we don't
    // spam a user's notification drawer.  However, we only show the ticker for the saving state
    // and if the ticker text is the same as the previous notification, then it will not show. So
    // for now, we just add and remove a space from the ticker text to trigger the animation when
    // necessary.
    private static boolean mTickerAddSpace;

    SaveImageInBackgroundTask(Context context, SaveImageInBackgroundData data,NotificationManager nManager, int nId) {
        Resources r = context.getResources();

        // Prepare all the output metadata
        File file = new File(StorageManagerEx.getDefaultPath(),Environment.DIRECTORY_PICTURES);
        try{
            file.mkdirs();
            if(file.exists()){
                mScreenshotDir = new File(file.toString() , SCREENSHOTS_DIR_NAME);
            } else {
                mScreenshotDir = new File(Environment.getExternalStoragePublicDirectory(
                    Environment.DIRECTORY_PICTURES), SCREENSHOTS_DIR_NAME);
            }
        }catch (Exception e) {
            Log.d(TAG, "save-Exception:"+e.toString());
        }
        TXLog.d(TAG,"SaveImageInBackgroundTask mScreenshotDir "+mScreenshotDir);
        
        mImageTime = System.currentTimeMillis();
        mImageFilePath = data.mImagePath;
        String picdir = new File(mImageFilePath).getParent();
        File rootdirFile = new File(picdir);
        if(!rootdirFile.exists()){
        	rootdirFile.mkdirs();
        }
        mImageFileName =  mImageFilePath.substring(mImageFilePath.lastIndexOf("/") + 1,mImageFilePath.lastIndexOf("."));
        TXLog.d(TAG,"----------SaveImageInBackgroundTask---mImageFilePath="+mImageFilePath+"  picdir=="+picdir+"  mImageFileName=="+mImageFileName);
        // Create the large notification icon
        mImageWidth = data.image.getWidth();
        mImageHeight = data.image.getHeight();
        int iconSize = data.iconSize;
        int previewWidth = data.previewWidth;
        int previewHeight = data.previewheight;

        Canvas c = new Canvas();
        Paint paint = new Paint();
        ColorMatrix desat = new ColorMatrix();
        /*Prize scale the screenshot picture with no scrim color liyao 20150708 start*/
       // desat.setSaturation(0.25f);
        paint.setColorFilter(new ColorMatrixColorFilter(desat));
        Matrix matrix = new Matrix();
        int overlayColor = 0x40FFFFFF;

        Bitmap picture = Bitmap.createBitmap(previewWidth, previewHeight, data.image.getConfig());
        matrix.setTranslate((previewWidth - mImageWidth) / 2, (previewHeight - mImageHeight) / 2);
        c.setBitmap(picture);
        c.drawBitmap(data.image, matrix, paint);
        //c.drawColor(0x40FFFFFF);
        /*Prize scale the screenshot picture with no scrim color liyao 20150708 end*/
        c.setBitmap(null);

        // Note, we can't use the preview for the small icon, since it is non-square
        float scale = (float) iconSize / Math.min(mImageWidth, mImageHeight);
        Bitmap icon = Bitmap.createBitmap(iconSize, iconSize, data.image.getConfig());
        matrix.setScale(scale, scale);
        matrix.postTranslate((iconSize - (scale * mImageWidth)) / 2,
                (iconSize - (scale * mImageHeight)) / 2);
        c.setBitmap(icon);
        c.drawBitmap(data.image, matrix, paint);
        c.drawColor(overlayColor);
        c.setBitmap(null);

        // Show the intermediate notification
        mTickerAddSpace = !mTickerAddSpace;
        mNotificationId = nId;
        mNotificationManager = nManager;
        final long now = System.currentTimeMillis();

        mNotificationBuilder = new Notification.Builder(context)
            .setTicker(r.getString(R.string.screenshot_saving_ticker)
                    + (mTickerAddSpace ? " " : ""))
            .setContentTitle(r.getString(R.string.screenshot_saving_title))
            .setContentText(r.getString(R.string.screenshot_saving_text))
            /*PRIZE-screenshot notification icon- liufan-2016-07-14-start*/
            .setSmallIcon(R.drawable.stat_notify_image_prize)
            /*PRIZE-screenshot notification icon- liufan-2016-07-14-end*/
            .setWhen(now)
            .setColor(r.getColor(com.android.internal.R.color.system_notification_accent_color));

        mNotificationStyle = new Notification.BigPictureStyle()
            .bigPicture(picture.createAshmemBitmap());
        mNotificationBuilder.setStyle(mNotificationStyle);

        // For "public" situations we want to show all the same info but
        // omit the actual screenshot image.
        mPublicNotificationBuilder = new Notification.Builder(context)
                .setContentTitle(r.getString(R.string.screenshot_saving_title))
                .setContentText(r.getString(R.string.screenshot_saving_text))
                /*PRIZE-screenshot notification icon- liufan-2016-07-14-start*/
                .setSmallIcon(R.drawable.stat_notify_image_prize)
                /*PRIZE-screenshot notification icon- liufan-2016-07-14-end*/
                .setCategory(Notification.CATEGORY_PROGRESS)
                .setWhen(now)
                .setColor(r.getColor(
                        com.android.internal.R.color.system_notification_accent_color));

        /*PRIZE-don't change screenshot notification icon- liufan-2016-07-14-start*/
        Notification pn = mPublicNotificationBuilder.build();
        pn.flags |= Notification.FLAG_KEEP_NOTIFICATION_ICON;
        mNotificationBuilder.setPublicVersion(pn);
        /*PRIZE-don't change screenshot notification icon- liufan-2016-07-14-end*/

        Notification n = mNotificationBuilder.build();
        n.flags |= Notification.FLAG_NO_CLEAR;
        /*PRIZE-don't change screenshot notification icon- liufan-2016-07-14-start*/
        n.flags |= Notification.FLAG_KEEP_NOTIFICATION_ICON;
        /*PRIZE-don't change screenshot notification icon- liufan-2016-07-14-end*/
        mNotificationManager.notify(nId, n);

        // On the tablet, the large icon makes the notification appear as if it is clickable (and
        // on small devices, the large icon is not shown) so defer showing the large icon until
        // we compose the final post-save notification below.
        mNotificationBuilder.setLargeIcon(icon.createAshmemBitmap());
        // But we still don't set it for the expanded view, allowing the smallIcon to show here.
        mNotificationStyle.bigLargeIcon((Bitmap) null);
    }

    @Override
    protected SaveImageInBackgroundData doInBackground(SaveImageInBackgroundData... params) {
        if (params.length != 1) return null;
        if (isCancelled()) {
            params[0].clearImage();
            params[0].clearContext();
            return null;
        }

        // By default, AsyncTask sets the worker thread to have background thread priority, so bump
        // it back up so that we save a little quicker.
        Process.setThreadPriority(Process.THREAD_PRIORITY_FOREGROUND);

        Context context = params[0].context;
        Bitmap image = params[0].image;
        Resources r = context.getResources();

        try {
            // Create screenshot directory if it doesn't exist
            mScreenshotDir.mkdirs();

            // media provider uses seconds for DATE_MODIFIED and DATE_ADDED, but milliseconds
            // for DATE_TAKEN
            long dateSeconds = mImageTime / 1000;

            // Save
            OutputStream out = new FileOutputStream(mImageFilePath);
            image.compress(Bitmap.CompressFormat.PNG, 100, out);
            out.flush();
            out.close();

            // Save the screenshot to the MediaStore
            ContentValues values = new ContentValues();
            ContentResolver resolver = context.getContentResolver();
            values.put(MediaStore.Images.ImageColumns.DATA, mImageFilePath);
            values.put(MediaStore.Images.ImageColumns.TITLE, mImageFileName);
            values.put(MediaStore.Images.ImageColumns.DISPLAY_NAME, mImageFileName);
            values.put(MediaStore.Images.ImageColumns.DATE_ADDED, dateSeconds);
            values.put(MediaStore.Images.ImageColumns.DATE_MODIFIED, dateSeconds);
            values.put(MediaStore.Images.ImageColumns.MIME_TYPE, "image/png");
            values.put(MediaStore.Images.ImageColumns.WIDTH, mImageWidth);
            values.put(MediaStore.Images.ImageColumns.HEIGHT, mImageHeight);
            values.put(MediaStore.Images.ImageColumns.SIZE, new File(mImageFilePath).length());
            Uri uri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);

            // Create a share intent
            String subjectDate = DateFormat.getDateTimeInstance().format(new Date(mImageTime));
            String subject = String.format(SCREENSHOT_SHARE_SUBJECT_TEMPLATE, subjectDate);
            Intent sharingIntent = new Intent(Intent.ACTION_SEND);
            sharingIntent.setType("image/png");
            sharingIntent.putExtra(Intent.EXTRA_STREAM, uri);
            sharingIntent.putExtra(Intent.EXTRA_SUBJECT, subject);

            // Create a share action for the notification
            final PendingIntent callback = PendingIntent.getBroadcast(context, 0,
                    new Intent(context, GlobalScreenshot.TargetChosenReceiver.class)
                            .putExtra(GlobalScreenshot.CANCEL_ID, mNotificationId),
                    PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT);
            Intent chooserIntent = Intent.createChooser(sharingIntent, null,
                    callback.getIntentSender());
            chooserIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK
                    | Intent.FLAG_ACTIVITY_NEW_TASK);
            mNotificationBuilder.addAction(R.drawable.ic_screenshot_share_prize,
                    r.getString(com.android.internal.R.string.share),
                    PendingIntent.getActivity(context, 0, chooserIntent,
                            PendingIntent.FLAG_CANCEL_CURRENT));

            // Create a delete action for the notification
            final PendingIntent deleteAction = PendingIntent.getBroadcast(context,  0,
                    new Intent(context, GlobalScreenshot.DeleteScreenshotReceiver.class)
                            .putExtra(GlobalScreenshot.CANCEL_ID, mNotificationId)
                            .putExtra(GlobalScreenshot.SCREENSHOT_URI_ID, uri.toString()),
                    PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT);
            mNotificationBuilder.addAction(R.drawable.ic_screenshot_delete_prize,
                    r.getString(com.android.internal.R.string.delete), deleteAction);

            params[0].imageUri = uri;
            params[0].image = null;
            params[0].result = 0;
        } catch (Exception e) {
            // IOException/UnsupportedOperationException may be thrown if external storage is not
            // mounted
            params[0].clearImage();
            params[0].result = 1;
        }

        // Recycle the bitmap data
        if (image != null) {
            image.recycle();
        }

        return params[0];
    }

    @Override
    protected void onPostExecute(SaveImageInBackgroundData params) {
        if (isCancelled()) {
            params.finisher.run();
            params.clearImage();
            params.clearContext();
            return;
        }

        if (params.result > 0) {
            // Show a message that we've failed to save the image to disk
            GlobalScreenshot.notifyScreenshotError(params.context, mNotificationManager);
        } else {
            // Show the final notification to indicate screenshot saved
            Resources r = params.context.getResources();

            // Create the intent to show the screenshot in gallery
            /*PRIZE-update the open picture method- liufan-2015-05-23-start*/
            Intent launchIntent = new Intent(Intent.ACTION_VIEW);
            launchIntent.setDataAndType(params.imageUri, "image/png");
                //launchIntent = new Intent(Intent.ACTION_VIEW)
                //    .setType("image/png")
                //    .putExtra(Intent.EXTRA_STREAM, params.imageUri)
                //    .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                try{
                    ComponentName cn = new ComponentName("com.android.gallery3d","com.android.gallery3d.app.GalleryActivity");
                    launchIntent.setComponent(cn);
                }catch (Exception e){
                    
                }
            /*PRIZE-update the open picture method- liufan-2015-05-23-end*/
            launchIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

            final long now = System.currentTimeMillis();

            mNotificationBuilder
                .setContentTitle(r.getString(R.string.screenshot_saved_title))
                .setContentText(r.getString(R.string.screenshot_saved_text))
                .setContentIntent(PendingIntent.getActivity(params.context, 0, launchIntent, 0))
                .setWhen(now)
                .setAutoCancel(true)
                .setColor(r.getColor(
                        com.android.internal.R.color.system_notification_accent_color));;

            // Update the text in the public version as well
            mPublicNotificationBuilder
                .setContentTitle(r.getString(R.string.screenshot_saved_title))
                .setContentText(r.getString(R.string.screenshot_saved_text))
                .setContentIntent(PendingIntent.getActivity(params.context, 0, launchIntent, 0))
                .setWhen(now)
                .setAutoCancel(true)
                .setColor(r.getColor(
                        com.android.internal.R.color.system_notification_accent_color));

            /*PRIZE-don't change screenshot notification icon- liufan-2016-07-14-start*/
            Notification pn = mPublicNotificationBuilder.build();
            pn.flags |= Notification.FLAG_KEEP_NOTIFICATION_ICON;
            mNotificationBuilder.setPublicVersion(pn);
            /*PRIZE-don't change screenshot notification icon- liufan-2016-07-14-end*/

            Notification n = mNotificationBuilder.build();
            n.flags &= ~Notification.FLAG_NO_CLEAR;
            /*PRIZE-don't change screenshot notification icon- liufan-2016-07-14-start*/
            n.flags |= Notification.FLAG_KEEP_NOTIFICATION_ICON;
            /*PRIZE-don't change screenshot notification icon- liufan-2016-07-14-end*/
            mNotificationManager.notify(mNotificationId, n);
            TXLog.d(TAG,"------onPostExecute--------------------------------");
        }
        params.finisher.run();
        params.clearContext();
    }
}

/**
 * An AsyncTask that deletes an image from the media store in the background.
 */
class DeleteImageInBackgroundTask extends AsyncTask<Uri, Void, Void> {
    private static final String TAG = "DeleteImageInBackgroundTask";

    private Context mContext;

    DeleteImageInBackgroundTask(Context context) {
        mContext = context;
    }

    @Override
    protected Void doInBackground(Uri... params) {
        if (params.length != 1) return null;

        Uri screenshotUri = params[0];
        ContentResolver resolver = mContext.getContentResolver();
        resolver.delete(screenshotUri, null, null);
        return null;
    }
}

/**
 * TODO:
 *   - Performance when over gl surfaces? Ie. Gallery
 *   - what do we say in the Toast? Which icon do we get if the user uses another
 *     type of gallery?
 */
class GlobalScreenshot {
    private static final String TAG = "GlobalScreenshot";

    static final String CANCEL_ID = "android:cancel_id";
    static final String SCREENSHOT_URI_ID = "android:screenshot_uri_id";

    private static final int SCREENSHOT_FLASH_TO_PEAK_DURATION = 130;
    private static final int SCREENSHOT_DROP_IN_DURATION = 430;
    private static final int SCREENSHOT_DROP_OUT_DELAY = 500;
    private static final int SCREENSHOT_DROP_OUT_DURATION = 430;
    private static final int SCREENSHOT_DROP_OUT_SCALE_DURATION = 370;
    private static final int SCREENSHOT_FAST_DROP_OUT_DURATION = 320;
    private static final float BACKGROUND_ALPHA = 0.5f;
    private static final float SCREENSHOT_SCALE = 1f;
    private static final float SCREENSHOT_DROP_IN_MIN_SCALE = SCREENSHOT_SCALE * 0.725f;
    private static final float SCREENSHOT_DROP_OUT_MIN_SCALE = SCREENSHOT_SCALE * 0.45f;
    private static final float SCREENSHOT_FAST_DROP_OUT_MIN_SCALE = SCREENSHOT_SCALE * 0.6f;
    private static final float SCREENSHOT_DROP_OUT_MIN_SCALE_OFFSET = 0f;
    private final int mPreviewWidth;
    private final int mPreviewHeight;

    private Context mContext;
    private WindowManager mWindowManager;
    private WindowManager.LayoutParams mWindowLayoutParams;
    private NotificationManager mNotificationManager;
    private Display mDisplay;
    private DisplayMetrics mDisplayMetrics;
    private Matrix mDisplayMatrix;

    private Bitmap mScreenBitmap;
    private View mScreenshotLayout;
    private ImageView mBackgroundView;
    private ImageView mScreenshotView;
    private ImageView mScreenshotFlash;

    private AnimatorSet mScreenshotAnimation;

    private int mNotificationIconSize;
    private float mBgPadding;
    private float mBgPaddingScale;

    private AsyncTask<SaveImageInBackgroundData, Void, SaveImageInBackgroundData> mSaveInBgTask;

    private MediaActionSound mCameraSound;


    /**
     * @param context everything needs a context :(
     */
    public GlobalScreenshot(Context context) {
    	 TXLog.d(TAG, "----GlobalScreenshot------start------");
        Resources r = context.getResources();
        mContext = context;
        LayoutInflater layoutInflater = (LayoutInflater)
                context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        // Inflate the screenshot layout
        mDisplayMatrix = new Matrix();
        mScreenshotLayout = layoutInflater.inflate(R.layout.global_screenshot, null);
        mBackgroundView = (ImageView) mScreenshotLayout.findViewById(R.id.global_screenshot_background);
        mScreenshotView = (ImageView) mScreenshotLayout.findViewById(R.id.global_screenshot);
        mScreenshotFlash = (ImageView) mScreenshotLayout.findViewById(R.id.global_screenshot_flash);
        mScreenshotLayout.setFocusable(true);
        mScreenshotLayout.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                // Intercept and ignore all touch events
                return true;
            }
        });

        // Setup the window that we are going to use
        mWindowLayoutParams = new WindowManager.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, 0, 0,
                WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY,
                WindowManager.LayoutParams.FLAG_FULLSCREEN
                    | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED
                    | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
                    | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED,
                PixelFormat.TRANSLUCENT);
        mWindowLayoutParams.setTitle("ScreenshotAnimation");
        mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        mNotificationManager =
            (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
        mDisplay = mWindowManager.getDefaultDisplay();
        mDisplayMetrics = new DisplayMetrics();
        mDisplay.getRealMetrics(mDisplayMetrics);

        // Get the various target sizes
        mNotificationIconSize =
            r.getDimensionPixelSize(android.R.dimen.notification_large_icon_height);

        // Scale has to account for both sides of the bg
        mBgPadding = (float) r.getDimensionPixelSize(R.dimen.global_screenshot_bg_padding);
        mBgPaddingScale = mBgPadding /  mDisplayMetrics.widthPixels;

        // determine the optimal preview size
        int panelWidth = 0;
        try {
            panelWidth = r.getDimensionPixelSize(R.dimen.notification_panel_width);
        } catch (Resources.NotFoundException e) {
        }
        if (panelWidth <= 0) {
            // includes notification_panel_width==match_parent (-1)
            panelWidth = mDisplayMetrics.widthPixels;
        }
        mPreviewWidth = panelWidth;
        mPreviewHeight = r.getDimensionPixelSize(R.dimen.notification_max_height);

        // Setup the Camera shutter sound
        mCameraSound = new MediaActionSound();
        mCameraSound.load(MediaActionSound.SHUTTER_CLICK);
    }

    /**
     * Creates a new worker thread and saves the screenshot to the media store.
     */
    private void saveScreenshotInWorkerThread(Runnable finisher,String path_name) {
    	TXLog.d(TAG, "----saveScreenshotInWorkerThread------start------");
        SaveImageInBackgroundData data = new SaveImageInBackgroundData();
        data.context = mContext;
        data.image = mScreenBitmap;
        data.iconSize = mNotificationIconSize;
        data.finisher = finisher;
        data.previewWidth = mPreviewWidth;
        data.previewheight = mPreviewHeight;
        data.mImagePath = path_name+".png";
        if (mSaveInBgTask != null) {
            mSaveInBgTask.cancel(false);
        }
        mSaveInBgTask = new SaveImageInBackgroundTask(mContext, data, mNotificationManager,
                R.id.notification_screenshot).execute(data);
    }

    /**
     * @return the current display rotation in degrees
     */
    private float getDegreesForRotation(int value) {
        switch (value) {
        case Surface.ROTATION_90:
            return 360f - 90f;
        case Surface.ROTATION_180:
            return 360f - 180f;
        case Surface.ROTATION_270:
            return 360f - 270f;
        }
        return 0f;
    }

    /**
     * Takes a screenshot of the current display and shows an animation.
     */
    void takeScreenshot(Runnable finisher, boolean statusBarVisible, boolean navBarVisible,String path_name) {
    	TXLog.d(TAG, "----takeScreenshot------start------");
        // We need to orient the screenshot correctly (and the Surface api seems to take screenshots
        // only in the natural orientation of the device :!)
        mDisplay.getRealMetrics(mDisplayMetrics);
        float[] dims = {mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels};
        float degrees = getDegreesForRotation(mDisplay.getRotation());
        boolean requiresRotation = (degrees > 0);
        if (requiresRotation) {
            // Get the dimensions of the device in its native orientation
            mDisplayMatrix.reset();
            mDisplayMatrix.preRotate(-degrees);
            mDisplayMatrix.mapPoints(dims);
            dims[0] = Math.abs(dims[0]);
            dims[1] = Math.abs(dims[1]);
        }

        // Take the screenshot
        mScreenBitmap = SurfaceControl.screenshot((int) dims[0], (int) dims[1]);
        if (mScreenBitmap == null) {
            notifyScreenshotError(mContext, mNotificationManager);
            finisher.run();
            return;
        }

        if (requiresRotation) {
            // Rotate the screenshot to the current orientation
            Bitmap ss = Bitmap.createBitmap(mDisplayMetrics.widthPixels,
                    mDisplayMetrics.heightPixels, Bitmap.Config.ARGB_8888);
            Canvas c = new Canvas(ss);
            c.translate(ss.getWidth() / 2, ss.getHeight() / 2);
            c.rotate(degrees);
            c.translate(-dims[0] / 2, -dims[1] / 2);
            c.drawBitmap(mScreenBitmap, 0, 0, null);
            c.setBitmap(null);
            // Recycle the previous bitmap
            mScreenBitmap.recycle();
            mScreenBitmap = ss;
        }

        // Optimizations
        /* prize-xuchunming-20170710-add circle window at screen four corners-start */
        //mScreenBitmap.setHasAlpha(false);
        /* prize-xuchunming-20170710-add circle window at screen four corners-end */
        mScreenBitmap.prepareToDraw();

        // Start the post-screenshot animation
        startAnimation(finisher, mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels,
                statusBarVisible, navBarVisible,path_name);
    }


    /**
     * Starts the animation after taking the screenshot
     */
    private void startAnimation(final Runnable finisher, int w, int h, boolean statusBarVisible,
            boolean navBarVisible,final String path_name) {
        // Add the view for the animation
    	TXLog.d(TAG, "----startAnimation------start------");
        mScreenshotView.setImageBitmap(mScreenBitmap);
        mScreenshotLayout.requestFocus();

        // Setup the animation with the screenshot just taken
        if (mScreenshotAnimation != null) {
            mScreenshotAnimation.end();
            mScreenshotAnimation.removeAllListeners();
        }

        mWindowManager.addView(mScreenshotLayout, mWindowLayoutParams);
        ValueAnimator screenshotDropInAnim = createScreenshotDropInAnimation();
        ValueAnimator screenshotFadeOutAnim = createScreenshotDropOutAnimation(w, h,
                statusBarVisible, navBarVisible);
        mScreenshotAnimation = new AnimatorSet();
        mScreenshotAnimation.playSequentially(screenshotDropInAnim, screenshotFadeOutAnim);
        mScreenshotAnimation.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                // Save the screenshot once we have a bit of time now
                saveScreenshotInWorkerThread(finisher,path_name);
                mWindowManager.removeView(mScreenshotLayout);

                // Clear any references to the bitmap
                mScreenBitmap = null;
                mScreenshotView.setImageBitmap(null);
            }
        });
        mScreenshotLayout.post(new Runnable() {
            @Override
            public void run() {
                // Play the shutter sound to notify that we've taken a screenshot
                mCameraSound.play(MediaActionSound.SHUTTER_CLICK);

                mScreenshotView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
                mScreenshotView.buildLayer();
                mScreenshotAnimation.start();
            }
        });
    }
    private ValueAnimator createScreenshotDropInAnimation() {
        final float flashPeakDurationPct = ((float) (SCREENSHOT_FLASH_TO_PEAK_DURATION)
                / SCREENSHOT_DROP_IN_DURATION);
        final float flashDurationPct = 2f * flashPeakDurationPct;
        final Interpolator flashAlphaInterpolator = new Interpolator() {
            @Override
            public float getInterpolation(float x) {
                // Flash the flash view in and out quickly
                if (x <= flashDurationPct) {
                    return (float) Math.sin(Math.PI * (x / flashDurationPct));
                }
                return 0;
            }
        };
        final Interpolator scaleInterpolator = new Interpolator() {
            @Override
            public float getInterpolation(float x) {
                // We start scaling when the flash is at it's peak
                if (x < flashPeakDurationPct) {
                    return 0;
                }
                return (x - flashDurationPct) / (1f - flashDurationPct);
            }
        };
        ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f);
        anim.setDuration(SCREENSHOT_DROP_IN_DURATION);
        anim.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationStart(Animator animation) {
                mBackgroundView.setAlpha(0f);
                mBackgroundView.setVisibility(View.VISIBLE);
                mScreenshotView.setAlpha(0f);
                mScreenshotView.setTranslationX(0f);
                mScreenshotView.setTranslationY(0f);
                mScreenshotView.setScaleX(SCREENSHOT_SCALE + mBgPaddingScale);
                mScreenshotView.setScaleY(SCREENSHOT_SCALE + mBgPaddingScale);
                mScreenshotView.setVisibility(View.VISIBLE);
                mScreenshotFlash.setAlpha(0f);
                mScreenshotFlash.setVisibility(View.VISIBLE);
            }
            @Override
            public void onAnimationEnd(android.animation.Animator animation) {
                mScreenshotFlash.setVisibility(View.GONE);
            }
        });
        anim.addUpdateListener(new AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float t = (Float) animation.getAnimatedValue();
                float scaleT = (SCREENSHOT_SCALE + mBgPaddingScale)
                    - scaleInterpolator.getInterpolation(t)
                        * (SCREENSHOT_SCALE - SCREENSHOT_DROP_IN_MIN_SCALE);
                mBackgroundView.setAlpha(scaleInterpolator.getInterpolation(t) * BACKGROUND_ALPHA);
                mScreenshotView.setAlpha(t);
                mScreenshotView.setScaleX(scaleT);
                mScreenshotView.setScaleY(scaleT);
                mScreenshotFlash.setAlpha(flashAlphaInterpolator.getInterpolation(t));
            }
        });
        return anim;
    }
    private ValueAnimator createScreenshotDropOutAnimation(int w, int h, boolean statusBarVisible,
            boolean navBarVisible) {
        ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f);
        anim.setStartDelay(SCREENSHOT_DROP_OUT_DELAY);
        anim.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                mBackgroundView.setVisibility(View.GONE);
                mScreenshotView.setVisibility(View.GONE);
                mScreenshotView.setLayerType(View.LAYER_TYPE_NONE, null);
            }
        });

        if (!statusBarVisible || !navBarVisible) {
            // There is no status bar/nav bar, so just fade the screenshot away in place
            anim.setDuration(SCREENSHOT_FAST_DROP_OUT_DURATION);
            anim.addUpdateListener(new AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    float t = (Float) animation.getAnimatedValue();
                    float scaleT = (SCREENSHOT_DROP_IN_MIN_SCALE + mBgPaddingScale)
                            - t * (SCREENSHOT_DROP_IN_MIN_SCALE - SCREENSHOT_FAST_DROP_OUT_MIN_SCALE);
                    mBackgroundView.setAlpha((1f - t) * BACKGROUND_ALPHA);
                    mScreenshotView.setAlpha(1f - t);
                    mScreenshotView.setScaleX(scaleT);
                    mScreenshotView.setScaleY(scaleT);
                }
            });
        } else {
            // In the case where there is a status bar, animate to the origin of the bar (top-left)
            final float scaleDurationPct = (float) SCREENSHOT_DROP_OUT_SCALE_DURATION
                    / SCREENSHOT_DROP_OUT_DURATION;
            final Interpolator scaleInterpolator = new Interpolator() {
                @Override
                public float getInterpolation(float x) {
                    if (x < scaleDurationPct) {
                        // Decelerate, and scale the input accordingly
                        return (float) (1f - Math.pow(1f - (x / scaleDurationPct), 2f));
                    }
                    return 1f;
                }
            };

            // Determine the bounds of how to scale
            float halfScreenWidth = (w - 2f * mBgPadding) / 2f;
            float halfScreenHeight = (h - 2f * mBgPadding) / 2f;
            final float offsetPct = SCREENSHOT_DROP_OUT_MIN_SCALE_OFFSET;
            final PointF finalPos = new PointF(
                -halfScreenWidth + (SCREENSHOT_DROP_OUT_MIN_SCALE + offsetPct) * halfScreenWidth,
                -halfScreenHeight + (SCREENSHOT_DROP_OUT_MIN_SCALE + offsetPct) * halfScreenHeight);

            // Animate the screenshot to the status bar
            anim.setDuration(SCREENSHOT_DROP_OUT_DURATION);
            anim.addUpdateListener(new AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    float t = (Float) animation.getAnimatedValue();
                    float scaleT = (SCREENSHOT_DROP_IN_MIN_SCALE + mBgPaddingScale)
                        - scaleInterpolator.getInterpolation(t)
                            * (SCREENSHOT_DROP_IN_MIN_SCALE - SCREENSHOT_DROP_OUT_MIN_SCALE);
                    mBackgroundView.setAlpha((1f - t) * BACKGROUND_ALPHA);
                    mScreenshotView.setAlpha(1f - scaleInterpolator.getInterpolation(t));
                    mScreenshotView.setScaleX(scaleT);
                    mScreenshotView.setScaleY(scaleT);
                    mScreenshotView.setTranslationX(t * finalPos.x);
                    mScreenshotView.setTranslationY(t * finalPos.y);
                }
            });
        }
        return anim;
    }

    static void notifyScreenshotError(Context context, NotificationManager nManager) {
        Resources r = context.getResources();

        // Clear all existing notification, compose the new notification and show it
        Notification.Builder b = new Notification.Builder(context)
            .setTicker(r.getString(R.string.screenshot_failed_title))
            .setContentTitle(r.getString(R.string.screenshot_failed_title))
            .setContentText(r.getString(R.string.screenshot_failed_text))
            /*PRIZE-screenshot notification icon- liufan-2016-07-14-start*/
            .setSmallIcon(R.drawable.stat_notify_image_error_prize)
            /*PRIZE-screenshot notification icon- liufan-2016-07-14-end*/
            .setWhen(System.currentTimeMillis())
            .setVisibility(Notification.VISIBILITY_PUBLIC) // ok to show outside lockscreen
            .setCategory(Notification.CATEGORY_ERROR)
            .setAutoCancel(true)
            .setColor(context.getColor(
                        com.android.internal.R.color.system_notification_accent_color));
        Notification n =
            new Notification.BigTextStyle(b)
                .bigText(r.getString(R.string.screenshot_failed_text))
                .build();
        /*PRIZE-don't change screenshot notification icon- liufan-2016-07-14-start*/
        n.flags |= Notification.FLAG_KEEP_NOTIFICATION_ICON;
        /*PRIZE-don't change screenshot notification icon- liufan-2016-07-14-end*/
        nManager.notify(R.id.notification_screenshot, n);
    }

    /**
     * Removes the notification for a screenshot after a share target is chosen.
     */
    public static class TargetChosenReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (!intent.hasExtra(CANCEL_ID)) {
                return;
            }

            // Clear the notification
            final NotificationManager nm =
                    (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
            final int id = intent.getIntExtra(CANCEL_ID, 0);
            nm.cancel(id);
        }
    }

    /**
     * Removes the last screenshot.
     */
    public static class DeleteScreenshotReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (!intent.hasExtra(CANCEL_ID) || !intent.hasExtra(SCREENSHOT_URI_ID)) {
                return;
            }

            // Clear the notification
            final NotificationManager nm =
                    (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
            final int id = intent.getIntExtra(CANCEL_ID, 0);
            final Uri uri = Uri.parse(intent.getStringExtra(SCREENSHOT_URI_ID));
            nm.cancel(id);

            // And delete the image from the media store
            new DeleteImageInBackgroundTask(context).execute(uri);
        }
    }
}


2) 静默安装接口


package com.prize.txInterface.thread;

import java.io.File;

import com.prize.txInterface.util.TXLog;
import android.content.pm.IPackageInstallObserver;
import android.content.pm.IPackageDeleteObserver;
import android.R.string;
import android.content.Context;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Handler;
import android.os.Message;

public class InstallThread extends Thread { 
    
	private int mInstallResult = 30;
    public static final int INSTALL_SUCCESS = 31;
    public static final int INSTALL_FAIL = 32;
    
    private int mUnInstallResult = 40;
    public static final int UNINSTALL_SUCCESS = 41;
    public static final int UNINSTALL_FAIL = 42;
    
    private String TAG = "snail_InstallThread";
    private Context mContext;
    private Handler mHandler;
    private String mPakckageName,mFilePath;
    private boolean mIsInstall;
    
    public InstallThread(Context context, Handler handler,Boolean isInstall,String filePath,String pakckageName) {
        mContext = context;
        mHandler = handler;
        mPakckageName = pakckageName;
        mFilePath = filePath;
        mIsInstall = isInstall;
        TXLog.d(TAG, "---InstallThread---filePath=="+filePath+"  pakcageName=="+pakckageName+"  mIsInstall=="+mIsInstall);
    }

    @Override
    public void run() {
        try {
        	if(mIsInstall){
        		installApkDefaul(mContext,mFilePath,mPakckageName);
        	}else {
        		uninstallApkDefaul(mContext,mPakckageName);
			}
        } catch (Exception e) {
            e.printStackTrace();
            	Message msg = mHandler.obtainMessage();
            	if(mIsInstall){
            		msg.what = INSTALL_FAIL;
            	}else {
            		msg.what = UNINSTALL_FAIL;
				}
                msg.obj = mPakckageName;
                mHandler.sendMessage(msg);
         }
    }
 // SilentInstall
 	private  void installApkDefaul(Context context, String filePath,String pakckageName) {
 		File file = new File(filePath);
 		int installFlags = 0;
 		TXLog.d(TAG, "---SilentInstall----installApkDefaul----filePath=="+filePath+"  pakcageName=="+pakckageName);
 		if (!file.exists())
 			return;
 		installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
 		//installFlags |= PackageManager.INSTALL_FROM_PRIZE;
 		PackageManager pm = context.getPackageManager();
 		IPackageInstallObserver observer = new MyPakcageInstallObserver();
 		TXLog.d(TAG, "---SilentInstall----installApkDefaul---installPackage----");
 		pm.installPackage(Uri.fromFile(file), observer, installFlags,pakckageName);
 	}
 	// SilentInstall  callBack 
 	private  class MyPakcageInstallObserver extends IPackageInstallObserver.Stub {
 		@Override
 		public void packageInstalled(String packageName, int returnCode) {
 			// TODO Auto-generated method stub
 			// 返回1代表安装成功
 			 try {
                 if(checkInstallResult(returnCode)) {
                     mInstallResult = INSTALL_SUCCESS;
                 } else {
                     mInstallResult = INSTALL_FAIL;
                 }
                 TXLog.d(TAG, "---SilentInstall----packageInstalled----returnCode=="+returnCode+"  pakcageName=="+packageName);
                 if (mHandler != null) {
                     Message msg = mHandler.obtainMessage();
                     msg.what = mInstallResult;
                     msg.obj = packageName;
                     mHandler.sendMessage(msg);
                 }
             } catch (Exception e) {
                 e.printStackTrace();
             }
 			
 		}
 	}
    // SilentUnInstall
 	private  void uninstallApkDefaul(Context context, String packageName) {
 		TXLog.d(TAG, "---uninstallApkDefaul----pakcageName=="+packageName);
   		PackageManager pm = context.getPackageManager();
   		IPackageDeleteObserver observer = new MyPackageDeleteObserver();
   		pm.deletePackage(packageName, observer, 0);
   	}
    // SilentUnInstall  callBack
  	private  class MyPackageDeleteObserver extends IPackageDeleteObserver.Stub {
  		@Override
  		public void packageDeleted(String packageName, int returnCode) {
  			// TODO Auto-generated method stub
  			// 返回1代表卸载成功
  			TXLog.d(TAG, "---SilentInstall----packageDeleted----returnCode=="+returnCode+"  pakcageName=="+packageName);
  			 try {
                  if(returnCode == 1) {
                 	 mUnInstallResult = UNINSTALL_SUCCESS;
                  } else {
                 	 mUnInstallResult = UNINSTALL_FAIL;
                  }
                  if (mHandler != null) {
                      Message msg = mHandler.obtainMessage();
                      msg.what = mUnInstallResult;
                      msg.obj = packageName;
                      mHandler.sendMessage(msg);
                  }
              } catch (Exception e) {
                  e.printStackTrace();
              }
  		}
  	}
}

3) 按键控制接口

-------frameworks/base/core/java/android/provider/Settings.java

+       /** @hide */
+        public static final String PRIZE_SHOWING_NAVBAR_BACKBTN = "prize_navbar_backbtn";
+        /** @hide */
+        public static final String PRIZE_SHOWING_NAVBAR_HOMEBTN = "prize_navbar_homebtn";
+         /** @hide */
+        public static final String PRIZE_SHOWING_NAVBAR_RECENTBTN = "prize_navbar_recentbtn";

---------frameworks/base/packages/SettingsProvider/res/values/defaults.xml

 <bool name="default_showing_backbtn">true</bool>
     <bool name="default_showing_homebtn">true</bool>
     <bool name="default_showing_recentbtn">true</bool>

 ------frameworks/base/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java

 	loadBooleanSetting(stmt, Settings.System.PRIZE_SHOWING_NAVBAR_BACKBTN, R.bool.default_showing_backbtn);
        loadBooleanSetting(stmt, Settings.System.PRIZE_SHOWING_NAVBAR_HOMEBTN, R.bool.default_showing_homebtn);
        loadBooleanSetting(stmt, Settings.System.PRIZE_SHOWING_NAVBAR_RECENTBTN, R.bool.default_showing_recentbtn);

--------- frameworks/base/packages/PrizeSystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java

    private boolean mShowNavBackbtn = true;
    private boolean mShowNavHomebtn = true;
    private boolean mShowNavRecentbtn = true;

         mContext.getContentResolver().registerContentObserver(
                 Settings.System.getUriFor(Settings.System.PRIZE_SHOWING_NAVBAR_BACKBTN),
                 true, mShowNavBackbtnObserver);
         mContext.getContentResolver().registerContentObserver(
                 Settings.System.getUriFor(Settings.System.PRIZE_SHOWING_NAVBAR_HOMEBTN),
                 true, mShowNavHomebtnObserver);
         mContext.getContentResolver().registerContentObserver(
                 Settings.System.getUriFor(Settings.System.PRIZE_SHOWING_NAVBAR_RECENTBTN),
                 true, mShowNavRecentbtnObserver);
				 
    private ContentObserver mShowNavBackbtnObserver = new ContentObserver(new Handler()) {
          @Override
          public void onChange(boolean selfChange) {
              printMyLog("mShowNavBackbtnObserver--onChange() --");
              int show = Settings.System.getInt(
                  mContext.getContentResolver(), 
                  Settings.System.PRIZE_SHOWING_NAVBAR_BACKBTN,
                  1);
              boolean isShow = (show == 1) ? true : false;
              if(isShow != mShowNavBackbtn && mNavigationBarView != null && mNavigationBarView.getBackButton() != null) {
                 mShowNavBackbtn = isShow;
                 if(mShowNavBackbtn){
                         mNavigationBarView.getBackButton().setVisibility(View.VISIBLE);
                 }else{
                         mNavigationBarView.getBackButton().setVisibility(View.GONE); 
                 }
              }
          }
 
      };
      private ContentObserver mShowNavHomebtnObserver = new ContentObserver(new Handler()) {
          @Override
          public void onChange(boolean selfChange) {
              printMyLog("mShowNavHomebtnObserver--onChange() --");
              int show = Settings.System.getInt(
                  mContext.getContentResolver(), 
                  Settings.System.PRIZE_SHOWING_NAVBAR_HOMEBTN,
                  1);
              boolean isShow = (show == 1) ? true : false;
              if(isShow != mShowNavHomebtn && mNavigationBarView != null &&mNavigationBarView.getHomeButton() != null) {
                 mShowNavHomebtn = isShow;
                 if(mShowNavHomebtn){
                         mNavigationBarView.getHomeButton().setVisibility(View.VISIBLE);
                 }else{
                         mNavigationBarView.getHomeButton().setVisibility(View.GONE); 
                 }
              }
          }
 
      };
      private ContentObserver mShowNavRecentbtnObserver = new ContentObserver(new Handler()) {
          @Override
          public void onChange(boolean selfChange) {
              printMyLog("mShowNavRecentbtnObserver--onChange() --");
              int show = Settings.System.getInt(
                  mContext.getContentResolver(), 
                  Settings.System.PRIZE_SHOWING_NAVBAR_RECENTBTN,
                  1);
              boolean isShow = (show == 1) ? true : false;
              if(isShow != mShowNavRecentbtn && mNavigationBarView != null &&mNavigationBarView.getRecentsButton() != null) {
                 mShowNavRecentbtn = isShow;
                 if(mShowNavRecentbtn){
                         mNavigationBarView.getRecentsButton().setVisibility(View.VISIBLE);
                 }else{
                         mNavigationBarView.getRecentsButton().setVisibility(View.GONE); 
                 }
              }
          }
	
    };
	
         mContext.getContentResolver().unregisterContentObserver(mShowNavBackbtnObserver);
         mContext.getContentResolver().unregisterContentObserver(mShowNavHomebtnObserver);
         mContext.getContentResolver().unregisterContentObserver(mShowNavRecentbtnObserver);
if(isshow){
	getStatusBarManager(mContext).disable(StatusBarManager.DISABLE_NONE);
}else {
	getStatusBarManager(mContext).disable(StatusBarManager.DISABLE_EXPAND);
}

4) 关机/重启控制接口

//广播形式实现慢
/*Intent shutdown = new Intent(Intent.ACTION_REQUEST_SHUTDOWN);  
	shutdown.putExtra(Intent.EXTRA_KEY_CONFIRM, false);  
 //其中false换成true,会弹出是否关机的确认窗口  
	shutdown.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);  
RemoteService.this.getApplicationContext().startActivity(shutdown);*/ 
			

public static void shutdown(Context context){
	PowerManager powermgr = (PowerManager) context.getApplicationContext().getSystemService(Context.POWER_SERVICE);
        try {
	Log.d("snail_","---shutdown------------------------");
	powermgr.shutdown(false,"txinterface",false);
	} catch (Exception e) {
		TXLog.i(TAG, "shutdown e  " + e.toString());
	}
}

//广播形式实现慢
/*Intent reboot = new Intent(Intent.ACTION_REBOOT);  
	reboot.putExtra("nowait", 1);  
	reboot.putExtra("interval", 1);  
	reboot.putExtra("window", 0);  
	RemoteService.this.getApplicationContext().sendBroadcast(reboot); */

public static void reboot(Context context){
       PowerManager powermgr = (PowerManager) context.getApplicationContext().getSystemService(Context.POWER_SERVICE);
	try {
		Log.d("snail_","---reboot------------------------");
		powermgr.reboot("txinterface");
	} catch (Exception e) {
		TXLog.i(TAG, "reboot e  " + e.toString());
	}
}

5) 关闭应用接口

@Override  //关闭应用
public void killApp(String pkg_name) throws RemoteException {
	// TODO Auto-generated method stub
	if(!TextUtils.isEmpty(pkg_name)){
		getActivityManager().forceStopPackage(pkg_name);
		Utils.removeRecentTask(RemoteService.this.getApplicationContext(), pkg_name);
	}
}
	
//移除最近任务栏记录	
public static void removeRecentTask(Context context,String pkg_name){
	ActivityManager activityManager = (ActivityManager) context.getApplicationContext().getSystemService(Context.ACTIVITY_SERVICE);
        List<RecentTaskInfo> appTask = activityManager.getRecentTasks(Integer.MAX_VALUE, 1);
        if (appTask != null){
            for (int i = 0; i < appTask.size(); i++) {
            	TXLog.d(TAG, "----------removeRecentTask-----pkg=="+appTask.get(i).baseIntent.toString()+"  pkg_name=="+pkg_name);
            	if (appTask.get(i).baseIntent.toString().contains(pkg_name)){
            		TXLog.d(TAG, "----------removeRecentTask-----stackId=="+appTask.get(i).persistentId);
            		if(appTask.get(i).persistentId != 0){
            			activityManager.removeTask(appTask.get(i).persistentId);
            			break;
            		}
                }
	    }
        }
}

6)控制应用使用

@Override
public void setAppsEnable(String apppkg, boolean appenable)throws RemoteException {
	// TODO Auto-generated method stub
	DisableChangeUtils disallowdischanger; 
	if(appenable){
		disallowdischanger = new DisableChangeUtils(RemoteService.this.getApplicationContext().getPackageManager(),Arrays.asList(apppkg.split(",")),
	                  PackageManager.COMPONENT_ENABLED_STATE_DEFAULT);
	}else{
		disallowdischanger = new DisableChangeUtils(RemoteService.this.getApplicationContext().getPackageManager(),Arrays.asList(apppkg.split(",")),
	                  PackageManager.COMPONENT_ENABLED_STATE_DISABLED);
	}
	disallowdischanger.execute((Object) null);
}
		
package com.prize.txInterface.util;

import java.util.List;

import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.AsyncTask;

public class DisableChangeUtils extends AsyncTask<Object, Object, Object>{

	private static String TAG = "snail_DisableChanger";
	  private PackageManager mPm;
	  private int mState;
	  private List<String> mPackages;
	  
	 public DisableChangeUtils(PackageManager Pm, List<String> packages, int state) {
         mPm = Pm;
         mPackages = packages;
         mState = state;
     }
	@Override
	protected Object doInBackground(Object... params) {
		// TODO Auto-generated method stub
		List<PackageInfo>  packageInfos = mPm.getInstalledPackages(PackageManager.GET_UNINSTALLED_PACKAGES);
		for (PackageInfo info : packageInfos) {
			ApplicationInfo appInfo = info.applicationInfo;
			for (int i = 0; i < mPackages.size(); i++) {
				if(appInfo.packageName.equals(mPackages.get(i))){
					if (Utils.isThirdApp(appInfo)) {
						//use DONT_KILL_APP  hideapp slow  10s   see PMS.java sendPackageChangedBroadcast   19489
						mPm.setApplicationEnabledSetting(appInfo.packageName, mState, 0);
						TXLog.d(TAG, "-----DisableChanger--doInBackground---isThirdApp-- name=="+appInfo.packageName+" mState=="+mState);
					}else {
						TXLog.d(TAG, "-----DisableChanger--doInBackground---!!!!!isThirdApp-- name=="+appInfo.packageName+" mState=="+mState);
						mPm.setApplicationEnabledSetting(appInfo.packageName, mState, 0);//PackageManager.DONT_KILL_APP
					}
				}
			}
		}
		return null;
	}
}

public static boolean isThirdApp(ApplicationInfo pInfo) {
	if ((pInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
		return true;
	} else if ((pInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
		return true;
	}
	return false;
}

8) 控制推送通知接口

public static void setNotificationEnable(Context mContext,boolean isenable){
		
	List<PackageInfo>  packageInfos = getPackageManager(mContext).getInstalledPackages(PackageManager.GET_UNINSTALLED_PACKAGES);
	for (PackageInfo info : packageInfos) {
		ApplicationInfo appInfo = info.applicationInfo;
		if (Utils.isThirdApp(appInfo)) {
			try {
				getNotificationManager(mContext).setNotificationsEnabledForPackage(appInfo.packageName, appInfo.uid, isenable);
			} catch (Exception e) {
			}
		}
	}
}

9) 控制SD/TF卡接口

@Override
public void setSDCardEnable(boolean sdenble) throws RemoteException {
	// TODO Auto-generated method stub
	if(sdenble){
		MountTaskUtil mount_task = new MountTaskUtil(RemoteService.this.getApplicationContext());
		mount_task.execute();
	}else {
		UnmountTaskUtils unmount_task = new UnmountTaskUtils(RemoteService.this.getApplicationContext());
		unmount_task.execute();
	}
}
		
package com.prize.txInterface.util;

import java.io.File;
import java.util.List;
import com.prize.txInterface.R;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Environment;
import android.os.storage.StorageManager;
import android.os.storage.VolumeInfo;
import android.os.SystemProperties;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast;

public class MountTaskUtil extends AsyncTask<Void, Void, Exception> {

	private String TAG = "snail_MountTaskUtil";
	private  Context mContext;
    private  StorageManager mStorageManager;
	
    public MountTaskUtil(Context context) {
        mContext = context.getApplicationContext();
        mStorageManager = mContext.getSystemService(StorageManager.class);
    }
    
	@Override
	protected Exception doInBackground(Void... params) {
		// TODO Auto-generated method stub
		try {
			final List<VolumeInfo> volumes = mStorageManager.getVolumes();
			for (VolumeInfo vol : volumes) {
				Log.d("snail", "--MountTaskUtil--------VolumeInfo--vol=="+vol.getId()+"  getType()=="+vol.getType()+"  getState()=="+vol.getState());
	             if (vol.getType() == VolumeInfo.TYPE_PUBLIC && vol.getState()==VolumeInfo.STATE_UNMOUNTED &&!TextUtils.isEmpty(vol.getId())) {
	    				mStorageManager.mount(vol.getId());
	            }
	        }
			
            return null;
        } catch (Exception e) {
        	return e;
        }
	}

	@Override
	protected void onPostExecute(Exception result) {
		// TODO Auto-generated method stub
		super.onPostExecute(result);
		if (result == null) {
                    TXLog.d(TAG, mContext.getString(R.string.storage_mount_success));
                } else {
        	     TXLog.d(TAG, mContext.getString(R.string.storage_mount_success)+"  error=="+result.getMessage());
                }
	}
}


package com.prize.txInterface.util;

import java.util.List;

import com.prize.txInterface.R;

import android.content.Context;
import android.os.AsyncTask;
import android.os.Environment;
import android.os.storage.StorageManager;
import android.os.storage.VolumeInfo;
import android.os.SystemProperties;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast;

public class UnmountTaskUtils  extends  AsyncTask<Void, Void, Exception> {

	private String TAG = "snail_MountTaskUtil";
	private  Context mContext;
    private  StorageManager mStorageManager;
    private final Object mLock = new Object();
    
    
    public UnmountTaskUtils(Context context) {
        mContext = context.getApplicationContext();
        mStorageManager = mContext.getSystemService(StorageManager.class);
    }
    
	@Override
	protected Exception doInBackground(Void... params) {
		// TODO Auto-generated method stub
		try {
			final List<VolumeInfo> volumes = mStorageManager.getVolumes();
			for (VolumeInfo vol : volumes) {
				Log.d("snail", "-------UnmountTaskUtils---VolumeInfo--vol=="+vol.getId()+"  getType()=="+vol.getType()+"  getState()=="+vol.getState());
	             if (vol.getType() == VolumeInfo.TYPE_PUBLIC && vol.getState()==VolumeInfo.STATE_MOUNTED &&!TextUtils.isEmpty(vol.getId())) {
	    				mStorageManager.unmount(vol.getId());
	            }
	        }
			
            return null;
        } catch (Exception e) {
        	
        	return e;
        }
	}

	@Override
	protected void onPostExecute(Exception result) {
		// TODO Auto-generated method stub
		super.onPostExecute(result);
		if (result == null) {
                    TXLog.d(TAG, mContext.getString(R.string.storage_unmount_success));
                } else {
        	     TXLog.d(TAG, mContext.getString(R.string.storage_unmount_failure)+"  error=="+result.getMessage());
                }
	}
}

10) 控制USB口接口

------ frameworks/base/services/usb/java/com/android/server/usb/UsbDeviceManager.java

@@ -1394,7 +1394,7 @@ public class UsbDeviceManager {
                     mUsbConfigured = mConfigured;
                     if (!mConnected) {
                         // When a disconnect occurs, relock access to sensitive user data
                         mUsbDataUnlocked = false;
  ------                      // mUsbDataUnlocked = false;
                     }
                     updateUsbNotification();
                     updateAdbNotification();
...	...
@@ -1403,7 +1403,7 @@ public class UsbDeviceManager {
                         updateCurrentAccessory();
                     } else if (!mConnected) {
                         // restore defaults when USB is disconnected
                         setEnabledFunctions(null, false);
    --------                     //setEnabledFunctions(null, false);
                     }
                     if (mBootCompleted) {
                         updateUsbStateBroadcastIfNeeded();


@Override
public void setUSBtransferEnable(boolean enable) throws RemoteException {
	// TODO Auto-generated method stub
	String usbMode = Utils.getUsbDataMode(RemoteService.this.getApplicationContext());
	if(!TextUtils.isEmpty(usbMode)){
		if(enable && !usbMode.equals("mtp")){
			Utils.setUsbDataMode(RemoteService.this.getApplicationContext(), UsbManager.USB_FUNCTION_MTP);
		}else if(!enable && !usbMode.equals("charge")){
			Utils.setUsbDataMode(RemoteService.this.getApplicationContext(), null);
		}
	}
}
		
public static void setUsbDataMode(Context context,String mode) {
	UsbManager mUsbManager = (UsbManager)context.getApplicationContext().getSystemService(Context.USB_SERVICE);
	TXLog.d(TAG, "--------setUsbDataMode-----------mode==="+mode);
	if(TextUtils.isEmpty(mode)){
		mUsbManager.setCurrentFunction(null);
		mUsbManager.setUsbDataUnlocked(false);
	}else {
		mUsbManager.setCurrentFunction(mode);
		mUsbManager.setUsbDataUnlocked(true);
	}
  }











猜你喜欢

转载自blog.csdn.net/mafei852213034/article/details/79938629