实战 QQ demo (学习 android 先来个QQ)
实战 QQ demo (学习 android 先来个QQ)
源码
服务器端下载:http://download.csdn.net/download/knight_black_bob/9822551
android eclipse 版:http://download.csdn.net/download/knight_black_bob/9822553
android stdio 版本:http://download.csdn.net/download/knight_black_bob/9822556
ps :该demo 中的 .9.png 为盗图,在as中不可使,在eclispe 中可以
先看效果图
android 框架
xlistviewswipe badgeview slidemenu scrollerview
volley
xutils3.0
eventbus
mob-sharesdk
baidupush
java
webservice+restful
bccs-api(百度推送)
数据库设计
用户表
CREATE TABLE `t_user` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `name` varchar(255) DEFAULT NULL, `nick_name` varchar(255) DEFAULT NULL, `password` varchar(255) DEFAULT NULL, `mail` varchar(255) DEFAULT NULL, `telphone` varchar(255) DEFAULT NULL, `photo` varchar(255) DEFAULT NULL, `insert_time` timestamp NULL DEFAULT NULL, `last_update_time` timestamp NULL DEFAULT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=1403271249 DEFAULT CHARSET=utf8
用户关系表
CREATE TABLE `t_friendship` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `user_src` bigint(20) DEFAULT NULL, `parent_id` bigint(20) DEFAULT NULL, `name` varchar(255) DEFAULT NULL, `user_id` bigint(20) DEFAULT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8
图床表
CREATE TABLE `picrepository` ( `id` int(10) NOT NULL AUTO_INCREMENT, `origin_name` varchar(255) DEFAULT NULL, `path` varchar(255) DEFAULT NULL, `user_id` int(10) DEFAULT NULL, `link` varchar(255) DEFAULT NULL, `insert_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `last_update_time` timestamp NULL DEFAULT NULL, `description` varchar(255) DEFAULT NULL, `nextfix` varchar(255) DEFAULT NULL, `pic_size` int(10) DEFAULT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=10002 DEFAULT CHARSET=utf8
朋友圈
CREATE TABLE `t_feed` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `user_from` bigint(20) DEFAULT NULL, `user_icon` varchar(255) DEFAULT NULL, `user_nickname` varchar(30) DEFAULT NULL, `clicknum` int(10) DEFAULT NULL, `location` varchar(200) DEFAULT NULL, `content` varchar(500) DEFAULT NULL, `insert_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `last_update_time` timestamp NULL DEFAULT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8
朋友圈评论
CREATE TABLE `t_feed_comment` ( `id` int(11) NOT NULL AUTO_INCREMENT, `feed_id` int(11) DEFAULT NULL, `user_a_id` bigint(20) DEFAULT NULL, `user_a_nickname` varchar(255) DEFAULT NULL, `user_b_id` bigint(20) DEFAULT NULL, `user_b_nickname` varchar(255) DEFAULT NULL, `parent_id` int(11) DEFAULT '0', `content` varchar(255) DEFAULT NULL, `insert_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP, `last_update_time` timestamp NULL DEFAULT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8
朋友圈图片
CREATE TABLE `t_feed_pic` ( `id` int(11) NOT NULL AUTO_INCREMENT, `feed_id` int(11) DEFAULT NULL, `pic_name` varchar(255) DEFAULT NULL, `pic_link` varchar(255) DEFAULT NULL, `insert_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `last_update_time` timestamp NULL DEFAULT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8
朋友圈点赞
CREATE TABLE `t_feed_zan` ( `id` int(11) NOT NULL AUTO_INCREMENT, `feed_id` int(11) DEFAULT NULL, `user_id` bigint(20) DEFAULT NULL, `user_nickname` varchar(255) DEFAULT NULL, `insert_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP, `last_update_time` timestamp NULL DEFAULT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8
聊天记录
CREATE TABLE `t_chatmessage` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `content` varchar(255) DEFAULT NULL, `user_src` bigint(20) DEFAULT NULL, `user_from` bigint(20) DEFAULT NULL, `user_to` bigint(20) DEFAULT NULL, `insert_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP, `last_update_time` timestamp NULL DEFAULT NULL, `new_flag` int(11) DEFAULT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8
java 图床设计接口
@Path(value = "/showPic")@Produces({ MediaType.APPLICATION_XML}) @Consumes({ MediaType.APPLICATION_XML})@Componentpublic class ShowPicRestService {// http://192.168.1.102:8080/RepositoryPic/WebService/rest/showPic/users/1401155710/pics/1.png@GET@Produces("image/*")@Path("/users/{userId}/pics/{picName}")public Response getInputStream(@PathParam("userId")int userId,@PathParam("picName")String picName, @Context HttpServletRequest request) throws Exception { HttpSession session = request.getSession(); ServletContext application = session.getServletContext(); String serverRealPath = application.getRealPath("/") ; String path = (serverRealPath +"img/"+userId+".png"); File file = new File(path); return Response.ok(file,"image/jpg").build();}@GET@Produces("image/*")@Path("/feed/{picSaveName}")public Response getInputStream(@PathParam("picSaveName")String picSaveName, @Context HttpServletRequest request) throws Exception { HttpSession session = request.getSession(); ServletContext application = session.getServletContext(); String serverRealPath = application.getRealPath("/") ; String path = (serverRealPath +"img/feed/"+picSaveName+".png"); File file = new File(path); return Response.ok(file,"image/jpg").build();}}
好友关系
@Path(value = "/friendShip")@Produces({ MediaType.APPLICATION_JSON}) @Consumes({ MediaType.APPLICATION_JSON}) @Component public class FriendShipRestService {@ResourceFriendShipSoapService friendShipSoapService;@ResourceUserSoapService userSoapService;@GET@Produces({ MediaType.APPLICATION_JSON}) @Path("/friendShips/{userId}")public Response getFriendShips(@PathParam("userId") Long userId) { List<FriendShip> fses = friendShipSoapService.getAllByUserId(userId); List<User> userList = new ArrayList<User>();for (FriendShip fs:fses) {if (fs.getUserId() != 0) {userList.add(userSoapService.get(fs.getUserId()));}}QueryResultJson result=new QueryResultJson(400,"error",null);if (null != fses && fses.size()>0 ) { result= new QueryResultJson();result.retcode = 200;result.retmsg ="success";FriendShipUserList list = new FriendShipUserList(fses,userList);result.retdata = list; } return Response .ok(result) .build(); }public static class FriendShipUserList{public List<FriendShip> friendShipList;public List<User> userList;public FriendShipUserList(List<FriendShip> fses, List<User> userList) { this.friendShipList = fses;this.userList = userList;}}}
朋友圈 详细
@Path(value = "/feedAll")@Produces({ MediaType.APPLICATION_JSON}) @Consumes({ MediaType.APPLICATION_JSON}) @Component public class FeedAllRestService {@ResourceFeedAllService feedAllService;@Resource FeedCommentDao feedCommentDao;@ResourceFeedZanDao feedZanDao;@ResourceFeedDao feedDao;@ResourceFeedPicDao feedPicDao;@GET@Produces({ MediaType.APPLICATION_JSON}) @Path("/feedAlls/user/{userId}/start/{start}")public Response getFriendShips(@PathParam("userId") Long userId ,@PathParam("start") int start ) { List<FeedAll> list = feedAllService.getAlls(userId, start, Constants.defaultPageNum);QueryResultJson result=new QueryResultJson(400,"error",null);if (null != list && list.size()>0 ) { result= new QueryResultJson();result.retcode = 200;result.retmsg ="success"; result.retdata = list; } else{result= new QueryResultJson();result.retcode = 400;result.retmsg ="no data"; result.retdata = list; } return Response .ok(result) .build(); }@POST@Consumes({ MediaType.APPLICATION_JSON})@Path("/feedCommemtAdd")public Response feedCommemtAdd(@RequestBody FeedComment feedc ) {int saveFeedComment = feedCommentDao.saveFeedComment(feedc);QueryResultJson result = new QueryResultJson(400, "error", null);if (saveFeedComment == 1) {result = new QueryResultJson();result.retcode = 200;result.retmsg = "success";}return Response.ok(result).build();}@POST@Consumes({ MediaType.APPLICATION_JSON})@Path("/feedZanAdd")public Response feedZanAdd(@RequestBody FeedZan feedz ) {FeedZan feedZan = feedZanDao.getFeedZan(feedz.getFeedId(), feedz.getUserId());if (feedZan != null) {feedZanDao.deleteFeedZan(feedz.getFeedId(), feedz.getUserId());} else{ feedZanDao.saveFeedZan(feedz);}QueryResultJson result = new QueryResultJson(400, "error", null);result = new QueryResultJson();result.retcode = 200;result.retmsg = "success";return Response.ok(result).build();}@POST@Consumes("multipart/form-data") @Path("/createFeed")public Response createFeed( List<Attachment>attachments,@Context HttpServletRequest request ) {long userFrom = 0;String userNickname = null,userIcon = null,location = null,content = null; List<FileKv> fileList = new ArrayList<FileKv>();for (Attachment attach : attachments) { DataHandler dh = attach.getDataHandler(); System.out.println(attach.getContentType().toString()); // text/plain;charset=UTF-8 if (attach.getContentType().toString().contains("text/plain")) { try { System.out.println(dh.getName()); System.out.println(writeToString(dh.getInputStream())); if ("userFrom".equals(dh.getName())) { userFrom = Long.valueOf( writeToString(dh.getInputStream()));}else if("userNickname".equals(dh.getName())) { userNickname = writeToString(dh.getInputStream()) ;}else if("userIcon".equals(dh.getName())) { userIcon = writeToString(dh.getInputStream()) ;}else if("location".equals(dh.getName())) { location = writeToString(dh.getInputStream()) ;}else if("content".equals(dh.getName())) {content = writeToString(dh.getInputStream()) ;} } catch (Exception e) { e.printStackTrace(); } } else if(attach.getContentType().toString().contains("application/octet-stream")){ String path = request.getRealPath("/"); String picSaveName = DatetimeUtil.getUniqueTimestamp()+""; try { writeToFile(dh.getInputStream(), path +"img/feed/"+ picSaveName+".png"); fileList.add(new FileKv(dh.getName(),picSaveName)); } catch (IOException e) { e.printStackTrace(); } }else{ } } Feed feed = new Feed(); feed.setUserFrom(userFrom); feed.setUserNickname( userNickname ); feed.setUserIcon( userIcon ); feed.setLocation( location ); feed.setContent( content ); feed.setClicknum(0); feed.setInsertTime(new Date()); feed.setLastUpdateTime(new Date()); int feedId = feedDao.saveFeedReturnFeedId(feed); for (FileKv kv : fileList) { feedPicDao.saveFeedPic(new FeedPic(feedId, kv.fileName, Constants.BASEIP+"/RepositoryPic/WebService/rest/showPic/feed/"+kv.fileSaveName, new Date(), new Date() )); }QueryResultJson result = new QueryResultJson(400, "error", null);result = new QueryResultJson();result.retcode = 200;result.retmsg = "success";return Response.ok(result).build();}private void writeToFile(InputStream ins, String path) { try { OutputStream out = new FileOutputStream(new File(path)); int read = 0; byte[] bytes = new byte[1024]; while ((read = ins.read(bytes)) != -1) { out.write(bytes, 0, read); } out.flush(); out.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } private String writeToString(InputStream ins) throws Exception { ByteArrayOutputStream out = new ByteArrayOutputStream(); byte[] b = new byte[1024]; int i = -1; while ((i = ins.read(b)) != -1) { out.write(b, 0, i); } ins.close(); return new String(out.toByteArray(), "UTF-8"); } public class FileKv{ public String fileName; public String fileSaveName; public FileKv(String fileName, String fileSaveName) {this.fileName = fileName;this.fileSaveName = fileSaveName;} }}
java 百度推送后台 推送 (用户 标签绑定)
@Path(value = "/pushService")@Produces({ MediaType.APPLICATION_JSON}) @Consumes({ MediaType.APPLICATION_JSON}) @Component public class BaidupushRestService {// http://192.168.1.102:8080/RepositoryPic/WebService/rest/pushService/addDevicesToTag@GET@Consumes({ MediaType.APPLICATION_JSON})@Path("/addDevicesToTag")public Response addDevicesToTag( @QueryParam("tag") String tag ,@QueryParam("channelId") String channelId) { System.out.println("============="+tag+"-------------------"+channelId);QueryResultJson result=new QueryResultJson(400,"error",null); if ( !StringUtils.isEmpty(tag) &&!StringUtils.isEmpty(channelId)) { boolean addDevicesToTag =true; try {boolean queryTag = BaiduPushServerApi.queryTag(tag); boolean createTag = true;if(!queryTag){ createTag = BaiduPushServerApi.createTag(tag);}if (createTag) { addDevicesToTag = BaiduPushServerApi.AddDevicesToTag(tag, channelId);}} catch (Exception e) { e.printStackTrace();}result = new QueryResultJson(200,"success",addDevicesToTag);} return Response.ok(result).build();}// http://192.168.1.102:8080/RepositoryPic/WebService/rest/pushService/sendMessageToTag@POST@Consumes({ MediaType.APPLICATION_JSON})@Path("/sendMessageToTag")public Response sendMessageToTag(@RequestBody TagMessage tagMessage ) { System.out.println("====="+tagMessage.toString());QueryResultJson result=new QueryResultJson(400,"error",null); if ( tagMessage != null) {BaiduPushServerApi.sendAndroidMessageFromTag( tagMessage.title,tagMessage.content, tagMessage.userFrom, tagMessage.userTo);result = new QueryResultJson(200,"success",true);} return Response.ok(result).build();}}class TagMessage{public String title;public String content; public long userFrom;public long userTo;@Overridepublic String toString() {return "TagMessage [title=" + title + ", content=" + content + ", userFrom=" + userFrom + ", userTo=" + userTo+ "]";}}
android 依赖 jar 和 框架依赖
android 百度推送 接收端
package com.curiousby.fitnessandappointment.quote.baidupush; import java.util.Date;import java.util.List;import org.json.JSONException;import org.json.JSONObject;import android.content.Context;import android.text.TextUtils;import android.util.Log;import com.baidu.android.pushservice.PushMessageReceiver;import com.curiousby.fitnessandappointment.MyApplication;import com.curiousby.fitnessandappointment.entity.ChatMessageEntity;import com.curiousby.fitnessandappointment.entity.CommonMessages;import com.curiousby.fitnessandappointment.entity.UserEntity;import com.curiousby.fitnessandappointment.request.db.ChatMessageDB;import com.curiousby.fitnessandappointment.request.db.CommonMsgDB;import com.curiousby.fitnessandappointment.request.db.UserDB;import com.curiousby.fitnessandappointment.request.dbmanager.ChatMessageDBManager;import com.curiousby.fitnessandappointment.request.dbmanager.CommonMessagesDBManager;import com.curiousby.fitnessandappointment.utils.JsonParser;import com.curiousby.fitnessandappointment.utils.PrefInfoUtils;import com.curiousby.fitnessandappointment.utils.RequestUtil;public class BaiduPushReceiver extends PushMessageReceiver{private UserEntity user ; private UserDB userDB; private ChatMessageDB chatMessageDB;private CommonMsgDB commonMsgDB;/** TAG to Log */ public static final String TAG = BaiduPushReceiver.class .getSimpleName(); /** * 调用PushManager.startWork后,sdk将对push * server发起绑定请求,这个过程是异步的。绑定请求的结果通过onBind返回。 如果您需要用单播推送,需要把这里获取的channel * id和user id上传到应用server中,再调用server接口用channel id和user id给单个手机或者用户推送。 * * @param context * BroadcastReceiver的执行Context * @param errorCode * 绑定接口返回值,0 - 成功 * @param appid * 应用id。errorCode非0时为null * @param userId * 应用user id。errorCode非0时为null * @param channelId * 应用channel id。errorCode非0时为null * @param requestId * 向服务端发起的请求id。在追查问题时有用; * @return none */ @Override public void onBind(Context context, int errorCode, String appid, String userId, String channelId, String requestId) { String responseString = "onBind errorCode=" + errorCode + " appid=" + appid + " userId=" + userId + " channelId=" + channelId + " requestId=" + requestId; System.out.println("baoyou -=========== "+responseString); Log.d(TAG, responseString); final String myChannelId = channelId; if (errorCode == 0) { // 绑定成功 if (channelId != null) { String userInfo = PrefInfoUtils.getUserInfo(MyApplication.newInstance()); user = JsonParser.parseDateJson(userInfo, UserEntity.class); Log.d(TAG, "========"+user.getId()+"========"+ channelId); try {//BaiduPushServerApi.AddDevicesToTag( user.getId()+"", channelId); RequestUtil.addDeviceToTag(user.getId()+"", myChannelId);} catch (Exception e) { e.printStackTrace(); }} } // Demo更新界面展示代码,应用请在这里加入自己的处理逻辑// updateContent(context, responseString); } /** * 接收透传消息的函数。 * * @param context * 上下文 * @param message * 推送的消息 * @param customContentString * 自定义内容,为空或者json字符串 */ @Override public void onMessage(Context context, String message, String customContentString) { String messageString = "透传消息 message=\"" + message + "\" customContentString=" + customContentString; Log.d(TAG, messageString); // Toast.makeText(MyApplication.newInstance(), messageString , Toast.LENGTH_SHORT).show(); if(!TextUtils.isEmpty(message)){ JSONObject msg = null; try {msg = new JSONObject(message);String title = null;String content = null;long userFrom = 0;long userTo = 0; if (!msg.isNull("title")) { title = msg.getString("title"); }if (!msg.isNull("content")) {content = msg.getString("content"); } if (!msg.isNull("userFrom")) { userFrom = msg.getLong("userFrom"); } if (!msg.isNull("userTo")) { userTo = msg.getLong("userTo"); } String userInfo = PrefInfoUtils.getUserInfo(MyApplication.newInstance()); user = JsonParser.parseDateJson(userInfo, UserEntity.class); chatMessageDB = new ChatMessageDB(MyApplication.newInstance(), user.getId()+""); ChatMessageEntity lastEntity = chatMessageDB.getLastEntity(); long id = 0; if (lastEntity!= null ) { id = lastEntity.getId() + 1; } if (user.getId() == userTo) { userDB = new UserDB(MyApplication.newInstance(), user.getId()+""); commonMsgDB = new CommonMsgDB(MyApplication.newInstance(), user.getId()+""); UserEntity entityById = userDB.getEntityById(userFrom+""); CommonMessages commonMessages = new CommonMessages(userFrom, entityById.getNickName(), new Date(), content, entityById.getPhoto(),1); commonMsgDB.saveOrUpdate(commonMessages ); CommonMessagesDBManager.recieveOneMessage(); ChatMessageEntity item = new ChatMessageEntity(id, content, user.getId(), userFrom, userTo, new Date(), new Date(), 0); chatMessageDB.saveOrUpdate(item); ChatMessageDBManager.recieveChatMessage(item); // Toast.makeText(MyApplication.newInstance(), user.getId()+"----"+userFrom +"---"+userTo , Toast.LENGTH_LONG ).show(); }} catch (JSONException e) { e.printStackTrace();} } // 自定义内容获取方式,mykey和myvalue对应透传消息推送时自定义内容中设置的键和值 if (!TextUtils.isEmpty(customContentString)) { JSONObject customJson = null; try { customJson = new JSONObject(customContentString); String myvalue = null; if (!customJson.isNull("tag")) { myvalue = customJson.getString("mykey"); } } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); } } // Demo更新界面展示代码,应用请在这里加入自己的处理逻辑 // updateContent(context, messageString); } /** * 接收通知点击的函数。 * * @param context * 上下文 * @param title * 推送的通知的标题 * @param description * 推送的通知的描述 * @param customContentString * 自定义内容,为空或者json字符串 */ @Override public void onNotificationClicked(Context context, String title, String description, String customContentString) { String notifyString = "通知点击 title=\"" + title + "\" description=\"" + description + "\" customContent=" + customContentString; Log.d(TAG, notifyString); // 自定义内容获取方式,mykey和myvalue对应通知推送时自定义内容中设置的键和值 if (!TextUtils.isEmpty(customContentString)) { JSONObject customJson = null; try { customJson = new JSONObject(customContentString); String myvalue = null; if (!customJson.isNull("mykey")) { myvalue = customJson.getString("mykey"); } } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); } } // Demo更新界面展示代码,应用请在这里加入自己的处理逻辑 updateContent(context, notifyString); /* Intent intent = new Intent(); intent.setClass(context.getApplicationContext(), PushMessageDetailActivity.class); intent.putExtra("pushMsgId",Tools.splitStr(s1)); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.getApplicationContext().startActivity(intent); */ } /** * 接收通知到达的函数。 * * @param context * 上下文 * @param title * 推送的通知的标题 * @param description * 推送的通知的描述 * @param customContentString * 自定义内容,为空或者json字符串 */ @Override public void onNotificationArrived(Context context, String title, String description, String customContentString) { String notifyString = "onNotificationArrived title=\"" + title + "\" description=\"" + description + "\" customContent=" + customContentString; Log.d(TAG, notifyString); // 自定义内容获取方式,mykey和myvalue对应通知推送时自定义内容中设置的键和值 if (!TextUtils.isEmpty(customContentString)) { JSONObject customJson = null; try { customJson = new JSONObject(customContentString); String myvalue = null; if (!customJson.isNull("mykey")) { myvalue = customJson.getString("mykey"); } } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); } } // Demo更新界面展示代码,应用请在这里加入自己的处理逻辑 // 你可以參考 onNotificationClicked中的提示从自定义内容获取具体值 updateContent(context, notifyString); } /** * setTags() 的回调函数。 * * @param context * 上下文 * @param errorCode * 错误码。0表示某些tag已经设置成功;非0表示所有tag的设置均失败。 * @param successTags * 设置成功的tag * @param failTags * 设置失败的tag * @param requestId * 分配给对云推送的请求的id */ @Override public void onSetTags(Context context, int errorCode, List<String> sucessTags, List<String> failTags, String requestId) { String responseString = "onSetTags errorCode=" + errorCode + " sucessTags=" + sucessTags + " failTags=" + failTags + " requestId=" + requestId; Log.d(TAG, responseString); // Demo更新界面展示代码,应用请在这里加入自己的处理逻辑 updateContent(context, responseString); } /** * delTags() 的回调函数。 * * @param context * 上下文 * @param errorCode * 错误码。0表示某些tag已经删除成功;非0表示所有tag均删除失败。 * @param successTags * 成功删除的tag * @param failTags * 删除失败的tag * @param requestId * 分配给对云推送的请求的id */ @Override public void onDelTags(Context context, int errorCode, List<String> sucessTags, List<String> failTags, String requestId) { String responseString = "onDelTags errorCode=" + errorCode + " sucessTags=" + sucessTags + " failTags=" + failTags + " requestId=" + requestId; Log.d(TAG, responseString); // Demo更新界面展示代码,应用请在这里加入自己的处理逻辑 updateContent(context, responseString); } /** * listTags() 的回调函数。 * * @param context * 上下文 * @param errorCode * 错误码。0表示列举tag成功;非0表示失败。 * @param tags * 当前应用设置的所有tag。 * @param requestId * 分配给对云推送的请求的id */ @Override public void onListTags(Context context, int errorCode, List<String> tags, String requestId) { String responseString = "onListTags errorCode=" + errorCode + " tags=" + tags; Log.d(TAG, responseString); // Demo更新界面展示代码,应用请在这里加入自己的处理逻辑 updateContent(context, responseString); } /** * PushManager.stopWork() 的回调函数。 * * @param context * 上下文 * @param errorCode * 错误码。0表示从云推送解绑定成功;非0表示失败。 * @param requestId * 分配给对云推送的请求的id */ @Override public void onUnbind(Context context, int errorCode, String requestId) { String responseString = "onUnbind errorCode=" + errorCode + " requestId = " + requestId; Log.d(TAG, responseString); if (errorCode == 0) { // 解绑定成功 } // Demo更新界面展示代码,应用请在这里加入自己的处理逻辑 updateContent(context, responseString); } private void updateContent(Context context, String content) { }}
android 百度推送 用户绑定标签
package com.curiousby.fitnessandappointment.quote.baidupush;import java.util.List;import com.baidu.yun.core.log.YunLogEvent;import com.baidu.yun.core.log.YunLogHandler;import com.baidu.yun.push.auth.PushKeyPair;import com.baidu.yun.push.client.BaiduPushClient;import com.baidu.yun.push.constants.BaiduPushConstants;import com.baidu.yun.push.exception.PushClientException;import com.baidu.yun.push.exception.PushServerException;import com.baidu.yun.push.model.AddDevicesToTagRequest;import com.baidu.yun.push.model.AddDevicesToTagResponse;import com.baidu.yun.push.model.DeviceInfo;public class BaiduPushServerApi {public static void AddDevicesToTag(String tag,String channelId) throws Exception{ // 1. get apiKey and secretKey from developer consoleString apiKey = BaiduConstants.apiKey;String secretKey = BaiduConstants.secretKey;PushKeyPair pair = new PushKeyPair(apiKey, secretKey);// 2. build a BaidupushClient object to access released interfacesBaiduPushClient pushClient = new BaiduPushClient(pair,BaiduConstants.CHANNEL_REST_URL);// 3. register a YunLogHandler to get detail interacted information// in this request.pushClient.setChannelLogHandler(new YunLogHandler() {@Overridepublic void onHandle(YunLogEvent event) {System.out.println(event.getMessage());}});try {// 4. specify request argumentsString[] channelIds = {channelId} ;AddDevicesToTagRequest request = new AddDevicesToTagRequest().addTagName(tag).addChannelIds(channelIds).addDeviceType(3);// 5. http requestAddDevicesToTagResponse response = pushClient.addDevicesToTag(request);// Http请求结果解析打印if (null != response) {StringBuilder strBuilder = new StringBuilder();strBuilder.append("devicesInTag:{");List<?> devicesInfo = response.getDevicesInfoAfterAdded();for (int i = 0; i < devicesInfo.size(); i++) {Object object = devicesInfo.get(i);if (i != 0) {strBuilder.append(",");}if (object instanceof DeviceInfo) {DeviceInfo deviceInfo = (DeviceInfo) object;strBuilder.append("{channelId:"+ deviceInfo.getChannelId() + ",result:"+ deviceInfo.getResult() + "}");}}strBuilder.append("}");System.out.println(strBuilder.toString());}} catch (PushClientException e) {if (BaiduPushConstants.ERROROPTTYPE) {throw e;} else {e.printStackTrace();}} catch (PushServerException e) {if (BaiduPushConstants.ERROROPTTYPE) {throw e;} else {System.out.println(String.format("requestId: %d, errorCode: %d, errorMessage: %s",e.getRequestId(), e.getErrorCode(), e.getErrorMsg()));}}}}
android 接收推送 修改 小红点
public void onEventMainThread( RequestEvent event){ if (event instanceof CommonMessagesDBEvent) { CommonMessagesDBEvent dbEvent = (CommonMessagesDBEvent) event; switch (dbEvent.status) {case DB_SUCCESS: { List<CommonMessages> list = dbEvent.mDataList;if (list != null && list.size() > 0 ) {long num =0;for (CommonMessages c : list) {num += c.getRecieveNum();}//sendMessageTip(mBottomMenuMsg, Integer.parseInt(num+""), BadgeView.POSITION_RIGHT_TOP);updateMessageTip(mBadgeViewMsg, Integer.parseInt(num+""));}}break;case DB_NONE: {updateMessageTip(mBadgeViewMsg, 0); }break;case HTTP_ADD_ONE: {CommonMessagesDBManager.getAllFromDB(commonMsgDB);}break;default:break;} }} public static BadgeView sendMessageTip(View targetView, int messageCount, int gravity) {BadgeView badge = new BadgeView(MyApplication.newInstance(), targetView);badge.setText("" + messageCount);badge.setTextColor(Color.WHITE);badge.setTextSize(10);badge.setGravity(Gravity.CENTER);badge.setBadgePosition(gravity);Drawable drawable = MyApplication.newInstance().getResources().getDrawable(R.drawable.red_point);badge.setBackgroundDrawable(drawable);badge.hide();return badge;} public static void updateMessageTip(BadgeView badgeView, int messageCount) {badgeView.setText(messageCount + "");if (messageCount == 0) {badgeView.hide();} else {badgeView.show();} }
android 图片选择器 使用 微信的图片选择器
package com.curiousby.fitnessandappointment.activity;import java.io.File;import java.io.FilenameFilter;import java.util.ArrayList;import java.util.Arrays;import java.util.HashSet;import java.util.List;import com.curiousby.fitnessandappointment.R;import com.curiousby.fitnessandappointment.quote.picselector.ImageFloder;import com.curiousby.fitnessandappointment.quote.picselector.ListImageDirPopupWindow;import com.curiousby.fitnessandappointment.quote.picselector.ListImageDirPopupWindow.OnImageDirSelected;import com.curiousby.fitnessandappointment.quote.picselector.PicSelectorAdapter;import android.app.Activity;import android.app.ProgressDialog;import android.content.ContentResolver;import android.content.Intent;import android.database.Cursor;import android.net.Uri;import android.os.Bundle;import android.os.Environment;import android.os.Handler;import android.provider.MediaStore;import android.util.DisplayMetrics;import android.util.Log;import android.view.LayoutInflater;import android.view.View;import android.view.View.OnClickListener;import android.view.ViewGroup.LayoutParams;import android.view.WindowManager;import android.widget.GridView;import android.widget.PopupWindow.OnDismissListener;import android.widget.Button;import android.widget.RelativeLayout;import android.widget.TextView;import android.widget.Toast; public class PicSelectorActivity extends Activity implements OnImageDirSelected,OnClickListener{private ProgressDialog mProgressDialog;/** * 存储文件夹中的图片数量 */private int mPicsSize;/** * 图片数量最多的文件夹 */private File mImgDir;/** * 所有的图片 */private List<String> mImgs;private GridView mGirdView;private PicSelectorAdapter mAdapter;private Button sureButton;private Button unsureButton;/** * 临时的辅助类,用于防止同一个文件夹的多次扫描 */private HashSet<String> mDirPaths = new HashSet<String>();/** * 扫描拿到所有的图片文件夹 */private List<ImageFloder> mImageFloders = new ArrayList<ImageFloder>();private RelativeLayout mBottomLy;private TextView mChooseDir;private TextView mImageCount;int totalCount = 0;private int mScreenHeight;private ListImageDirPopupWindow mListImageDirPopupWindow;private Handler mHandler = new Handler(){public void handleMessage(android.os.Message msg){mProgressDialog.dismiss();// 为View绑定数据data2View();// 初始化展示文件夹的popupWindwinitListDirPopupWindw();}};/** * 为View绑定数据 */private void data2View(){if (mImgDir == null){Toast.makeText(getApplicationContext(), "擦,一张图片没扫描到",Toast.LENGTH_SHORT).show();return;}mImgs = Arrays.asList(mImgDir.list());/** * 可以看到文件夹的路径和图片的路径分开保存,极大的减少了内存的消耗; */mAdapter = new PicSelectorAdapter(getApplicationContext(), mImgs,R.layout.picselector_grid_item, mImgDir.getAbsolutePath());mGirdView.setAdapter(mAdapter);mImageCount.setText(totalCount + "张");};/** * 初始化展示文件夹的popupWindw */private void initListDirPopupWindw(){mListImageDirPopupWindow = new ListImageDirPopupWindow(LayoutParams.MATCH_PARENT, (int) (mScreenHeight * 0.7),mImageFloders, LayoutInflater.from(getApplicationContext()).inflate(R.layout.picselector_list_dir, null));mListImageDirPopupWindow.setOnDismissListener(new OnDismissListener(){@Overridepublic void onDismiss(){// 设置背景颜色变暗WindowManager.LayoutParams lp = getWindow().getAttributes();lp.alpha = 1.0f;getWindow().setAttributes(lp);}});// 设置选择文件夹的回调mListImageDirPopupWindow.setOnImageDirSelected(this);}@Overrideprotected void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.picselector_activity_main);DisplayMetrics outMetrics = new DisplayMetrics();getWindowManager().getDefaultDisplay().getMetrics(outMetrics);mScreenHeight = outMetrics.heightPixels;initView();getImages();initEvent();}/** * 利用ContentProvider扫描手机中的图片,此方法在运行在子线程中 完成图片的扫描,最终获得jpg最多的那个文件夹 */private void getImages(){if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){Toast.makeText(this, "暂无外部存储", Toast.LENGTH_SHORT).show();return;}// 显示进度条mProgressDialog = ProgressDialog.show(this, null, "正在加载...");new Thread(new Runnable(){@Overridepublic void run(){String firstImage = null;Uri mImageUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;ContentResolver mContentResolver = PicSelectorActivity.this.getContentResolver();// 只查询jpeg和png的图片Cursor mCursor = mContentResolver.query(mImageUri, null,MediaStore.Images.Media.MIME_TYPE + "=? or "+ MediaStore.Images.Media.MIME_TYPE + "=?",new String[] { "image/jpeg", "image/png" },MediaStore.Images.Media.DATE_MODIFIED);Log.e("TAG", mCursor.getCount() + "");while (mCursor.moveToNext()){// 获取图片的路径String path = mCursor.getString(mCursor.getColumnIndex(MediaStore.Images.Media.DATA));Log.e("TAG", path);// 拿到第一张图片的路径if (firstImage == null)firstImage = path;// 获取该图片的父路径名File parentFile = new File(path).getParentFile();if (parentFile == null)continue;String dirPath = parentFile.getAbsolutePath();ImageFloder imageFloder = null;// 利用一个HashSet防止多次扫描同一个文件夹(不加这个判断,图片多起来还是相当恐怖的~~)if (mDirPaths.contains(dirPath)){continue;} else{mDirPaths.add(dirPath);// 初始化imageFloderimageFloder = new ImageFloder();imageFloder.setDir(dirPath);imageFloder.setFirstImagePath(path);}if(parentFile.list()==null)continue ;int picSize = parentFile.list(new FilenameFilter(){@Overridepublic boolean accept(File dir, String filename){if (filename.endsWith(".jpg")|| filename.endsWith(".png")|| filename.endsWith(".jpeg"))return true;return false;}}).length;totalCount += picSize;imageFloder.setCount(picSize);mImageFloders.add(imageFloder);if (picSize > mPicsSize){mPicsSize = picSize;mImgDir = parentFile;}}mCursor.close();// 扫描完成,辅助的HashSet也就可以释放内存了mDirPaths = null;// 通知Handler扫描图片完成mHandler.sendEmptyMessage(0x110);}}).start();}/** * 初始化View */private void initView(){sureButton = (Button) findViewById(R.id.b_selector_title_btn_sure);unsureButton = (Button) findViewById(R.id.b_selector_title_btn_unsure);mGirdView = (GridView) findViewById(R.id.id_gridView);mChooseDir = (TextView) findViewById(R.id.id_choose_dir);mImageCount = (TextView) findViewById(R.id.id_total_count);mBottomLy = (RelativeLayout) findViewById(R.id.id_bottom_ly);}private void initEvent(){mBottomLy.setOnClickListener(this);sureButton.setOnClickListener(this);unsureButton.setOnClickListener(this);}@Overridepublic void selected(ImageFloder floder){mImgDir = new File(floder.getDir());mImgs = Arrays.asList(mImgDir.list(new FilenameFilter(){@Overridepublic boolean accept(File dir, String filename){if (filename.endsWith(".jpg") || filename.endsWith(".png")|| filename.endsWith(".jpeg"))return true;return false;}}));/** * 可以看到文件夹的路径和图片的路径分开保存,极大的减少了内存的消耗; */mAdapter = new PicSelectorAdapter(getApplicationContext(), mImgs,R.layout.picselector_grid_item, mImgDir.getAbsolutePath());mGirdView.setAdapter(mAdapter);// mAdapter.notifyDataSetChanged();mImageCount.setText(floder.getCount() + "张");mChooseDir.setText(floder.getName());mListImageDirPopupWindow.dismiss();}@Overridepublic void onClick(View view) { switch (view.getId()) {case R.id.b_selector_title_btn_sure:{List<String> list = PicSelectorAdapter.getmSelectedImage();Intent intent = new Intent();intent.putStringArrayListExtra("list", new ArrayList<String>(list));setResult(TrendCreateActivity.RESULT_OK, intent);Log.e("baoyou", "=============="+list.toString());PicSelectorAdapter.removeAllMSelectedImage(); Log.e("baoyou", "---------------======--------------========");finish();}break;case R.id.b_selector_title_btn_unsure:{List<String> list = PicSelectorAdapter.getmSelectedImage();Intent intent = new Intent();intent.putStringArrayListExtra("list", new ArrayList<String>(list));setResult(TrendCreateActivity.RESULT_NO, intent);Log.e("baoyou", "=============="+list.toString());PicSelectorAdapter.removeAllMSelectedImage(); Log.e("baoyou", "---------------======--------------========");finish();}break;case R.id.id_bottom_ly: {mListImageDirPopupWindow .setAnimationStyle(R.style.anim_popup_dir);mListImageDirPopupWindow.showAsDropDown(mBottomLy, 0, 0);// 设置背景颜色变暗WindowManager.LayoutParams lp = getWindow().getAttributes();lp.alpha = .3f;getWindow().setAttributes(lp); }break;default:break;}} }
android 朋友圈设计
package com.curiousby.fitnessandappointment.activity;import java.util.ArrayList;import java.util.Date;import java.util.List;import android.content.Context;import android.content.Intent;import android.os.Bundle;import android.view.View;import android.view.View.OnClickListener;import android.view.View.OnFocusChangeListener;import android.view.inputmethod.InputMethodManager;import android.widget.Button;import android.widget.EditText;import android.widget.LinearLayout;import cn.sharesdk.framework.ShareSDK;import cn.sharesdk.onekeyshare.OnekeyShare; import com.curiousby.fitnessandappointment.R;import com.curiousby.fitnessandappointment.adpter.TrendAdapter;import com.curiousby.fitnessandappointment.entity.FeedAllEntity;import com.curiousby.fitnessandappointment.entity.FeedCommentEntity;import com.curiousby.fitnessandappointment.entity.FeedEntity;import com.curiousby.fitnessandappointment.entity.FeedPicEntity;import com.curiousby.fitnessandappointment.entity.FeedZanEntity;import com.curiousby.fitnessandappointment.entity.UserEntity;import com.curiousby.fitnessandappointment.listener.OnClickCommentListener;import com.curiousby.fitnessandappointment.listener.OnClickForwordListener;import com.curiousby.fitnessandappointment.listener.OnClickToTrendCreateListener;import com.curiousby.fitnessandappointment.listener.OnClickZanListener;import com.curiousby.fitnessandappointment.quote.xlistview.MsgListView;import com.curiousby.fitnessandappointment.quote.xlistview.MsgListView.IXListViewListener;import com.curiousby.fitnessandappointment.request.db.UserDB;import com.curiousby.fitnessandappointment.request.event.TrendHttpEvent;import com.curiousby.fitnessandappointment.request.event.base.RequestEvent;import com.curiousby.fitnessandappointment.request.http.TrendHttpRequest;import com.curiousby.fitnessandappointment.utils.JsonParser;import com.curiousby.fitnessandappointment.utils.PrefInfoUtils;import de.greenrobot.event.EventBus;public class TrendActivity extends BaseActivity implements IXListViewListener , OnClickListener ,OnFocusChangeListener,OnClickCommentListener,OnClickZanListener, OnClickToTrendCreateListener,OnClickForwordListener { final static int defaultPageNum = 5;private Context mContext;private EditText sendContent;LinearLayout inputLayout;private Button sendButton;private MsgListView mListView;private List<FeedAllEntity> mDataList; private TrendAdapter mAdapter;private UserDB userDB; private UserEntity user;private static int start = 0; // send reply needprivate boolean isReply;private FeedCommentEntity feedComment;private FeedEntity feedEntity;@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);setContentView(R.layout.trend_list);mContext = TrendActivity.this;ShareSDK.initSDK(getApplicationContext());initUtils();initView( );initListeners();EventBus.getDefault().register( this );start =0;TrendHttpRequest.getTrendFromWebByPage(user.getId()+"", start);}private void initListeners() { mListView.setPullLoadEnable(true);mListView.setPullRefreshEnable(true);mListView.setXListViewListener(this);mListView.setAdapter(mAdapter);mListView.setSelection(mAdapter.getCount() - 1);sendButton.setOnClickListener(this); sendContent.setOnFocusChangeListener(this);} private void initView() { mListView = (MsgListView) this.findViewById(R.id.trend_msgsend_list); sendContent = (EditText) this.findViewById(R.id.et_trend_msgsend);sendButton = (Button) this.findViewById(R.id.b_trend_msgsend_send); inputLayout = (LinearLayout) findViewById(R.id.ll_trend_msgsend_inputBar);mListView.setAdapter(mAdapter);} private void initUtils() { String userInfo = PrefInfoUtils.getUserInfo(mContext); user = JsonParser.parseDateJson(userInfo, UserEntity.class);mDataList = new ArrayList<FeedAllEntity>();mAdapter = new TrendAdapter(mContext);mAdapter.setCommentListener(this);mAdapter.setZanListener(this);mAdapter.setmDataList(mDataList);mAdapter.setToTrendCreateListener(this);mAdapter.setForwordListener(this);} @Overridepublic void onRefresh() { start =0; mListView.setPullLoadEnable(true);mListView.setPullRefreshEnable(true);TrendHttpRequest.getTrendFromWebByPage(user.getId()+"",start);}@Overridepublic void onLoadMore() { start += defaultPageNum;TrendHttpRequest.getTrendFromWebByPage(user.getId()+"", start);}// textView//commentListener.onCommentClick(true, feedComment, feed);//button//commentListener.onCommentClick(false, null, feed);@Overridepublic void onClick(View v) { switch (v.getId()) {case R.id.b_trend_msgsend_send: { String content = sendContent.getText().toString();InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);imm.hideSoftInputFromWindow(sendContent.getWindowToken(), 0);inputLayout.setVisibility(View.GONE);if (mAdapter.getmDataList().contains(new FeedAllEntity(feedEntity, null, null,null))) {for (FeedAllEntity feedall : mAdapter.getmDataList()) {if (feedall.equals(new FeedAllEntity(feedEntity, null,null, null))) {FeedCommentEntity feedc = new FeedCommentEntity();feedc.setFeedId(feedEntity.getId());feedc.setUserAId(user.getId());feedc.setUserANickname(user.getNickName());feedc.setUserBId(isReply ? feedComment.getUserAId(): feedEntity.getUserFrom());feedc.setUserBNickname(isReply ? feedComment.getUserBNickname() : feedEntity.getUserNickname());feedc.setContent(content);feedc.setParentId(isReply ? feedComment.getId() : 0);feedc.setInsertTime(new Date());feedc.setLastUpdateTime(new Date());if (feedall.feedComments == null) {List<FeedCommentEntity> feedComments = new ArrayList<FeedCommentEntity>();feedall.feedComments = feedComments;}feedall.feedComments.add(feedc);TrendHttpRequest.postTrendFeedComment(feedc);mAdapter.notifyDataSetChanged();}}}}break;default:break;}}public void onEventMainThread(RequestEvent requestEvent){if(requestEvent instanceof TrendHttpEvent){TrendHttpEvent event = (TrendHttpEvent) requestEvent;switch(event.status){case HTTP_NONE:mListView.stopRefresh(); mListView.stopLoadMore();mListView.setPullLoadEnable(false);break;case HTTP_START:{mListView.stopRefresh(); mListView.stopLoadMore();List<FeedAllEntity> list = event.mDataList; FeedEntity feedUser = new FeedEntity(); feedUser.setUserFrom(user.getId()); feedUser.setUserNickname(user.getNickName()); feedUser.setUserIcon(user.getPhoto()); list.add(0, new FeedAllEntity(feedUser, null, null,null)); mAdapter.setmDataList(list); mAdapter.notifyDataSetChanged(); }break;case HTTP_SUCCESS: { mListView.stopRefresh(); mListView.stopLoadMore(); List<FeedAllEntity> list = event.mDataList; mAdapter.addDataList(list); mAdapter.notifyDataSetChanged(); } break;default:break;}}}@Override public void onDestroy() { EventBus.getDefault().unregister( this ); super.onDestroy(); } @Overridepublic void onFocusChange(View view, boolean hasFocus) { if (!hasFocus) inputLayout.setVisibility(View.GONE); elseinputLayout.setVisibility(View.VISIBLE); }@Overridepublic void onCommentClick(boolean isReply, FeedCommentEntity feedComment,FeedEntity feedEntity) { this.isReply = false;this.feedComment = null;this.feedEntity = null; inputLayout.setVisibility(View.VISIBLE); ((InputMethodManager)getSystemService(INPUT_METHOD_SERVICE)).toggleSoftInput(0,InputMethodManager.HIDE_NOT_ALWAYS);sendContent.setFocusable(true);sendContent.requestFocus(); this.isReply = isReply;this.feedComment = feedComment;this.feedEntity = feedEntity; }@Overridepublic void onZanClick(FeedEntity feedEntity) { if (mAdapter.getmDataList().contains(new FeedAllEntity(feedEntity, null, null,null))) {for (FeedAllEntity feedall : mAdapter.getmDataList()) {if (feedall.equals(new FeedAllEntity(feedEntity, null,null, null))) { FeedZanEntity feedz = new FeedZanEntity(); feedz.setFeedId(feedEntity.getId());feedz.setUserId(user.getId());feedz.setUserNickname(user.getNickName());feedz.setInsertTime(new Date());feedz.setLastUpdateTime(new Date());if (feedall.feedComments == null) {List<FeedCommentEntity> feedComments = new ArrayList<FeedCommentEntity>();feedall.feedComments = feedComments;}if (!feedall.feedZans.contains(feedz)) {feedall.feedZans.add(feedz);}else{feedall.feedZans.remove(feedz);}TrendHttpRequest.postTrendFeedZan(feedz);mAdapter.notifyDataSetChanged();}}}}@Overridepublic void onToTrendCreateClick(View view) { Intent intent = new Intent(TrendActivity.this, TrendCreateActivity.class); startActivity(intent);}@Overridepublic void onForwordClick(List<FeedPicEntity> feedPics,FeedEntity feedEntity) {OnekeyShare oks = new OnekeyShare();oks.setTitle("[来自fitnesschat]");oks.setText("[来自fitnesschat]" + feedEntity.getContent()); // 应用通过审核后才能分享网络图片/*if (feedPics.size() > 0) {String [] strArr = new String [feedPics.size()];for (int i =0 ; i<feedPics.size(); i++) {strArr[i] = feedPics.get(i).getPicLink();}oks.setImageUrl(strArr[0]); }*/oks.show(mContext);}}
捐助开发者
在兴趣的驱动下,写一个免费
的东西,有欣喜,也还有汗水,希望你喜欢我的作品,同时也能支持一下。 当然,有钱捧个钱场(支持支付宝和微信 以及扣扣群),没钱捧个人场,谢谢各位。
个人主页:http://knight-black-bob.iteye.com/
谢谢您的赞助,我会做的更好!
更多相关文章
- Android(安卓)获取最新图片
- 关于Android(安卓)Studio安装完后activity_main.xml前几行报错的
- 科普篇
- android 通过webservice方式向服务器上传图片
- android studio 开发 cordova plugin(组件)的 helloWorld
- Error: Could not find gradle wrapper within Android(安卓)SDK
- Android平台上利用opencv进行图像的缩放
- Android(安卓)异步获取网络图片并处理图片Out Of Memory 内存溢
- AndroidStudio 使用技巧:无法删除 Android(安卓)Emulator 解决方