2014年7月17日星期四

DexClassLoader加载未安装的apk

参考:  http://wangleyiang.iteye.com/blog/1791947

用DexClassLoader加载jar没什么难度,不过用无参数的构造行数反射调用apk中的Activity就有问题,被调用的Activity中
super.onCreate(savedInstanceState);
会报错,这个Activity没有被正常的初始化,Activity的父父类ContextWrapper的构造函数需要Context。只能修改要被调用的Activity了,注释掉上面出错的那行,然后提供一个有参构造函数,传一个Context过去,以后被调用的Activity里面只能使用这个Context了.
       String dexPath = Environment.getExternalStorageDirectory()
  + "/Test/AAA.apk";
 PackageInfo packageInfo = getPackageManager().getPackageArchiveInfo(
  dexPath, PackageManager.GET_ACTIVITIES);
 String activityName = packageInfo.activities[0].name;
 File dirFile = getDir("whocares", 0);
 DexClassLoader loader = new DexClassLoader(dexPath,
  dirFile.getAbsolutePath(), null,
  ClassLoader.getSystemClassLoader());
 try {
      Class clz = loader.loadClass(activityName);
      Constructor constructor = clz
   .getConstructor(new Class[] { Context.class });
      Activity activity = (Activity) constructor
   .newInstance(new Object[] { this });
      Method create = clz.getDeclaredMethod("onCreate",
   new Class[] { Bundle.class });
      create.setAccessible(true);
      create.invoke(activity, new Object[] { null });
 } catch (ClassNotFoundException e) {
  e.printStackTrace();
 } catch (NoSuchMethodException e) {
  e.printStackTrace();
 } catch (InstantiationException e) {
  e.printStackTrace();
 } catch (IllegalAccessException e) {
  e.printStackTrace();
 } catch (IllegalArgumentException e) {
  e.printStackTrace();
 } catch (InvocationTargetException e) {
  e.printStackTrace();
 }

2014年7月16日星期三

get the URI of an image resource in android

Reference:http://androidbook.blogspot.jp/2009/08/referring-to-android-resources-using.html

Two methods:

  1. android.resource://[package]/[res id]
  2. android.resource://[package]/[res type]/[res name]

Example:

  1. Uri.parse("android.resource://com.example.test/“ + R.drawable.ic_launcher)
  2. Uri.parse("android.resource://com.example.test/drawable/ic_launcher")

2014年7月15日星期二

修改长按home后出现的app

长按home默认出现的是Google Search,可以改成选择任意的Activity:

   <intent-filter>
      <action android:name="android.intent.action.ASSIST" />
      <category android:name="android.intent.category.DEFAULT" />
   </intent-filter>

     <meta-data
        android:name="com.android.systemui.action_assist_icon"
        android:resource="@android:drawable/sym_def_app_icon" />

2014年6月27日星期五

Android sdk manger cannot download anything in China

因为goagent不能用了,所以只能用改hosts了。
1.先选中Force https://... sources to be fetched using http://...
2. hosts里面添加:
203.208.46.146 dl.google.com
203.208.46.146 dl-ssl.google.com

2014年6月15日星期日

proguard与gson,searchview (v7)

与proguard同时使用要注意:

使用gson时(参见https://code.google.com/p/google-gson/source/browse/trunk/examples/android-proguard-example/proguard.cfg):
##---------------Begin: proguard configuration for Gson  ----------
# Gson uses generic type information stored in a class file when working with fields. Proguard
# removes such information by default, so configure it to keep all of it.
-keepattributes Signature

# For using GSON @Expose annotation
-keepattributes *Annotation*

# Gson specific classes
-keep class sun.misc.Unsafe { *; }
#-keep class com.google.gson.stream.** { *; }

# Application classes that will be serialized/deserialized over Gson
-keep class com.google.gson.examples.android.model.** { *; }

##---------------End: proguard configuration for Gson  ----------

使用android support v7中的searchview时:
-keep class android.support.v7.widget.SearchView { *; }

2013年9月2日星期一

判断statusbar是否存在

private boolean checkStatusbar(){
   Rect rect=new Rect();
   getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);
   //屏幕高度还有别的办法得到,不赘述
   return (rect.bottom-rect.top)
           ==getResources().getDisplayMetrics().heightPixels;
}

另一种计算一般statusbar高度的方法(固定值,不是实时的高度):
(参考http://mrtn.me/blog/2012/03/17/get-the-height-of-the-status-bar-in-android/)
private int getStatusBarHeight() {
   int result = 0;
   int resourceId = getResources()
           .getIdentifier("status_bar_height", "dimen", "android");
   if (resourceId > 0) {
         result = getResources().getDimensionPixelSize(resourceId);
   }
 return result;
}