MCDonald Blog

想写点东西

Wechatserver

服务器的配置

服务器地址

https://github.com/donal-tong/wechat4server

包括源代码及数据库脚本放在dump文件夹里

1、根据sql脚本创建需要的数据库hcapi,然后命令行执行脚本,这个不多说。

2、用myeclipse import项目,(如果发现缺少jar,请自行到群共享下载jar),需要更改的文件只有一个 persistence.xml,其实就是数据库的配置文件,更改username及password

至此服务器端的源码配置完成

Openfire配置

openfire地址

http://www.igniterealtime.org/projects/openfire/

以Mac为例,openfire安装成功后会出现在系统偏好设置,openfire的配置需要已有数据库的配置,这里已mysql为例,并且是需要已创建了一个openfire的db,若对mysql安装及配置有问题可以参考 http://www.cnblogs.com/xiaodao/archive/2013/04/04/2999426.html

配置openfire服务器

1、设置语言,选中文

2、服务器设置,域填入 wechat.com 端口默认,需要选择blowfish(服务器需要),key填入4H709fjyRIPOVvK

3、数据库设置,默认标准

4、数据库连接,选择mysql,数据库url为jdbc:mysql://localhost:3306/openfire?useUnicode=true&characterEncoding=UTF-8&characterSetResults=UTF-8,注意openfire以存在用户名密码都是自行输入

5、特性设置,默认初始

6、设置openfire服务器管理员的帐号和密码,默认是admin,可以选择跳过

至此openfire配置好

另外这里检查一下passwordKey有没有设置,如果没有可以在底部位置添加,然后重启openfire

运行服务器及openfire测试

服务器运行需要tomcat配合,请自行安装tomcat

编译通过以后,在tomcat里会有wechat的一个文件夹

另外需要建立一个res的文件夹且放一个default.png的图片,其中res是存放上传的图片

最后就可以用客户端去测试了

客户端介绍 http://donal-tong.github.io/blog/2014/03/01/xmpp4android1/

ListView or GridView for ScrollView

ScrollView嵌套ListView或者是GridView的结构,Google公司不建议一起使用,但是看看下面这个设计(其中分类上面还有广告位,整个页面能够上下滑动):

如果用layout来做,这是需要写12个button,但是如果以后这些类别需要从api获取再显示的话,用layout的方法明显不够灵活,因此就会想到用Gridview来实现。

但是由于Gridview或者Listview在ScrollView里面,高度都是显示不完整的,那么需要怎么解决?

前面一篇文章提到可以单独计算ListView的高度,但是这个有点不好的地方就是ListView的item只能用LinearLayout,这个可以返回阅读。

那么现在介绍另外一个方法:自定义可适应ScrollView的ListView或者Gridview,以Gridview为例

public class GridViewForScrollView extends GridView{ public GridViewForScrollView(Context context) { super(context); } public GridViewForScrollView(Context context, AttributeSet attrs) { super(context, attrs); } public GridViewForScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST); super.onMeasure(widthMeasureSpec, expandSpec); }}

其中重点就是在onMeasure方法

int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);

接下来直接用GridViewForScrollView即可

Picasso and Android-Universal-Image-Loader

picasso

Picasso http://square.github.io/picasso/Square的开源项目之一

最大特点就是你只需要一句代码:

Picasso.with(context).load("http://i.imgur.com/DvpvklR.png").into(imageView);

缓存什么的设置基本可以忽略了

另外的一些诸如裁剪图片:

Picasso.with(context) .load(url) .resize(50, 50) .centerCrop() .into(imageView)

同样Picasso也支持Resources, assets, files, content providers的加载

Picasso.with(context).load(R.drawable.landing_screen).into(imageView1);Picasso.with(context).load(new File(...)).into(imageView2);

Android-Universal-Image-Loader

Android-Universal-Image-Loader https://github.com/nostra13/Android-Universal-Image-Loader

特点

多线程加载图片

尽可能多的配置选项(线程池,加载器,解析器,内存/磁盘缓存,显示参数等等)

图片可以缓存在内存中,或者设备文件目录下,或者SD卡中

可以添加图片加载监听器

可以自定义显示每一张图片时都带不同参数

支持Widget

Android 2.0以上支持

使用

1、初始化imageloader,这个方法需要在application的create调用

public static void init(Context context) { ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context) .threadPriority(Thread.NORM_PRIORITY - 2) .denyCacheImageMultipleSizesInMemory() .discCacheFileNameGenerator(new Md5FileNameGenerator()) .tasksProcessingOrder(QueueProcessingType.LIFO) .writeDebugLogs() // Remove for release app .build(); ImageLoader.getInstance().init(config);}

2.配置显示的options

DisplayImageOptions displayOption = new DisplayImageOptions.Builder().bitmapConfig(Bitmap.Config.RGB_565).showImageOnLoading(R.drawable.avatar_placeholder).showImageForEmptyUri(R.drawable.avatar_placeholder).showImageOnFail(R.drawable.avatar_placeholder).cacheInMemory(true).cacheOnDisc(true).imageScaleType(ImageScaleType.IN_SAMPLE_POWER_OF_2) .displayer(new BitmapDisplayer() { @Override public void display(Bitmap bitmap, ImageAware imageAware, LoadedFrom loadedFrom) { imageAware.setImageBitmap(bitmap); }}).build();

3.加载到view

ImageLoader.getInstance().displayImage(model.avatar, cell.avatarImageView, displayOption);

根据url获取已读的图片文件

File file1 = DiscCacheUtil.findInCache(card.avatar, imageLoader.getDiscCache());

Android WebView上传文件

需要的变量

private ValueCallback<Uri> mUploadMessage;private final static int FILECHOOSER_RESULTCODE = 1;private final static int CAMERA_RESULTCODE = 2;private Uri outputFileUri;

在WebChromeClient里添加

public void openFileChooser( ValueCallback<Uri> uploadMsg, String acceptType ) { mUploadMessage = uploadMsg; QYWebView.this.openImageIntent();} // For Android < 3.0public void openFileChooser( ValueCallback<Uri> uploadMsg ) { openFileChooser( uploadMsg, "" );}// For Android > 4.1public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture){ openFileChooser( uploadMsg, "" );}

onActivityResult处理

if(requestCode==FILECHOOSER_RESULTCODE) { if (null == mUploadMessage) return; Uri result = intent == null || resultCode != RESULT_OK ? null: intent.getData(); mUploadMessage.onReceiveValue(result); mUploadMessage = null; } if(requestCode==CAMERA_RESULTCODE) { if (null == mUploadMessage) return; outputFileUri = outputFileUri == null || resultCode != RESULT_OK ? null: outputFileUri; mUploadMessage.onReceiveValue(outputFileUri); mUploadMessage = null; }

体验

在我看来这样的上传方式用户体验相当不友好,特别是在上传图片时,如果图片比较大并且web前端没有进行压缩的话,那么上传速度达到龟速甚至上传失败,可想而之用户对此的烦躁心情,对你的产品大打折扣了。

我的建议还是上传文件模块还是使用native,本地压缩后上传。

ps:有草稿箱的设计更好!!

ListView嵌套ListView遇到的问题

Listview嵌套会造成的问题主要是子listview的高度错误导致内容不能正常显示完,解决这个问题,我个人第一个想法就是重新计算子listview的高度,代码如下:

private void setListViewHeightBasedOnChildren(ListView listView) { if(listView == null) return; ListAdapter listAdapter = listView.getAdapter(); if (listAdapter == null) { return; } int totalHeight = 0; for (int i = 0; i < listAdapter.getCount(); i++) { View listItem = listAdapter.getView(i, null, listView); listItem.measure(0, 0); totalHeight += listItem.getMeasuredHeight(); } ViewGroup.LayoutParams params = listView.getLayoutParams(); params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1)); listView.setLayoutParams(params); }

父listview的adapter中getview方法调用

RelationAdapter relationAdapter = new RelationAdapter(context, model.relations);cell.xlistView.setAdapter(relationAdapter);setListViewHeightBasedOnChildren(cell.xlistView);

注意事项:

Adapter中getView方法返回的View的必须由LinearLayout组成,因为只有LinearLayout才有measure()方法,如果使用其他的布局如RelativeLayout,在调用listItem.measure(0, 0);时就会抛异常。

效果图:

xmpp4Android 第一期

仿微信基本功能,基于XMPP服务器的即时通信以及交友客户端。

代码的功能如下

1.用户登录,注册

2.登陆并连接XMPP服务器

3.查找最新注册用户:(下拉刷新 上拉翻页)

4.点击某个用户即可对他发送消息,带聊天记录(下拉查看消息的loading没做)

5.首页显示收到的和发送的所有消息,按时间排序

源代码

项目代码

library代码

QQ群 293158074