[转载]微享,微信分享实例-Android开发源码下载-eoe Android开发者社区_Android开发论坛 – Powered by Discuz!.
最近在搞微信分享,因此做了个小应用,坑爹的微信官方文档,真让人火大,这是后话了,先看我这个应用的效果图:
主要有三个功能,拍照立即分享、取本地照片分享、微信好友及好友圈,我一一讲解,先看项目结构图:
(一)拍照
//打开相机
private final int CAMERA_CODE = 1; // 这里的CAMERA_CODE 是自己任意定义的
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); startActivityForResult(intent,CAMERA_CODE);
//onActivityResult方法返回处理拍照照片
protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (resultCode != RESULT_OK) { // 此处的 RESULT_OK 是系统自定义得一个常量 Toast.makeText(WXEntryActivity.this, "操作取消", Toast.LENGTH_SHORT) .show(); return; } switch (requestCode) { case CAMERA_CODE: if (data != null) { // HTC if (data.getData() != null) { // 根据返回的URI获取对应的SQLite信息 Cursor cursor = getContentResolver().query(data.getData(), null, null, null, null); if (cursor.moveToFirst()) { filePath = cursor.getString(cursor .getColumnIndex("_data"));// 获取绝对路径 } cursor.close(); } else { // 三星 小米(小米手机不会自动存储DCIM mBitmap = (Bitmap) (data.getExtras() == null ? null : data .getExtras().get("data")); } // 直接强转报错 这个主要是为了去高宽比例 Bitmap bitmap = mBitmap == null ? null : (Bitmap) mBitmap; if (bitmap == null) { /** * 该Bitmap是为了获取压缩后的文件比例 如果没有缩略图的比例 * 就获取真实文件的比例(真实图片比例会耗时很长,所以如果有缩略图最好) */ bitmap = BitmapFactory.decodeFile(filePath); } path = AppUtil.saveBitmap(bitmap); shareImg.setImageBitmap(AppUtil.getLoacalBitmap(path)); // 设置Bitmap isPicture = true; } break; default: break; } }
其中saveBitmap()方法:
/** * 是否存在SDCard * */ public static boolean hasSdCard() { if (Environment.MEDIA_MOUNTED.equals(Environment .getExternalStorageState())) { return true; } return false; } /** * 将Bitmap保存在本地 * * @param mBitmap * @return */ @SuppressLint("SimpleDateFormat") public static String saveBitmap(Bitmap mBitmap) { try { String sdCardPath = ""; if (hasSdCard()) { sdCardPath = Environment.getExternalStorageDirectory() .getPath(); } else { } String filePath = sdCardPath + "/" + "MicroShare/"; Date date = new Date(System.currentTimeMillis()); SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");// 时间格式-显示方式 String imgPath = filePath + sdf.format(date) + ".png"; File file = new File(filePath); if (!file.exists()) { file.mkdirs(); } File imgFile = new File(imgPath); if (!imgFile.exists()) { imgFile.createNewFile(); } FileOutputStream fOut = new FileOutputStream(imgFile); mBitmap.compress(Bitmap.CompressFormat.PNG, 100, fOut); fOut.flush(); if (fOut != null) { fOut.close(); } return imgPath; } catch (IOException e) { e.printStackTrace(); } return null; }
这样拍照的过程完了,分享等下再说。
(二)本地照片
// 使用intent调用系统提供的相册功能,使用startActivityForResult是为了获取用户选择的图片
private final int IMAGE_CODE = 0; // 这里的IMAGE_CODE是自己任意定义的
Intent getAlbum = new Intent( Intent.ACTION_GET_CONTENT); getAlbum.setType(IMAGE_TYPE); startActivityForResult(getAlbum,IMAGE_CODE);
//onActivityResult方法返回处理照片
protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (resultCode != RESULT_OK) { // 此处的 RESULT_OK 是系统自定义得一个常量 Toast.makeText(WXEntryActivity.this, "操作取消", Toast.LENGTH_SHORT) .show(); return; } switch (requestCode) { case IMAGE_CODE: Bitmap bm = null; // 外界的程序访问ContentProvider所提供数据 可以通过ContentResolver接口 ContentResolver resolver = getContentResolver(); try { Uri originalUri = data.getData(); // 获得图片的uri bm = MediaStore.Images.Media.getBitmap(resolver, originalUri); // 显得到bitmap图片 // 这里开始的第二部分,获取图片的路径: String[] proj = { MediaStore.Images.Media.DATA }; // 好像是android多媒体数据库的封装接口,具体的看Android文档 Cursor cursor = managedQuery(originalUri, proj, null, null, null); // 按我个人理解 这个是获得用户选择的图片的索引值 int column_index = cursor .getColumnIndexOrThrow(MediaStore.Images.Media.DATA); // 将光标移至开头 ,这个很重要,不小心很容易引起越界 cursor.moveToFirst(); // 最后根据索引值获取图片路径 path = cursor.getString(column_index); Bitmap bitmap = AppUtil.getLoacalBitmap(path); // 从本地取图片(在cdcard中获取) shareImg.setImageBitmap(bitmap); // 设置Bitmap isPicture = true; } catch (IOException e) { Toast.makeText(WXEntryActivity.this, e.toString(), Toast.LENGTH_SHORT).show(); } break; default: break; } }
提示:调用系统提供的相册功能时,请选择系统的相册功能进入,比如:
这里请选择系统的,如果你选择第三方进入它的的相册肯定是报错,关于这个错误我没有做处理。
(三)微信分享
这部分是重点也是难点,我慢慢讲解我两天做的微 信分享的心得,首先我给的项目源码你们肯定跑不起来,因为我的这项目已经微信审核通过了,审核的时候应用签名(打包时MD5值)和包名绑定了,因此运行源 码是不能调微信客户端的。附件里已经附带了我打包好了apk,大家可以跑这个看效果。
1、申请你的appid
请到 微信开发者应用登记页面 进行登记,登记并选择移动应用进行设置后,将该应用提交审核,只有审核通过的应用才能进行开发。
2、导jar包
在工程中新建一个libs目录,将开发工具包中libs目录下的libammsdk.jar复制到该目录中(如下图所示,建立了一个名为SDK_Sample 的工程,并把jar包复制到libs目录下)。
3、代码编写
(1)初始化、注册
// 通过WXAPIFactory工厂,获取IWXAPI的实例 api = WXAPIFactory.createWXAPI(this, APP_ID, false); // 将该app注册到微信 api.registerApp(APP_ID); api.handleIntent(getIntent(), this);//此行后面再说
(2)分享部分
此项目制涉及分享本地的图片,代码如下:
// 微信好友 case 0: weixinShare(true); break; // 微信朋友圈 case 1: weixinShare(false); break;
weixinShare方法:
private void weixinShare(boolean isFriend) { File file = new File(path); if (!file.exists()) { String tip = WXEntryActivity.this .getString(R.string.send_img_file_not_exist); Toast.makeText(WXEntryActivity.this, tip + " path = " + path, Toast.LENGTH_LONG).show(); return; } WXImageObject imgObj = new WXImageObject(); imgObj.setImagePath(path); WXMediaMessage msg = new WXMediaMessage(); msg.mediaObject = imgObj; Bitmap bmp = BitmapFactory.decodeFile(path); Bitmap thumbBmp = Bitmap.createScaledBitmap(bmp, THUMB_SIZE, THUMB_SIZE, true); bmp.recycle(); msg.thumbData = Util.bmpToByteArray(thumbBmp, true); int imageSize = msg.thumbData.length / 1024; if (imageSize > 32) { Toast.makeText(WXEntryActivity.this, "您分享的图片过大", Toast.LENGTH_SHORT) .show(); return; } SendMessageToWX.Req req = new SendMessageToWX.Req(); req.transaction = buildTransaction("img"); req.message = msg; req.scene = isFriend ? SendMessageToWX.Req.WXSceneSession : SendMessageToWX.Req.WXSceneTimeline; api.sendReq(req); finish(); }
注意点:如果分享的图片大于35k,微信客户端是没有响应的,因此做了判断,这是官方demo没有的,官方文档有讲解。
(3)接收微信的请求及返回值如果你的程序需要接收微信发送的请求,或者接收发送到微信请求的响应结果,需要下面3步操作:
a. 在你的包名相应目录下新建一个wxapi目录,并在该wxapi目录下新增一个WXEntryActivity类(注意点:必须是wxapi目录,WXEntryActivity类),该类继承自Activity并在manifest文件里面加上exported属性,设置为true,例如:
b. 实现IWXAPIEventHandler接口,微信发送的请求将回调到onReq方法,发送到微信请求的响应结果将回调到onResp方法
c. 在WXEntryActivity中将接收到的intent及实现了IWXAPIEventHandler接口的对象传递给IWXAPI接口的handleIntent方法,示例如下:
api.handleIntent(getIntent(), this);
当微信发送请求到你的应用,将通过IWXAPIEventHandler接口的onReq方法进行回调,类似的,应用请求微信的响应结果将通过onResp回调。
protected void onNewIntent(Intent intent) { super.onNewIntent(intent); setIntent(intent); api.handleIntent(intent, this); } // 微信发送请求到第三方应用时,会回调到该方法 @Override public void onReq(BaseReq req) { } // 第三方应用发送到微信的请求处理后的响应结果,会回调到该方法 @Override public void onResp(BaseResp resp) { String result = ""; switch (resp.errCode) { case BaseResp.ErrCode.ERR_OK: result = "发送成功"; break; case BaseResp.ErrCode.ERR_USER_CANCEL: result = "分享取消"; break; case BaseResp.ErrCode.ERR_AUTH_DENIED: result = "发送失败"; break; default: result = "出现异常"; break; } Toast.makeText(this, result, Toast.LENGTH_LONG).show(); }
(四)其他功能
(1)再按一次退出程序
private static Boolean isExit = false; @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { if (isExit == false) { isExit = true; Toast.makeText(this, "再按一次退出程序", Toast.LENGTH_SHORT).show(); new Timer().schedule(new TimerTask() { @Override public void run() { isExit = false; } }, 2000); } else { finish(); System.exit(0); } } return false; }
(2)检测网络
public boolean checkNetworkInfo() { ConnectivityManager conMan = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); // mobile 3G Data Network State mobile = conMan.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) .getState(); // wifi State wifi = conMan.getNetworkInfo(ConnectivityManager.TYPE_WIFI) .getState(); // 如果3G网络和wifi网络都未连接,且不是处于正在连接状态 则进入Network Setting界面 由用户配置网络连接 if (mobile == State.CONNECTED || mobile == State.CONNECTING) return true; if (wifi == State.CONNECTED || wifi == State.CONNECTING) return true; AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setMessage("网络不给力") .setTitle("提示") .setCancelable(false) .setPositiveButton("配置", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { // 进入无线网络配置界面 startActivity(new Intent( Settings.ACTION_WIRELESS_SETTINGS)); WXEntryActivity.this.finish(); } }) .setNegativeButton("退出", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { WXEntryActivity.this.finish(); } }); builder.show(); return false; }