Android-aidl传输parceble数据错误

写了一个service,使用AIDL跨进程调用时出现问题,service这边写的数据是正确的,client端拿到的是默认值,都是0.

找了下,

http://stackoverflow.com/questions/24615317/android-aidl-and-service-and-activity-parceable-seems-to-be-passing-default-clas

因为 in  out写反了。

in表示这个参数是入参,会被这个method读,但不会写。out意味着这个method会写但不读。inout表示会读也会写。

in/out/inout从字面意思上很好理解,要记住,它们是修饰参数,in/out都是相对于当前method的。

Android-获取内存,当前/总cpu信息

内存信息中最有用的就是PSS了,还有各种零碎的,在android.os.Debug中可以直接拿到MemeryInfo

 

cpu信息分两类,总的cpu使用率,取proc/stat的数据,这个样子

取到之后解析,拿到使用时间和空闲时间

隔一段时间后,再取一次数据,即可得到cpu使用时间

当前进程的cpu使用率计算方法和总的相似,只不过路径变成了proc/<pid>/stat

解析数据代码如下,如果不计算子进程时间则只用toks[13]和toks[14]

取到之后除以总的cpu时间,即

通过jni获得应用Icon(getApplicationIcon)

jni获得应用icon有两步

1.在java端写一个方法,通过包名获取appIcon,返回byte[]

native初始化时,获取这个method,同时拿到VM和全局context

jobject mBzAppContext;
JavaVM *m_appContext_VM = NULL;

mAppContext = env->NewGlobalRef(thiz);
env->GetJavaVM(&m_appContext_VM);

FIND_CLASS(clazz, "com/xx/xx/xx");
if (clazz == NULL) {
loge("class not exist!!");
}

GET_METHOD_ID(gAppGlobalCallMethod.getAppIcon, clazz,
"getAppIcon", "(Ljava/lang/String;)[B");
if (gAppGlobalCallMethod.getAppIcon == NULL) {
loge("method get fail!!");
}

(Ljava/lang/String;)[B 指入参是String,回参是jbyteArray

2.调用jni函数,拿到byte[],转成char*

void readAppIcon(const char* packageName)
{
if (m_appContext_VM == NULL) {
loge("m_appContext_VM null");
return;
}
if (mAppContext == NULL) {
loge("mAppContext null");
return;
}
if (gAppGlobalCallMethod.getAppIcon== NULL) {
loge("gAppGlobalCallMethod.getAppIcon null");
return;
}
CHECK_JVM_THREAD(m_appContext_VM);
if (error) {
loge("check jvm thread error");
return;
}
jstring jPackageName = env->NewStringUTF(packageName);
jbyteArray jbarray = (jbyteArray)env->CallObjectMethod(mBzAppContext, gAppGlobalCallMethod.getAppIcon, jPackageName);

if (jbarray == nullptr) {
logi("getAppIcon null");
} else {
len = (int)env->GetArrayLength (jbarray);
char *data = (char*)env->GetByteArrayElements(jbarray, 0);
// 这里就把appicon拿到并转成了char*,注意释放data

env->ReleaseByteArrayElements(jbarray, data, 0);
}
if (attached) {
m_appContext_VM->DetachCurrentThread();
}
}

 

AndroidStudio 更改jar包编译顺序优先于android.jar,使用@hide api

使用@hide 的api,可以通过反射,但反射速度慢,且使用不方便。

@hide的api,在编译的时候有问题,如果能编译成功,是可以调用的。那么问题来了,如何编译成功?

可以修改android源码,去掉@hide,编译生成该模块的framework.jar。Eclipse中直接引入该jar包在android.jar前即可。AndroidStudio就比较麻烦,需要做两步。

1.引入jar包,这个网上有无数方法,不表。注意设置compile->provide,gradle文件如下:

原因就是我们只需要编译成功,不需要把这个包打到系统。

这时候在系统自动生成的iml文件中,可以看到一排orderEntry标签 <orderEntry>,也就是我们引用的所有jar包信息,把framework的jar包放到orderEntry的第一位,也就是

前面,这时候IDE就不报错了。

不过只是表象,方便我们写代码自动补全而已。而且iml文件是自动生成的,每次重启IDE都要重新改一下。

2.真正的编译需要在工程的gradle中增加编译选项

找到

在repositores同级增加

Xbootclasspath/p:是Java编译的寻址优先设置,先找缺省路径还是全路径

不确定路径怎么填的,可以使用绝对路径,如

编译通过

Tips:

1.有时候@hide的api编译过了,其他地方又报错。查看一下报错的api,看看是不是对android版本有要求,framework.jar编译最好用较新的编译环境。

2.不要做过多的其他尝试,这两步绝对可以解决问题。

calling startactivity() from outside of an activity context requires the flag_activity_new_task flag. Is this really what you want?

今天遇到一个错误,莫名戳中笑点,好贴心好长的提示。

原因:使用application startActivity,必须使用FLAG_ACTIVITY_NEW_TASK,因为新起来的Activity没办法和application放到一个task中,必须用FLAG_ACTIVITY_NEW_TASK让新启动的ACTIVITY独占一个TASK。

statfs获得硬盘信息

statfs结构如下:

struct statfs
{
long    f_type;     /* 文件系统类型  */
long    f_bsize;    /* 经过优化的传输块大小  */
long    f_blocks;   /* 文件系统数据块总数 */
long    f_bfree;    /* 可用块数 */
long    f_bavail;   /* 非超级用户可获取的块数 */
long    f_files;    /* 文件结点总数 */
long    f_ffree;    /* 可用文件结点数 */
fsid_t  f_fsid;     /* 文件系统标识 */
long    f_namelen;  /* 文件名的最大长度 */
};

statfs接口调用成功返回0,失败返回-1.

简单用法:
int resultCode = statfs(path.c_str(), &data);
if (resultCode < 0) {
return false;
} else {
unsigned long freeSize = data.f_bsize * data.f_bfree;
unsigned long availSize = data.f_bsize * data.f_bavail;
unsigned long totalSize = data.f_bsize * data.f_blocks;
}

单位bytes,使用>>20转为MB。

NoClassdefFoundError R$layout

工程引入了jar包,jar包使用了R.layout.xx,但这个layout并没有打进jar包导致找不到R.layout.xx。

It's because inside JAR doesn't contain resource folder of SDK Project.

解决方法有两种:

  1. 导入SDK Project,并以lib的形式依赖。

    如果要把jar包提供出去,则需要使用方法2

  2. 首先,使用下面的方法替代R(在SDK中,R自动为SDK的包名,引入他人工程后肯定找不到这个R,所以不能在SDK中使用R)

    public static int getResourseIdByName(String packageName, String className, String name) {
    Class r = null;
    int id = 0;
    try {
    r = Class.forName(packageName + ".R");

    Class[] classes = r.getClasses();
    Class desireClass = null;

    for (int i = 0; i < classes.length; i++) {
    if(classes[i].getName().split("\\$")[1].equals(className)) {
    desireClass = classes[i];

    break;
    }
    }

    if(desireClass != null)
    id = desireClass.getField(name).getInt(desireClass);
    } catch (ClassNotFoundException e) {
    e.printStackTrace();
    } catch (IllegalArgumentException e) {
    e.printStackTrace();
    } catch (SecurityException e) {
    e.printStackTrace();
    } catch (IllegalAccessException e) {
    e.printStackTrace();
    } catch (NoSuchFieldException e) {
    e.printStackTrace();
    }

    return id;

    }

    举例,如果以前使用了 R.layout.main,现在需要使用getResourseIdByName(context.getPackageName(), "layout", "main")      以前使用了R.id.mView,现在需要使用getResourseIdByName(context.getPackageName(), "id", "mView")

然后,把用到的资源从SDK中copy到Apk工程。

源自http://stackoverflow.com/questions/14373004/java-lang-noclassdeffounderror-com-facebook-android-rlayout-error-when-using-f

 

Android获得内存信息

在Android中,想要获得进程内存信息,有两类方法

1.exec大法,使用Runtime.getRuntime().exec()方法来执行命令行,主要命令行有 dumpsys(需要system权限)  cat /proc等

private String catProc() {
StringBuilder meminfo = new StringBuilder();
try {
ArrayList<String> commandLine = new ArrayList<String>();
commandLine.add("cat");
// commandLine.add("/proc/meminfo");
commandLine.add("/proc/" + android.os.Process.myPid() + "/status");

Process process = Runtime.getRuntime().exec(commandLine.toArray(new String[commandLine.size()]));
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));

String line;
while ((line = bufferedReader.readLine()) != null) {
meminfo.append(line);
meminfo.append("\n");
}

} catch (IOException e) {
Log.e(TAG, "Could not read /proc/meminfo", e);
}

Log.i(TAG, "showMeminfo = " + meminfo.toString());

return meminfo.toString();
}

2.android.os.Debug

Debug类有大量的获取内存信息方法,如getPss,用起来很简单