Android AIDL 实现两个APP之间的跨进程通信实例
1 Service端创建
首先需要创建一个Android工程然后创建AIDL文件,创建AIDL文件主要为了生成继承了Binder的Stub类,以便应用Binder进行进程间通信
servier端结构如下
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端
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);
}
}
}
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>
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);
}
}