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.不要做过多的其他尝试,这两步绝对可以解决问题。

IntelliJ IDEA2016.2使用Gradle创建Java Web应用

1.如下图,第一步很简单的,File->New->Project
20160502164417038

2.如下图,完成第一步后,会弹出这样一个窗体,然后在左边栏目找到Gradle,然后在右边勾选JavaWeb两个选项,最后点击Next
20160502164806993
3.如下图,到了输入GroupIdAcrtifactId窗口了,对于这两个名字的解释

GroupID是项目组织唯一的标识符,实际对应JAVA的包的结构,是main目录里java的目录结构。
ArtifactID就是项目的唯一的标识符,实际对应项目的名称,就是项目根目录的名称。
一般来说,包的命名习惯是域名的反过来,加个公司或者个人的名称吧,个人习惯。www.demo.com -> com.richard.demo; 那么都知道,test是项目名称,也是在最后面的,所有项目组的唯一标识符(groupId):com.richard, 项目的唯一标识符(ArtifactId)demo.

然后点击Next
20160502165336980

4. 如下图,这个页面,刚进来默认选择的是Use default gradle wrapper(recommended), 我不选择这个是因为我本地有装Gradle,所有不需要是用它默认的,如果选择它,那么创建项目之后,它就会去自动下载Gradle,然后配置好,下载过 程一般都很慢,至少我在我电脑上很慢。所有我选择的是Use local gradle distribution,。然后上面还有一个勾选,就是自动创建空的根目录文件夹,如果不选择,创建完的项目会没有Java文件夹,所以勾选,让它自动创建吧,继续点击Next
20160502172330113
5. 如下图,它默认的就是ArtifactId的名字,项目的唯一标识嘛,然后module name,如果不清楚应该填什么,可以按照默认的无所谓,点击Finish,创建就这样完成了。
20160502172559648
6.创建完成之后,如果你之前没有配置Tomcat的话,是没办法运行的,所以也需要配置Tomcat,如下图, 左侧是成功创建的项目文件目录,如果之前没有勾选Create directories for empty content roots automatically, 那么就不会生成javaresource这个两个孔文件夹。这不的重点是点击Edit configuration
20160502173439340
6. 弹出如下图配置框,点击左上角加号,往下滚动找到Tomcat Server->Local,点击Local.
20160502174005936
7. 如下图,弹出配置框,默认是配置Server属性,输入这个配置的名字,name,可以取任意的名字,点击Configure选择本地Tomcat的路径,都配置好了直接点击OK就可以运行了。
20160502174445592
8.如下图,然后选择Server旁边的Deployment, 页面之后,点击加号,在弹出的页面选择名字更长的那个,也就是后面有(exploded)的那条,点击OK
20160502175547163

9.如下图,在右侧输入Application context的名字,这个对应就是等会儿运行时,默认路径(http://localhost:8080/demo/)中的demo, 所以如果你不配置这项,它的默认路径将会是(http://localhost:8080/)这样的。最后点击Apply, 再点击OK.
20160502180004992
10.倒数第二步了,如下图,打开index.jsp页面,长方形圈出来的是系统默认生成的,不用管,可以删掉,然后圆圈的是我自己写的。我只是为了让你知道,jsp页面长啥样子的,免得你看到它,以为是生成错文件了,点击有上角的运行按钮。
20160502180443932

11.最后一步,见证如下成果。
20160502180826574

参考链接


IntelliJ IDEA2016.1 + maven 创建java web 项目

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。

Android中对SD卡/U盘挂载和卸载的监听

Android系统中,当SD卡挂载在电脑上时候,如果手动将语音备忘录中的录音删除的时,那么相应数据库中的数据也是需要修改的。此时实现需要对挂载进行监听,需要继承BroadcastReceiver类,实现其中的onRecieve(Context context, Intent inten)方法。代码如下:

此时须在Manifest中进行注册:

参考链接


android中对SD卡挂载和卸载的监听

Java 读写Properties配置文件

1.Properties类与Properties配置文件

Properties类继承自Hashtable类并且实现了Map接口,也是使用一种键值对的形式来保存属性集。不过Properties有特殊的地方,就是它的键和值都是字符串类型。

2.Properties中的主要方法

(1)load(InputStream inStream)

   这个方法可以从.properties属性文件对应的文件输入流中,加载属性列表到Properties类对象如下面的代码:

(2)store(OutputStream out, String comments)

这个方法将Properties类对象的属性列表保存到输出流中如下面的代码:

如果comments不为空,保存后的属性文件第一行会是#comments,表示注释信息;如果为空则没有注释信息。

注释信息后面是属性文件的当前保存时间信息。

(3)getProperty/setProperty

这两个方法是分别是获取和设置属性信息。

3.代码实例

属性文件a.properties如下:

读取a.properties属性列表,与生成属性文件b.properties。代码如下:

参考链接


Java 读写Properties配置文件

Android获取外接SD卡或者U盘路径方法

最近在开发Android时遇到插U盘获取U盘内容的需求,但是按照传统的Environment.getExternalStorageDirectory()只能读取到插入的SD卡的路径,如果是U盘的话无法读出U盘的路径。

最终在一个在CSDN的论坛里找到相关的东西,就试了下直接通过StorageManager获取存储路径的。

核心如下,volumePaths的数组就是系统外接设备的路径,经过测试的确是挂载的路径。不过有些是不可用的,它只是列出了系统可支持的外接路径。

参考链接


android获取外接SD卡或者U盘路径方法

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