android为应用程序添加退出动画
原本想搞一个退出程序时,把前一个应用程序的VIEW或者截图抓过来为我用,以实现更复杂的动画效果,尝试了很多方法,但都有或多或少的缺陷,可惜最后失败了。不过也算有所得。写文以标记。
其实抓图在4.0以后的版本中,还是很容易实现的,因为系统有十分完美的自带的截图。只要有源码,可以修改系统,通过执行screencap 和screenshot命令可以实现。
public static boolean RootCommand(String command) //申请root权限 { Process process = null; DataOutputStream os = null; try { process = Runtime.getRuntime().exec("su"); os = new DataOutputStream(process.getOutputStream()); os.writeBytes(command + "\n"); os.writeBytes("exit\n"); os.flush(); process.waitFor(); } catch (Exception e) { Log.d("*** DEBUG ***", "ROOT REE" + e.getMessage()); return false; } finally { try { if (os != null) { os.close(); } process.destroy(); } catch (Exception e) { } } Log.d("*** DEBUG ***", "Root SUC "); return true; }
通过调用系统的截屏程序也能实现。如果要实现进入自己的软件前获得屏幕BUFFER,下面的函数可以实现,返回的BITMAP就是前一屏的BITMAP,不过如果抓图是竖屏,进入自己的程序后变横屏,这个图就没办法变横了。因为我是需要在锁屏时,把前一屏数据结果锁屏做一个动画,所以如果解锁时,前一窗口数据已经变化,这个载屏就没什么用处了。无法实现解锁窗口与前一程序无缝衔接。同时如果你的锁屏如果是在黑屏后才进入,那么这个裁屏截到的也是黑屏了,大家都懂的。
public Bitmap getScreenBuffer() { Display mDisplay; DisplayMetrics mDisplayMetrics; Matrix mDisplayMatrix = new Matrix(); WindowManager mWindowManager = (WindowManager) mContext .getSystemService(Context.WINDOW_SERVICE); mDisplay = mWindowManager.getDefaultDisplay(); mDisplayMetrics = new DisplayMetrics(); mDisplay.getRealMetrics(mDisplayMetrics); mDisplay.getRealMetrics(mDisplayMetrics); float[] dims = { mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels }; mlock = Surface.screenshot((int) dims[0], (int) dims[1]); return mlock; }
截屏函数在上锁时,由于会黑屏,结果只能抓到黑屏图,所以可以通过调用4.0以后最近运行的程序的快照来替代,大概是ActivityManager.java 中getTaskThumbnails(int)}.但由于我的需要支持横竖屏,所以当解锁前后横竖屏状态不同时,这个快照也失去了意义。
那么只剩下最后一种方式,获得上一次运行的activity的实例,进而获得其getDecorView,把其getDecorView转为BITMAP来运用。获得前一次运行的程序,可以通过以下代码获取:
ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE); List<RunningTaskInfo> cn = am.getRunningTasks(2); RunningTaskInfo taskInfo = cn.get(1); ComponentName name = taskInfo.topActivity; Log.i("jia @@@@@@", "name.getClassName() = "+name.getClassName()); Log.i("jia @@@@@@", "name.getPackageName() = "+name.getPackageName()); Log.i("jia @@@@@@", "name.getClass() = "+name.getClass().toString()); Log.i("jia @@@@@@", "name.getShortClassName() = "+name.getShortClassName());
getRunningTasks可以获得当前运行的程序,参数2为获得最近两个程序,
cn.get(1);为获得倒数第二个运行的程序,如果参数为0,就是当前程序
然后使用动态加载反射其activity
Context cc = null;
try {
cc = this.createPackageContext(name.getPackageName(), Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);
} catch (NameNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//载入这个类
Class clazz = null;
try {
clazz = cc.getClassLoader().loadClass(name.getClassName());
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Activity aa = null;
try {
aa = (Activity)clazz.newInstance();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Intent in = new Intent(cc, clazz);
in.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
this.startActivity(in);
overridePendingTransition(android.R.anim.slide_in_left,
android.R.anim.slide_out_right);
最后,完整的代码
package com.example.testtaskactivity; import java.util.List; import android.os.Bundle; import android.app.Activity; import android.app.ActivityGroup; import android.app.ActivityManager; import android.app.ActivityManager.RunningTaskInfo; import android.app.LocalActivityManager; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager.NameNotFoundException; import android.graphics.Rect; import android.util.Log; import android.view.Menu; import android.view.View; import android.view.Window; import android.widget.RelativeLayout.LayoutParams; public class MainActivity extends ActivityGroup { private LocalActivityManager localActivityManager = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } public void gettaskview(View view) { ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE); List<RunningTaskInfo> cn = am.getRunningTasks(2); RunningTaskInfo taskInfo = cn.get(1); ComponentName name = taskInfo.topActivity; Log.i("jia @@@@@@", "name.getClassName() = " + name.getClassName()); Log.i("jia @@@@@@", "name.getPackageName() = " + name.getPackageName()); Log.i("jia @@@@@@", "name.getClass() = " + name.getClass().toString()); Log.i("jia @@@@@@", "name.getShortClassName() = " + name.getShortClassName()); Activity a = null; Class c = null; /* * try { c = Class.forName(name.getClassName()); Log.i("jia @@@@@@", * "c = "+c.getName().toString()); } catch (ClassNotFoundException e) { * // TODO Auto-generated catch block e.printStackTrace(); * Log.i("jia @@@@@@", "11111111111111111 "); } try { a = * (Activity)c.newInstance(); Log.i("jia @@@@@@", "a = "+a.toString()); * } catch (InstantiationException e) { // TODO Auto-generated catch * block e.printStackTrace(); } catch (IllegalAccessException e) { // * TODO Auto-generated catch block e.printStackTrace(); } */ /* * View currentScreen = a.getWindow().getDecorView(); * * this.addContentView(currentScreen, new LayoutParams( * LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); */ // this.createPackageContext(packageName, flags); Context cc = null; try { cc = this.createPackageContext(name.getPackageName(), Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY); } catch (NameNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } // 载入这个类 Class clazz = null; try { clazz = cc.getClassLoader().loadClass(name.getClassName()); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } Activity aa = null; try { aa = (Activity) clazz.newInstance(); } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } // PolicyManager.makeNewWindow(context); // View v = aa.getWindow().getDecorView(); // setContentView(v); Intent in = new Intent(cc, clazz); in.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); this.startActivity(in); overridePendingTransition(android.R.anim.slide_in_left, android.R.anim.slide_out_right); /* * Rect frame = new Rect(); * getWindow().getDecorView().getWindowVisibleDisplayFrame(frame); int * statusBarHeight = frame.top; Log.i("jia @@@@@@", * "statusBarHeight = " + statusBarHeight); * * * LocalActivityManager mgr = this.getLocalActivityManager(); * Intent in * = new Intent(this, clazz); in.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK * | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); Window w = * mgr.startActivity("aaa", in); View v =w.getDecorView(); //View v = * a.getWindow().getDecorView(); setContentView(v); */ } }
这样可以使唤得我们可以在不同的应用之间使用动画跳转,但我尝试使用Window w = mgr.startActivity("aaa", in)获得前一activity的VIEW时,提示该activity没有在我的
AndroidManifest.xml中声明,第三方的和系统的应用,本不该在我的应用中声明,可能是因为别人的VIEW不能为我所用吧。抓图程序需要system权限,需要在AndroidManifest.xml文件的manifest标签中声明,android:sharedUserId="android.uid.system"。要不抓不了图,也获取不了屏幕的bitmap,Surface.screenshot函数是系统的隐藏API,不可在APK中直接使用,需要写一个如下的MK文件,放在源码目录下使用MM编绎:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_JAVA_LIBRARIES := bouncycastle \
framework \
mediatek-framework
LOCAL_CERTIFICATE := platform
LOCAL_STATIC_JAVA_LIBRARIES := \
android-support-v4
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_PACKAGE_NAME := Scr
#LOCAL_SDK_VERSION := current
include $(BUILD_PACKAGE)
# Use the following include to make our test apk.
include $(call all-makefiles-under,$(LOCAL_PATH))
本文不可转载,需注明出处:
http://blog.csdn.net/cnbloger/article/details/10029633