</pre>在公司实习做网页,需要做app的微信授权登陆,由于没有人做过android,有过有一点经验的我就瞬间转战android了,废话不多说,直接上干货。</h2><div><span style="white-space:pre"> </span> 看微信开放平台的微信授权接入指南其实一切都已经足够了,个人觉得微信的文档写得实在有点蛋疼,对于一个初做者的话,感觉有点迷茫,下面我就仔细分析一下过程吧。</div><div></div><div>1.在微信开放平台上申请appid。到管理中心->创建移动应用,微信上说一个周申请成功,一般只要一天就可以通过了。申请的时候,有两个东西可能会不好理解,一个是应用包名,如下图:</div><div><img src="https://img-blog.csdn.net/20150811164119404?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" width="600" height="200" alt="" /></div><div></div><div>或者也可以到AndroidManifest.xml文件中查看,具体位置如代码:</div><div></div><div><pre name="code" class="html"><?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="cm.senguo"
android:versionCode="1"
android:versionName="1.0" >
另外一个需要填写的是应用签名,这个官网上说了,有专门的签名生成工具,你可以先把自己的app安装到自己的手机,然后下载安装签名生成工具,即可根据包名生成相应的签名。填写好这些信息之后等待审核即可。
2.下载微信终端开发工具包,开发包中主要含有3部分,然后只有
libammsdk.jar是必须的,下载好了之后把这个文件复制到自己工程的libs目录下面,如果没有这个目录,则自己新建一个,然后配置文件路径,右键点击工程,选择Build Path中的Configure Build Path...,选中Libraries这个tab,并通过Add Jars...导入工程libs目录下的libammsdk.jar文件。这个jar包里面包含了将要使用到的微信终端api。然后对AndroidManifest.xml 进行设置,代码如下:
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
到这里,相关配置就基本上完成了,接下来就可以相关代码的处理了。
3.微信授权处理一般单独进行封装,在你的工程/src/ 目录下新建一个包名,一般以自己的“应用包名+.wxapi" 作为包名,当然也不一定非得这样,自己定义也是可以的。在新建的包下面新建一个类 WXEntryActivity 作为微信授权处理的类,继承于Activity和IWXAPIEventHandler,代码如下(解释详见注释):
</pre><pre name="code" class="java">public class WXEntryActivity extends Activity implements IWXAPIEventHandler{
// IWXAPI 是第三方app和微信进行通信的openapi接口
public static IWXAPI api;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(api==null){ / / 创建微信api对象,获取<span style="font-family: Arial, Helvetica, sans-serif;">IWXAPI 实例</span>
api = WXAPIFactory.createWXAPI(this, Constants.APP_ID, false);
}
// 根据在微信开放;平台注册的appid注册app
api.registerApp(Constants.APP_ID);
<strong> <span style="background-color: rgb(255, 255, 51);"> //我在做微信授权功能的时候就是因为下面这句话的位置没有放对,然后一直导致的结果是能够拉起微信授权的页面,但是一旦点击确定授权之后就什么都没有了,后来通过各种调试,才发现在 发送请求到微信之前就必须调用这个函数,目的是将<span style="color: rgb(34, 34, 34); font-family: 'Hiragino Sans GB', 'Microsoft YaHei', 黑体, Helvetica, Arial, Tahoma, sans-serif; font-size: 14px; line-height: 22.3999996185303px;">将接收到的intent及实现了IWXAPIEventHandler接口的对象传递给IWX//API接口,所以必须在接下来的发送页面请求之前调用,切记。。。</span></span></strong>
api.handleIntent(getIntent(),this);
if (!api.isWXAppInstalled()){ //判断用户是否安装了微信客户端
Toast.makeText(WXEntryActivity.this,"你还没有安装微信,请安装合适版本的微信",Toast.LENGTH_LONG).show();
return;
}
//发送启动页面请求,我在实际做的时候又遇到了问题,我做了两个app,但是在使用<pre name="code" class="java">//req.openId=Constants.APP_ID;
//这句代码的时候发现了一个奇怪的现象,我这句话不能调用,找了半天发现问题在于我自动导入包的时候两个app导入的包不一样:
//其中一个是:
//import com.tencent.mm.sdk.constants.ConstantsAPI;
//import com.tencent.mm.sdk.modelbase.BaseReq;
//import com.tencent.mm.sdk.modelbase.BaseResp;
//import com.tencent.mm.sdk.modelmsg.SendAuth;
//import com.tencent.mm.sdk.modelmsg.SendAuth.Resp;
//另一个是:
//import com.cm.senguoadmin.Constants;
//import com.tencent.mm.sdk.openapi.BaseReq;
//import com.tencent.mm.sdk.openapi.BaseResp;
//import com.tencent.mm.sdk.openapi.ConstantsAPI;
//import com.tencent.mm.sdk.openapi.IWXAPI;
//你发现区别了吗?后来我在网上查到了有人也遇到过这种问题,因为最新的包并不需要这个openid,好吧,自己注意吧~
final SendAuth.Req req=new SendAuth.Req();
req.openId=Constants.APP_ID;
req.scope="snsapi_userinfo";
req.state="carjob_wx_login";
api.sendReq(req);
//到此,微信授权页面就可以拉起了
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
api.handleIntent(intent, this);
}
//下面的函数是微信授权的时候等待用户确认调用的,微信会自动调用,因此不需要自己显示调用
@Override
public void onReq(BaseReq req) {
switch (req.getType()) {
case ConstantsAPI.COMMAND_GETMESSAGE_FROM_WX:
break;
case ConstantsAPI.COMMAND_SHOWMESSAGE_FROM_WX:
break;
// 授权
case ConstantsAPI.COMMAND_SENDAUTH:
break;
default:
break;
}
}
//以下函数微信在授权成功后会自动调用,我们如果需要拉去微信信息的话,就可以在<span style="font-family: Arial, Helvetica, sans-serif;">case BaseResp.ErrCode.ERR_OK:后面添加代码</span>
@Override
public void onResp(BaseResp resp) {
int result = 0;
Bundle bundle=new Bundle();
switch (resp.errCode) {
case BaseResp.ErrCode.ERR_OK:
result = R.string.errcode_success;
resp.toBundle(bundle);
Resp sp=new Resp(bundle);
final String code=sp.code; //针对具体导入的包不同,这里会有所不同,我做的时候一个需要sp.code,但是一个却是sp.token,好吧,不过,虽然长相不一一样,但是//功能却是相同的
<strong style="background-color: rgb(255, 255, 51);">//不要以为现在你就已经大工告成了,下面的这个问题一定会让你欲哭无泪的,那就是android访问网路一定要新开线程,也就是说不能在主线程中进行访问网络或者画图等比较耗时的操作,一定要注意这个啊,我因为这个研究了一整天</strong>
new Thread(){
@Override
public void run(){
//这个函数是我封装的获取微信信息的函数,见后面的代码
goToGetMsg(code);
}
}.start();
this.finish();
break;
case BaseResp.ErrCode.ERR_USER_CANCEL:
break;
case BaseResp.ErrCode.ERR_AUTH_DENIED:
break;
case ConstantsAPI.COMMAND_SENDAUTH:
break;
default:
result = R.string.errcode_unknown;
break;
}
}
对于goToGetMsg(code)函数,主要就是根据code获取微信个人信息,具体分为两步:
通过code获取access_token
获取第一步的code后,请求以下链接获取access_token:
https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
APPID和SECRET都是注册app的时候获得的,此处不多说。
通过access_token调用接口
获取access_token后,进行接口调用,
httpUrl="https://api.weixin.qq.com/sns/userinfo?access_token="+ACCESS_TOKEN+"&openid="+OPENID;
到此,微信信息就可以获取了,然后可以对得到的返回数据进行处理,返回数据识json格式,具体处理过程此处步详细叙述了。最后,附上代码片段:
private void goToGetMsg(String code) {
String result = null;
// http地址
URL url = null;
HttpURLConnection connection = null;
InputStreamReader in = null;
try {
url = new URL("https://api.weixin.qq.com/sns/oauth2/access_token?appid="+Constants.APP_ID+"&secret="+Constants.APP_SECRET+"&code="+code+"&grant_type=authorization_code");
connection = (HttpURLConnection) url.openConnection();
in = new InputStreamReader(connection.getInputStream());
BufferedReader bufferedReader = new BufferedReader(in);
StringBuffer strBuffer = new StringBuffer();
String line = null;
while ((line = bufferedReader.readLine()) != null) {
strBuffer.append(line);
}
result = strBuffer.toString();
Log.v("str",result);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (connection != null) {
connection.disconnect();
}
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
String ACCESS_TOKEN=null;
String OPENID=null;
try {
JSONObject datajson=new JSONObject(result);
ACCESS_TOKEN=datajson.getString("access_token");
OPENID=datajson.getString("unionid");
} catch (JSONException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
String httpUrl="https://api.weixin.qq.com/sns/userinfo?access_token="+ACCESS_TOKEN+"&openid="+OPENID;
// String httpUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid="+Constants.APP_ID+"&secret="+Constants.APP_SECRET+"&code="+code+"&grant_type=authorization_code";
// HttpGet连接对象
HttpGet httpRequest = new HttpGet(httpUrl);
try
{
// 取得HttpClient对象
HttpClient httpclient = new DefaultHttpClient();
// 请求HttpClient,取得HttpResponse
HttpResponse httpResponse = httpclient.execute(httpRequest);
// 请求成功
if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK)
{
// 取得返回的字符串
String strResult = EntityUtils.toString(httpResponse.getEntity());
JSONObject user;
String unionid = null;
String openid = null;
String country=null;
String province=null;
String city=null;
String headimgurl=null;
String nickname=null;
int sex=0;
try {
user=new JSONObject(strResult);
unionid=user.getString("unionid");
openid=user.getString("openid");
country=user.getString("country");
province=user.getString("province");
city=user.getString("city");
headimgurl=user.getString("headimgurl");
nickname=user.getString("nickname");
sex=user.getInt("sex");
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String info="http://test123.senguo.cc/customer/weixinphoneadmin?openid="+openid+"&unionid="+unionid+"&country="+country+"&province="+
province+"&city="+city+"&headimgurl="+headimgurl+"&nickname="+nickname+"&sex="+sex;
finish();
Intent intent=new Intent(WXEntryActivity.this,Senguo_admin.class);
Bundle bundle=new Bundle();
bundle.putCharSequence("URL", info);
intent.putExtras(bundle);
startActivity(intent);
}
else
{
Log.e("error","请求错误!");
}
}
catch (ClientProtocolException e)
{
Log.e("duizhan",e.getMessage().toString());
}
catch (IOException e)
{
Log.e("duizhan",e.getMessage().toString());
}
catch (Exception e)
{
Log.e("duizhan",e.getMessage().toString());
}
}
总结:具体需要注意的东西在过程中都一一记录了,以前做android都没有涉及到种调用第三方api的内容,经过这次实践,最深的体会就是要仔细看相关api的文档。说点别的吧,这是我的第一篇博客,写得有点粗糙,以后慢慢改进吧,不过技术这种东西,干活为主吧。希望自己以后越走越好~~good luck
</pre>在公司实习做网页,需要做app的微信授权登陆,由于没有人做过android,有过有一点经验的我就瞬间转战android了,废话不多说,直接上干货。</h2><div><span style="white-space:pre"> </span> 看微信开放平台的微信授权接入指南其实一切都已经足够了,个人觉得微信的文档写得实在有点蛋疼,对于一个初做者的话,感觉有点迷茫,下面我就仔细分析一下过程吧。</div><div></div><div>1.在微信开放平台上申请appid。到管理中心->创建移动应用,微信上说一个周申请成功,一般只要一天就可以通过了。申请的时候,有两个东西可能会不好理解,一个是应用包名,如下图:</div><div><img src="https://img-blog.csdn.net/20150811164119404?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" width="600" height="200" alt="" /></div><div></div><div>或者也可以到AndroidManifest.xml文件中查看,具体位置如代码:</div><div></div><div><pre name="code" class="html"><?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="cm.senguo"
android:versionCode="1"
android:versionName="1.0" >
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
到这里,相关配置就基本上完成了,接下来就可以相关代码的处理了。
</pre><pre name="code" class="java">public class WXEntryActivity extends Activity implements IWXAPIEventHandler{
// IWXAPI 是第三方app和微信进行通信的openapi接口
public static IWXAPI api;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(api==null){ / / 创建微信api对象,获取<span style="font-family: Arial, Helvetica, sans-serif;">IWXAPI 实例</span>
api = WXAPIFactory.createWXAPI(this, Constants.APP_ID, false);
}
// 根据在微信开放;平台注册的appid注册app
api.registerApp(Constants.APP_ID);
<strong> <span style="background-color: rgb(255, 255, 51);"> //我在做微信授权功能的时候就是因为下面这句话的位置没有放对,然后一直导致的结果是能够拉起微信授权的页面,但是一旦点击确定授权之后就什么都没有了,后来通过各种调试,才发现在 发送请求到微信之前就必须调用这个函数,目的是将<span style="color: rgb(34, 34, 34); font-family: 'Hiragino Sans GB', 'Microsoft YaHei', 黑体, Helvetica, Arial, Tahoma, sans-serif; font-size: 14px; line-height: 22.3999996185303px;">将接收到的intent及实现了IWXAPIEventHandler接口的对象传递给IWX//API接口,所以必须在接下来的发送页面请求之前调用,切记。。。</span></span></strong>
api.handleIntent(getIntent(),this);
if (!api.isWXAppInstalled()){ //判断用户是否安装了微信客户端
Toast.makeText(WXEntryActivity.this,"你还没有安装微信,请安装合适版本的微信",Toast.LENGTH_LONG).show();
return;
}
//发送启动页面请求,我在实际做的时候又遇到了问题,我做了两个app,但是在使用<pre name="code" class="java">//req.openId=Constants.APP_ID;
//这句代码的时候发现了一个奇怪的现象,我这句话不能调用,找了半天发现问题在于我自动导入包的时候两个app导入的包不一样:
//其中一个是:
//import com.tencent.mm.sdk.constants.ConstantsAPI;
//import com.tencent.mm.sdk.modelbase.BaseReq;
//import com.tencent.mm.sdk.modelbase.BaseResp;
//import com.tencent.mm.sdk.modelmsg.SendAuth;
//import com.tencent.mm.sdk.modelmsg.SendAuth.Resp;
//另一个是:
//import com.cm.senguoadmin.Constants;
//import com.tencent.mm.sdk.openapi.BaseReq;
//import com.tencent.mm.sdk.openapi.BaseResp;
//import com.tencent.mm.sdk.openapi.ConstantsAPI;
//import com.tencent.mm.sdk.openapi.IWXAPI;
//你发现区别了吗?后来我在网上查到了有人也遇到过这种问题,因为最新的包并不需要这个openid,好吧,自己注意吧~
final SendAuth.Req req=new SendAuth.Req();
req.openId=Constants.APP_ID;
req.scope="snsapi_userinfo";
req.state="carjob_wx_login";
api.sendReq(req);
//到此,微信授权页面就可以拉起了
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
api.handleIntent(intent, this);
}
//下面的函数是微信授权的时候等待用户确认调用的,微信会自动调用,因此不需要自己显示调用
@Override
public void onReq(BaseReq req) {
switch (req.getType()) {
case ConstantsAPI.COMMAND_GETMESSAGE_FROM_WX:
break;
case ConstantsAPI.COMMAND_SHOWMESSAGE_FROM_WX:
break;
// 授权
case ConstantsAPI.COMMAND_SENDAUTH:
break;
default:
break;
}
}
//以下函数微信在授权成功后会自动调用,我们如果需要拉去微信信息的话,就可以在<span style="font-family: Arial, Helvetica, sans-serif;">case BaseResp.ErrCode.ERR_OK:后面添加代码</span>
@Override
public void onResp(BaseResp resp) {
int result = 0;
Bundle bundle=new Bundle();
switch (resp.errCode) {
case BaseResp.ErrCode.ERR_OK:
result = R.string.errcode_success;
resp.toBundle(bundle);
Resp sp=new Resp(bundle);
final String code=sp.code; //针对具体导入的包不同,这里会有所不同,我做的时候一个需要sp.code,但是一个却是sp.token,好吧,不过,虽然长相不一一样,但是//功能却是相同的
<strong style="background-color: rgb(255, 255, 51);">//不要以为现在你就已经大工告成了,下面的这个问题一定会让你欲哭无泪的,那就是android访问网路一定要新开线程,也就是说不能在主线程中进行访问网络或者画图等比较耗时的操作,一定要注意这个啊,我因为这个研究了一整天</strong>
new Thread(){
@Override
public void run(){
//这个函数是我封装的获取微信信息的函数,见后面的代码
goToGetMsg(code);
}
}.start();
this.finish();
break;
case BaseResp.ErrCode.ERR_USER_CANCEL:
break;
case BaseResp.ErrCode.ERR_AUTH_DENIED:
break;
case ConstantsAPI.COMMAND_SENDAUTH:
break;
default:
result = R.string.errcode_unknown;
break;
}
}
对于goToGetMsg(code)函数,主要就是根据code获取微信个人信息,具体分为两步:
通过code获取access_token
获取第一步的code后,请求以下链接获取access_token:
https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
通过access_token调用接口
获取access_token后,进行接口调用,
httpUrl="https://api.weixin.qq.com/sns/userinfo?access_token="+ACCESS_TOKEN+"&openid="+OPENID;
到此,微信信息就可以获取了,然后可以对得到的返回数据进行处理,返回数据识json格式,具体处理过程此处步详细叙述了。最后,附上代码片段:
private void goToGetMsg(String code) {
String result = null;
// http地址
URL url = null;
HttpURLConnection connection = null;
InputStreamReader in = null;
try {
url = new URL("https://api.weixin.qq.com/sns/oauth2/access_token?appid="+Constants.APP_ID+"&secret="+Constants.APP_SECRET+"&code="+code+"&grant_type=authorization_code");
connection = (HttpURLConnection) url.openConnection();
in = new InputStreamReader(connection.getInputStream());
BufferedReader bufferedReader = new BufferedReader(in);
StringBuffer strBuffer = new StringBuffer();
String line = null;
while ((line = bufferedReader.readLine()) != null) {
strBuffer.append(line);
}
result = strBuffer.toString();
Log.v("str",result);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (connection != null) {
connection.disconnect();
}
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
String ACCESS_TOKEN=null;
String OPENID=null;
try {
JSONObject datajson=new JSONObject(result);
ACCESS_TOKEN=datajson.getString("access_token");
OPENID=datajson.getString("unionid");
} catch (JSONException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
String httpUrl="https://api.weixin.qq.com/sns/userinfo?access_token="+ACCESS_TOKEN+"&openid="+OPENID;
// String httpUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid="+Constants.APP_ID+"&secret="+Constants.APP_SECRET+"&code="+code+"&grant_type=authorization_code";
// HttpGet连接对象
HttpGet httpRequest = new HttpGet(httpUrl);
try
{
// 取得HttpClient对象
HttpClient httpclient = new DefaultHttpClient();
// 请求HttpClient,取得HttpResponse
HttpResponse httpResponse = httpclient.execute(httpRequest);
// 请求成功
if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK)
{
// 取得返回的字符串
String strResult = EntityUtils.toString(httpResponse.getEntity());
JSONObject user;
String unionid = null;
String openid = null;
String country=null;
String province=null;
String city=null;
String headimgurl=null;
String nickname=null;
int sex=0;
try {
user=new JSONObject(strResult);
unionid=user.getString("unionid");
openid=user.getString("openid");
country=user.getString("country");
province=user.getString("province");
city=user.getString("city");
headimgurl=user.getString("headimgurl");
nickname=user.getString("nickname");
sex=user.getInt("sex");
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String info="http://test123.senguo.cc/customer/weixinphoneadmin?openid="+openid+"&unionid="+unionid+"&country="+country+"&province="+
province+"&city="+city+"&headimgurl="+headimgurl+"&nickname="+nickname+"&sex="+sex;
finish();
Intent intent=new Intent(WXEntryActivity.this,Senguo_admin.class);
Bundle bundle=new Bundle();
bundle.putCharSequence("URL", info);
intent.putExtras(bundle);
startActivity(intent);
}
else
{
Log.e("error","请求错误!");
}
}
catch (ClientProtocolException e)
{
Log.e("duizhan",e.getMessage().toString());
}
catch (IOException e)
{
Log.e("duizhan",e.getMessage().toString());
}
catch (Exception e)
{
Log.e("duizhan",e.getMessage().toString());
}
}
总结:具体需要注意的东西在过程中都一一记录了,以前做android都没有涉及到种调用第三方api的内容,经过这次实践,最深的体会就是要仔细看相关api的文档。说点别的吧,这是我的第一篇博客,写得有点粗糙,以后慢慢改进吧,不过技术这种东西,干活为主吧。希望自己以后越走越好~~good luck