Android AIDL 使用

一、概述:

AIDL是Android中IPC(Inter-Process Communication)方式中的一种,AIDL是Android Interface definition language的缩写。

其主要作用是用于进程间额通讯。

在Android系统中,每个进程都运行在一块独立的内存中,在其中完成自己的各项活动,与其他进程都分隔开来。可是有时候我们又有应用间进行互动的需求,比较传递数据或者任务委托等,AIDL就是为了满足这种需求而诞生的。通过AIDL,可以在一个进程中获取另一个进程的数据和调用其暴露出来的方法,从而满足进程间通信的需求。
二、语法:
1、支持的数据类型:
  • 八种基本数据类型:byte、char、short、int、long、float、double、boolean
  • String,CharSequence
  • 实现了Parcelable接口的数据类型
  • List 类型。List承载的数据必须是AIDL支持的类型,或者是其它声明的AIDL对象
  • Map类型。Map承载的数据必须是AIDL支持的类型,或者是其它声明的AIDL对象

2、

AIDL文件可以分为两类。一类用来声明实现了Parcelable接口的数据类型,以供其他AIDL文件使用那些非默认支持的数据类型。还有一类是用来定义接口方法,声明要暴露哪些接口给客户端调用,定向Tag就是用来标注这些方法的参数值。

 

3、

定向Tag。定向Tag表示在跨进程通信中数据的流向,用于标注方法的参数值,分为 in、out、inout 三种。其中 in 表示数据只能由客户端流向服务端, out 表示数据只能由服务端流向客户端,而 inout 则表示数据可在服务端与客户端之间双向流通。此外,如果AIDL方法接口的参数值类型是:基本数据类型、String、CharSequence或者其他AIDL文件定义的方法接口,那么这些参数值的定向 Tag 默认是且只能是 in,所以除了这些类型外,其他参数值都需要明确标注使用哪种定向Tag。
4、

明确导包。在AIDL文件中需要明确标明引用到的数据类型所在的包名,即使两个文件处在同个包名下。

 

三、编写代码:

创建两个工程,一个作为服务端,一个作为客户端,客户端绑定服务端service,然后调用方法向服务端获取书籍列表,向服务端添加书籍。

 

1、服务端:

(1)、创建aidl文件Book.aidl

创建后便可以在目录里看到aidl文件。

接下来定义Book类,注意Books类的包名必须与Book.aidl包名一样,但是不可与Book.aidl在同一个目录下。

Book.class的代码如下,其必须继承Parcelable接口:

 

接下来修改Book.aidl文件,将其声明为parcelable类型,并且需要注意的是,原先默认的interface接口需要去掉,否则编译会报错。

 

接下来便是要定义服务端暴露给客户端的接口了(获取书籍列表,添加书籍)

在同样的目录定义aidl文件BookManager.aidl

 

代码如下:

 

注意要把包手动导进来。

接下来,make project便可以看到aidl编译成代码文件

 

这个文件才是我们真正需要用到的。

(2)、创建Service,供客户端绑定

Manifests文件中可以这样写:

 

 onBind方法返回的是BookManager.Stub对象,实现里面的两个方法,客户端拿到这个对象后就可以与服务端通讯了。

 

2、客户端

(1)

将aidl文件与Book.class拷贝到客户端的工程,注意他们的目录需要与服务端的一样,也就是说aidl与Book.class包名要与服务端的一样。

 

make project一下便会生成编译后的文件

(2)、编写代码,与服务端连接:

 

textView3用于绑定服务端

textView4用于获取服务端书籍列表

textView5用于向服务端添加书籍

 

 转载请标明出处:http://77blogs.com/?p=293

参考:https://www.jianshu.com/p/29999c1a93cd

 

 

解决Android编译时出现aapt.exe finished with non-zero exit value 1(第二篇)

转载请标明出处,违权必究:http://77blogs.com/?p=294

之前出现该错误,我用的是这个方法:

https://www.cnblogs.com/tangZH/p/10691383.html

然而遗憾的是,这次不管用了,无奈,只好另寻他法,其实会出现这个错误就是资源文件出现问题,导致无法被打包。

从具体的错误里面也可以看出,确实是资源文件出了问题

 

点击右上角gradle:

 

other里面找到相应的模块,点击运行

然后便可以打印出了错误信息。

 

解决Error:All flavors must now belong to a named flavor dimension. Learn more at…

转载请标明出处:http://77blogs.com/?p=297

低版本的gradle里面不会出现这个错误,高版本出现,不多说,看如何解决

在defaultConfig{}中添加:

flavorDimensions “default”

保证所有的flavor 都属于同一个维度

 

 

Cannot set the value of read-only property ‘outputFile’ for ApkVariantOutputImpl_Decorated{…

转载请标明出处:http://77blogs.com/?p=298

在做多渠道打包的时候出现了这个错误,在高版本的gradle出现。

 

具体错误为:Cannot set the value of read-only property ‘outputFile’ for ApkVariantOutputImpl_Decorated{apkData=Main{type=MAIN, fullName=debug, filters=[]}} of type com.android.build.gradle.internal.api.ApkVariantOutputImpl.
我的代码为下:

 

这个在低版本的gradle是行得通的,但是高版本就不行。

高版本的应该这样:

 

variant.outputs.each改为variant.outputs.all

output.outputFile = new File(outputFile.parent, fileName)改为outputFileName = fileName

 

谈谈Fragment中的onActivityResult

大家或许有遇到这个神坑,在Fragment中使用startActivityForResult能够成功,可是在Fragment中的onActivityResult却无法被调用。一不注意就让人一夜愁白了头。苦经探索(当然包括亲爱的百度和谷歌),终于总结出了一些规律。

在Fragment中使用startActivityForResult之后,onActivityResult的调用是从activity中开始的(即会先调用activity中的onActivityResult)。

一.只嵌套了一层Fragment(比如activity中使用了viewPager,viewPager中添加了几个Fragment)

在这种情况下要注意几个点:

1.在Fragment中使用startActivityForResult的时候,不要使用getActivity().startActivityForResult,而是应该直接使startActivityForResult()。

2.如果activity中重写了onActivityResult,那么activity中的onActivityResult一定要加上super.onActivityResult(requestCode, resultCode, data)。

如果违反了上面两种情况,那么onActivityResult只能够传递到activity中的,无法传递到Fragment中的。

没有违反上面两种情况的前提下,可以直接在Fragment中使用startActivityForResult和onActivityResult,和在activity中使用的一样。

 

二.嵌套多层Fragment(比如activity中使用了viewPager,viewPager中添加了几个Fragment,即第一层Fragment。其中一个Fragment又使用了一个ViewPager,这个ViewPager又加入了几个Fragment,即第二层Fragment)

在这种情况下activity中的onActivityResult调用无法传到第二层Fragment中。自己动手丰衣足食,我们只有手动传了。

让activity继承上面的MyBaseFragmentActivity 。这样就手动把onActivityResult的调用传递到每一层的每一个Fragment里面了。然后在每一个Fragment里面重写onActivityResult就行了,然后根据requestCode和resultCode来分别执行对应事件。

当然,不管是哪个Fragment调用startActivityForResult,onActivityResult的调用都会传递到每个Fragment中。

同样需要注意:

1.如果activity中重写了onActivityResult,那么activity中的onActivityResult一定要加上super.onActivityResult(requestCode, resultCode, data),否则也无法传进Fragment中。

 

不过有点值得注意的是:

在所有的Fragment中若是直接使用startActivityForResult(),那么传到activity中的onActivityResult中的requestCode就会不对,resultCode是对的,当然,这样的话传到每个Fragment中的onActivityResult的requestCode也是不对的(这里大家留意一下,评论里有人说传到Fragment中的是对的)。若是用getActivity().startActivityForResult,则传出来的requestCode和rusultCode就都是对的。

当然若是直接按返回键返回,那么会自动给一个resultCode,这个resultCode和我们设定的是不一样的,因此在重写onActivityResult的时候需要判定resultCode。

由于我们是手动将activity中的onActivityResult的调用传进每一层的每一个Fragment中去的,所以不管在Fragment中是使用startActivityForResult(),还是使用getActivity().startActivityForResult,都没关系,使用getActivity().startActivityForResult不会出现activity中onActivityResult中的调用无法传进去的情况。会影响的只有requestCode。

转载请标明出处,维权必究:http://77blogs.com/?p=11

 

 

解决Android编译时出现aapt.exe finished with non-zero exit value 1

当出现这个错误的时候,说明了你的资源文件出错了。然而AS能给你提供的信息实在太少,看了半天没看出个所以然,也没有说明是哪个资源文件出错,一头雾水。

这时候就可以用

Gradlew

来调试。

而gradlew命令需要java环境,所以我们需要配置JDK和jre环境变量,过程就不说了。

若是已经配置好了java环境,便可使用Android Studio自带的终端进行调试:

此时可以看到一些java信息。

接下来输入一条非常关键的指令:

gradlew processDebugResources --debug

 

然后项目开始编译,屏幕上输出大量编译Log信息

将其全部拷贝到Notepad++,然后搜索:aapt

然后看查找到的appt错误提示是什么,从中可以看到是哪个资源文件出错。

 

转载请标明出处:http://77blogs.com/?p=300

参考文章:https://blog.csdn.net/qq_24118527/article/details/83586161

 

自定义Json解析工具

此博客为博主原创文章,转载请标明出处,维权必究:http://77blogs.com/?p=301

fastjson是很好用的json解析工具,只可惜项目中要求apk体积尽量小,所以并不打算引入fastJson,只好自己写一个,遗憾的是写出的这个并没法解析所有的json数据,不过还是很值得学习的,且听我一一道来。

主要实现两个功能:

1、将jsonArray解析为List

2、将json数据转化为class

当然,class里面的成员变量的名称需要与json里面的key一样。

 

思路:

1、通过反射获取class类里面的成员变量名称以及类型

2、通过成员变量的名称与类型去json数据中获取该key对应的value

2、将value通过反射赋值给class对象。

 

具体且看:

1、定义一个实体类保存class里面的反射获取到的每个成员变量对应字段,名称,类型

 

2、将json数据转换为实体类

 

2.1 取出实体类中的属性,根据名称与类型去jsonObject中取值

 

2.2 给实体类赋值

 

2.3 JsonArrayToList方法

 

3、将jsonArray转为list,注意参数json是jsonArray数据,原理类似,就不再多讲

 

Process ‘command ‘D:\jdk8\jdk\bin\java.exe” finished with non-zero exit value 2

 

转载请标明出处,维权必究:http://77blogs.com/?p=302

捣鼓了好久,现在已经不想说话,为何会出现这个问题,Process ‘command ‘D:\jdk8\jdk\bin\java.exe” finished with non-zero exit value 2。那是因为项目中出现了冲突的依赖包,仔细看看自己有没有重复依赖包咯

 

当然,我也不知道其他问题会不会也造成这个错误。

 

查看自己的依赖树:

执行命令 ./gradlew 模块名:dependencies、

 

便可以查看该module的依赖树了。

C:\Program Files\Java\jdk1.7.0_79\bin\java.exe” finished with non-zero exit value 1

 

转载请标明出处:http://77blogs.com/?p=303

今天,在项目过程中碰到了这个奇怪的问题,C:\Program Files\Java\jdk1.7.0_79\bin\java.exe” finished with non-zero exit value 1,我擦,毫无征兆,毫无头绪,什么鬼,各种谷歌之后,在stackoverflow.com上面看到了别人说解决方案,总的来说就是项目中,不同module中具有相同包名且相同类名的文件

我看了一下自己的,还真是有。。。。。。

最终,通过重命名解决了。

 

地址:https://stackoverflow.com/questions/34766206/error-gradle-build-c-program-files-java-jdk1-7-0-79-bin-java-exe-finished-wit/35045501#35045501

Android自动解析html带图片,实现图文混排

在android中,如何将html代码转换为text,然后显示在textview中呢,有一个简单直接的方法:

 

然而用的时候却发现html里面的图片没法被被解析出来,别慌,Html还有一个方法:

 

其中,我们可以自定义imageGetter,这个对象是用于解析html中的图片。

 

最终调用:

textView.setText(Html.fromHtml(text, new MImageGetter(textView, this), null));

这样便可以实现图文混排了,在该显示图片的地方显示图片。

 

如果是要显示网络上的图片,getDrawable方法可以这样

 

第三个参数 其作用是把 HTML 带标记的文本内容字符串转化成可以显示效果的的 Spanned 字符串 。由于并非所有的 HTML 标签都可以转化,所以在使用时,用户需要自己添加一些必要的标签和处理方法时才会使用的。

 

转载请标明出处,维权必究:http://77blogs.com/?p=304

参考链接:https://blog.csdn.net/qq_30548105/article/details/78031347