最近看了许多基于编译时注解自动生成代码的文章,确实挺实用的,可以减轻我们在开发中重复性代码的书写,提升代码的开发效率,比如我们经常使用的butterknife,dagger等框架,一般写这类项目需要创建几个Model,比如我的项目Model为:
前面的annotations一般为定义自己的注解,为java library,而compile是用来处理annotations中定义的注解,所以要依赖annotations库,也是java library,而wechat_demo为android library,依赖annotations和compile这两个库。
这篇文章主要是用注解处理器处理微信相关业务,必须在自己应用包名后面建.wxapi包名以及WXEntryActivity的问题。跳过微信包名限制。并且以后使用时,只需要引入相应的代码,然后编译,就可以自动生成WXEntryActivity类,不必要每次都在自己的包名后面再建wxapi包名。当然支付也差不多,本篇文章并不是介绍微信相关业务,就不多解释了。
使用
1).编写注解代码
自己定义了一个注解主要用来生成WXEntryActivity类
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
public @interface EntryGenerator {
String packageName();
Class<?> classname();
}
2).编写注解处理器
public class NarkangProcessor extends AbstractProcessor {
@Override
public SourceVersion getSupportedSourceVersion() {
return SourceVersion.latestSupported();
}
@Override
public Set<String> getSupportedAnnotationTypes() {
LinkedHashSet<String> annotiations = new LinkedHashSet<>();
annotiations.add(EntryGenerator.class.getCanonicalName());
return annotiations;
}
@Override
public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
generWXEntryActivityCode(roundEnvironment);
return true;
}
/**
* 生成微信登录分享code
*/
private void generWXEntryActivityCode(RoundEnvironment roundEnvironment) {
WXEntryVisitor wxEntryVisitor = new WXEntryVisitor(processingEnv.getFiler());
scan(roundEnvironment, EntryGenerator.class, wxEntryVisitor);
}
private void scan(RoundEnvironment env,
Class<? extends Annotation> annotation,
AnnotationValueVisitor visitor) {
//返回使用给定注释类型注释的元素。
for (Element typeElement : env.getElementsAnnotatedWith(annotation)) {
//getAnnotationMirrors 返回直接存在于此元素上的注释。
final List<? extends AnnotationMirror> annotationMirrors =
typeElement.getAnnotationMirrors();
for (AnnotationMirror annotationMirror : annotationMirrors) {
//AnnotationMirror 返回此注释元素的值。
final Map<? extends ExecutableElement, ? extends AnnotationValue> elementValues
= annotationMirror.getElementValues();
for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry
: elementValues.entrySet()) {
//将一个 visitor 应用到此值。
entry.getValue().accept(visitor, null);
}
}
}
}
}
WXEntryVisitor 代码为:
/**
* Created by Administrator on 2017/9/4.
* 生成微信登录和分享所必须要写的代码,可以直接跳过微信包名限制
*/
public class WXEntryVisitor extends SimpleAnnotationValueVisitor7{
private Filer mFiler;
private String mPackageName;
WXEntryVisitor(Filer filer){
mFiler = filer;
}
@Override
public Object visitString(String s, Object o) {
mPackageName = s;
return o;
}
@Override
public Object visitType(TypeMirror typeMirror, Object o) {
generateJavaCode(typeMirror);
return o;
}
//生成java代码
private void generateJavaCode(TypeMirror typeMirror) {
final TypeSpec targetActivity = TypeSpec.classBuilder("WXEntryActivity")
.addModifiers(Modifier.PUBLIC)
.superclass(TypeName.get(typeMirror))
.build();
JavaFile javaFile = JavaFile.builder(mPackageName + ".wxapi", targetActivity)
.addFileComment("微信登录和分享入口文件")
.build();
try {
javaFile.writeTo(mFiler);
} catch (IOException e) {
e.printStackTrace();
}
}
}
基本都是模板代码,网上资料很多。
3).编写微信相关业务
a.BaseWXActivity
public abstract class BaseWXActivity extends AppCompatActivity implements IWXAPIEventHandler{
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
WeChatUtil.getApi().handleIntent(getIntent(), this);
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
WeChatUtil.getApi().handleIntent(getIntent(), this);
}
}
登录和支付的代码都可以直接继承自这里
b.BaseWXEntryActivity
public class BaseWXEntryActivity extends BaseWXActivity {
//微信请求第三方应用回调
@Override
public void onReq(BaseReq baseReq) {
}
//微信响应第三方应用回调
@Override
public void onResp(BaseResp baseResp) {
String code = ((SendAuth.Resp)baseResp).code;
//获取access_token
StringBuilder sb = new StringBuilder();
sb.append("https://api.weixin.qq.com/sns/oauth2/access_token?")
.append("appid=")
.append(WeChatUtil.appid)
.append("&secret=")
.append(WeChatUtil.secret)
.append("&code=")
.append(code)
.append("&grant_type=authorization_code");
HttpUtil.sendGetRequest(sb.toString(), new DataGetSuccessListener() {
@Override
public void dataGetSuccess(String date) {
System.out.println("获取token----------->>>>>"+date);
try {
JSONObject jsonObject = new JSONObject(date);
String access_token = jsonObject.getString("access_token");
String openid = jsonObject.getString("openid");
//获取用户信息
StringBuffer sb = new StringBuffer();
sb.append("https://api.weixin.qq.com/sns/userinfo?access_token=")
.append(access_token)
.append("&openid=")
.append(openid);
HttpUtil.sendGetRequest(sb.toString(), new DataGetSuccessListener() {
@Override
public void dataGetSuccess(final String date) {
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
WeChatUtil.mListener.getUserInfo(date);
}
});
}
});
} catch (JSONException e) {
e.printStackTrace();
}
}
});
finish();
}
}
这些都是微信开发者平台都有的,我只是简单集成到一起了。
c.使用自定义的注解生成WXEntryActivity
@EntryGenerator(
packageName = "自己应用的包名",
classname = BaseWXEntryActivity.class
)
public class WXEntryTemplate {
}
生成的代码:
及其简单。
好了,就介绍到这里。
最后
代码还可以简化,以后慢慢补充。