用树莓派2代打造智能家庭路由
Posted on February 26, 2015
| 1 minutes
| 128 words
家里的宽带上下行都有10Mbps了吧?除了可以BT下载外还能让你的移动设备在外的时候也能科学上网。
区别于在海外架设VPN服务:
国内和大部分国外网站都可以直连而不降低速度;不像海外VPN所有流量(国内和国外网站)都要经过海外服务器,速度有一定的延迟 这个方案代理可以使用免费的Goagent服务;或低成本的ssh帐号;而租用海外VPS服务器自建服务或购买VPN帐号费用较高些; 利用的是家里的宽带,只有树莓派的硬件成本,没有主机托管成本; 假设家里的路由器IP地址为:192.168.1.1,树莓派2的IP地址为:192.168.1.3,以下是需要安装和设置步骤。
PPTP和L2TP VPN Server 首先在树莓派上安装和设置VPN服务器,移动设备就可以通过运营商网络连接回家里的树莓派(iPhone和Android都内置了PPTP和L2TP客户端),这样移动设备将以树莓派为路由访问网站,通过一些设置我们可以让树莓派提供科学上网服务。
关于PPTP和L2TP VPN设置和安装可以参考: http://hugozhu.myalert.info/2013/03/01/setup-l2tp-pptp-openvpn-on-ubuntu.html
但在树莓派上安装L2TP时不能直接apt-get install openswan,需要手动下载来安装,原因是因为最新的版本在协议上有些不兼容:
wget http://snapshot.raspbian.org/201403301125/raspbian/pool/main/o/openswan/openswan_2.6.37-3_armhf.deb sudo dpkg -i openswan_2.6.37-3_armhf.deb 假设VPN服务端的local ip我们设置为192.168.3.1,PPTP客户端IP分配区间为:192.168.3.200~192.168.3.210,L2TP 客户端IP分配区间为:192.168.3.100~192.168.3.110,我们可以通过iptables对IP来源为192.168.3.0/24网段的流量做特殊的处理以达到科学上网的目的。
完成这一步后,需要在路由器上设置端口转发,使得使用运营商网络如移动4G的手机可以通过PPTP或L2TP连到树莓派上。
PPTP需要设置的端口转发 - tcp: 1723
L2TP需要设置的端口转发 - tcp: 50, udp: 500,4500,1701
两种VPN服务相比较:PPTP拨号速度比较快,但是不安全;L2TP有加密,相对安全。
Redsocks2 redsocks2是一个透明TCP代理,其实现使用了libevent库,性能较好,其最大的特点是如果目标IP可以直连则不会转发流量给加密代理,如果IP不能直连(通过连接超时判断)则会将流量转发给加密代理。这样可以将最少的流量转发到代理上,访问一般的国外网站如yahoo.com也不会经过代理而减速,在配置方面则做到了零配置,不需要手工维护网站名单。代理也能支持很多中类型,如socks5, shadowsocks, goagent, http-proxy等,redsocks2安装和配置可以见链接: http://github.com/hugozhu/redsocks
这里我们假设redsocks2的端口使用12345
iptables 使用iptables我们可以将VPN客户端192.168.3.0/24的流量转发到redsocks5的端口12345
sudo iptables -F sudo iptables -X sudo iptables -t nat -F sudo iptables -t nat -X sudo iptables -t nat -A PREROUTING -s 192.168.3.0/24 -p tcp --dport 80 -j REDIRECT --to-ports 12345 #转发VPN客户端的HTTP流量到端口12345 sudo iptables -t nat -A PREROUTING -s 192.
[Read More]零佣金的券商靠什么赚钱?
Posted on February 10, 2015
| 1 minutes
| 16 words
最近一家叫Robinhood的创业公司推出了零佣金的股票交易服务公测,用户可以通过iOS上的专用App交易。
这家公司的两个创始人斯坦福大学毕业后去了纽约给华尔街的大型股票经济公司做交易系统,做了几年后突然有一天发现券商公司对每一笔交易付出的成本微乎其微,但要收取每个客户多达10美金的佣金。。。于是他们毅然决定辞职,回到硅谷创业去了。
公司打出的口号是就是零佣金,如果你交易的资金来源于自己,那么买入和卖出交易,以及银行转入和转出(不包括电汇)都是免费的。
零佣金对资金不那么充裕的年轻人来说非常有吸引力。那么问题来了,这家公司靠什么赚钱呢?
交易过股票的人大概都知道,券商会提供融资服务给流动资金不充足的投资者,融资交易(Securities Margin Trading)就是投资者以资金或证券作为质押,向券商借入资金用于证券买卖,并在约定的期限内偿还借款本金和利息。相应的还有融券服务,融券交易是投资者以资金或证券作为质押,向券商借入证券卖出,在约定的期限内,买入相同数量和品种的证券归还券商并支付相应的融券费用。所以Robinhood首先可以通过融资融券服务盈利;
对于投资者在Robinhood账户里的未购买股票的闲余资金,Robinhood可以通过金融市场获得一部分利息收入;
提供收费接口给小型的量化和对冲基金;
目前Robinhood已经完成了千万美元的风险投资,现阶段提供颠覆性的交易体验,吸引更多年轻的新投资者,赢得用户的信任显然更为重要。用户多了,盈利就不是问题了。。。
App界面
创始人
参考文档
- http://techcrunch.cn/2014/09/25/robinhood-stock-app/
- https://robinhoodapp.zendesk.com/hc/en-us/articles/202853769-How-does-Robinhood-make-money-
- http://baike.baidu.com/view/431144.htm?fromtitle=融资融券&fromid=1628138&type=syn
使用Gradle生成包含所有依赖库(.jar或.aar)的aar包
Posted on November 5, 2014
| 1 minutes
| 145 words
Android Library项目中如果使用Android Gradle plugin打aar包,通过maven依赖的库,或者是local依赖的aar都不会包含在生成的aar包里,如果项目是发布一个SDK,为了方便开发者使用,我们倾向于生成一个包含所有依赖库以及.so等文件的aar包。
通过反复研究和测试,以下Gradle脚本能满足需求,如果需要对代码运行ProGuard混淆,则需要使用Gradle 2.1
方法是为项目增加一个sub project(如pkg_project)专门用于打包,该项目中build.gradle内容如下:
apply plugin: 'java' version = 1.0 buildscript { repositories { mavenCentral() } dependencies { classpath 'com.android.tools.build:gradle:19.1.0' } } repositories { mavenCentral() } dependencies { compile project(':<your_library_project>') //此处填写需要打包的Android Library Project name } task sync_jars() << { //把所有依赖的.jar库都拷贝到build/aar/libs下 copy { into buildDir.getPath() +"/aar/libs" from configurations.compile.findAll { it.getName().endsWith(".jar") } } } task sync_aars(dependsOn:':<your_library_project>:assembleRelease') << { //把所有依赖的.aar库里包含的classes.jar都拷贝到build/aar/libs下,并重命名以不被覆盖 def jar_name def aar_path def dest_dir = buildDir.getPath()+"/aar" configurations.compile.findAll { it.
[Read More]常用Linux命令
Posted on September 4, 2014
| 1 minutes
| 3 words
拷贝文件
如果想事实看到拷贝的速度可以用rsync -aP
简单手机应用同步协议设计和实现
Posted on August 27, 2014
| 2 minutes
| 354 words
版本:Ver 0.3
在手机上我们需要持久化应用的一些数据(典型的如本地的设置信息),同时又希望能重装应用或换一台手机登录后能把这些数据再同步回来。业界有SyncMl标准,覆盖的功能很完善,正因为要保证兼容性,开源的实现都较重。如何借鉴这个标准自己来实现一个多端双向同步可扩展的功能呢?
App使用同步协议可以将原本必须在线操作的功能(如:删除一个联系人,修改一个联系人的备注信息)也可以在断网情况下完成。
我们假设一些前提:
同一时刻只有一端(iPhone,iPad或其他移动设备)能和服务器同步; 客户端和服务端的时间一致或误差较小;可在长连建立时通过协议记录时间差 客户端保存全量数据(对于客户端只保存部分数据的情况后面再做讨论); 应用场景 通讯录同步 最近联系人 App客户端设置 最近会话列表 黑名单 群设置 群成员 用户的一些设置和开关 名词解释 LCID - Local Unique Identifiers, 客户端生成的记录ID,客户端唯一; GUID - Global Unique Identifiers, 服务端生成的记录ID,全局唯一; Anchor - 同步锚点,可以使用递增的序列号或时间戳来表示,用来发现两端数据变化的部分; Session - 同步会话,由客户端发起,Session Id唯一。 客户端表设计 每条记录包含两个同步用的字段:
status - 用来标识记录的状态
Status 含义 0 本地新增 -1 标记删除 1 本地更新 9 已同步 anchor - 用来记录服务端同步过来的时间戳。
服务端表设计 modified - 记录在服务端的修改时间
双向同步流程示例 1. Client 增加2条记录 id key value status modified anchor 1 Foo Bar 0 1 0 2 Hello World 0 2 0 客户端新增记录时,需要将Status设为0
[Read More]使用Gradle生成一个App的不同版本,且可以同时安装在一个手机上
Posted on August 3, 2014
| 1 minutes
| 138 words
背景 开发一个App一般会生成内测版和正式版,甚至还会有不同渠道的版本,不同版本的配置可能会不一样,比如内测版会需要记录完整的日志。
Android手机对于同样的Application Id的App只能安装一个版本,如果我们需要同时安装内测版和正式版,就必须修改其中一个版本的Application Id。
解决方案 Gradle支持buildTypes和productFlavors两种定制方法,这里只介绍通过buildType的解决方案。通过productFlavors则可有效解决渠道包,arm,x86等分平台以及付费版和广告版的打包问题。
修改debug版的包名 配置如下:
android { buildTypes { release { ... } debug { applicationIdSuffix '.debug' ... } } } 修正资源文件里的包名 如果你的项目里使用了自定义的View,且有自定义的属性时,会需要修正一下xml命名空间里的包名。
android.applicationVariants.all { variant -> def buildType = variant.buildType def encoding = java.nio.charset.Charset.defaultCharset().toString() if (buildType.applicationIdSuffix) { def defaultPackageId = variant.packageName.replaceAll(buildType.applicationIdSuffix,'') variant.mergeResources.doLast { def dir = file("${buildDir}/intermediates/res/${variant.dirName}/layout") dir.listFiles().each { f-> String content = f.getText(encoding) content = content.replaceAll("res/"+defaultPackageId, "res/"+variant.packageName) f.write(content, encoding) } } } } 定制APK的应用名称 如果同时安装两个版本,那么最好能从应用名称上来区别一下,一般我们在AndroidManifest.
[Read More]安装第三方App到电视盒子
Posted on July 26, 2014
| 1 minutes
| 19 words
安装第三方App方法1
- 准备一个U盘,注意用FAT格式(Windows能读写就OK)
- 将需要安装的App下载到U盘,文件后缀名必须是.apk
- 将U盘插入电视盒子,然后通过盒子自身带的文件管理App安装:如Magic Box:应用--> 本地播放,进入后选中U盘上的.apk文件即可安装
安装第三方App方法2
- 如果盒子不带USB盘,还可以用adb远程安装
- adb connect <your_magic_box_ip>
- adb install <you_app_to_install>.apk
直播和回放App
- 在电脑上用浏览器下载:http://app.shafa.com/shafa.apk 到U盘
- 按方法1安装好后,在“应用“中找到“沙发管家”
- 启动“沙发管家”,安装直播App:如“龙龙直播”,也有支持回放的App,如“电视猫视频”等。
Gradle的Properties
Posted on July 23, 2014
| 1 minutes
| 173 words
问题背景 团队一起在开发一个Android项目,工程师有的使用Eclipse,有个使用Intellij IDEA,有的使用Android Studio。每个人安装的Android SDK build-tools可能都不一样,有的是19.0.3,有的是19.1.0,不同版本的build-tools对Gradle Plugin也有相应的要求,如19.0.3对应的是com.android.tools.build:gradle:0.10.+,19.1.0对应的是com.android.tools.build:gradle:0.12.+,下面是一个典型的build.gradle配置文件。
buildscript { repositories { mavenCentral() } dependencies { classpath 'com.android.tools.build:gradle:0.10.+' } } apply plugin: 'android-library' android { compileSdkVersion 19 buildToolsVersion 19.0.3 defaultConfig { minSdkVersion 8 targetSdkVersion 19 } } 在合作开发中遇到的一个尴尬的问题是,IDEA最新版还不能很好的支持Gradle Plugin 0.12+,而Android Studio最新版则要求使用0.12+。大家又共用一个Git仓库。可能的解决方案是,从Git checkout出来的项目需要有一个基础的版本号,但是开发者可以在本地通过一处文件(不check in到git)来重载版本号。
解决方案 Gradle支持三种Properties, 这三种Properties的作用域和初始化阶段都不一样,下面分别列出了其部分特点。:
System Properties:
可通过gradle.properties文件,环境变量或命令行-D参数设置 2. 可在setting.gradle或build.gradle中动态修改,在setting.gradle中的修改对buildscript block可见; 所有工程可见,不建议在build.gradle中修改 多子工程项目中,子工程的gradle.properties会被忽略掉,只有root工程的gradle.properties有效; Project Properties:
可通过gradle.properties文件,环境变量或命令行-P参数设置,优先级是: 可在build.gradle中动态修改,但引用不存在的project properties会立即抛错 动态修改过的project properties在buildscript block中不可见 Project ext properties:
可在项目的build.gradle中声明和使用,本工程和子工程可见 不能在setting.gradle中访问 如果有多处设置,加载次序如下(注意:gradle 2.0是这样的, 1.10~1.12有bug), 后面的覆盖前面的设置
[Read More]Android异步编程
Posted on June 29, 2014
| 1 minutes
| 113 words
Android的线程和内存模型 Android操作系统在boot后,会启动一个Zygote(受精卵)进程,Zygote进程负责创建大部分应用程序进程。Zygote进程启动加载核心程序库和数据结构到内存后会创建一个Dalvik虚拟机(DVM)进程--SystemServer,此进程会包含大部分的系统服务(包括管理Activity的服务ActivityManagerService),SystemServer初始化后,Zygote进程会侦听本地的socket端口, 等待进一步的指令。当新的app被启动时,Zygote会为这个app创建一个DVM—-直接fork出一个子进程,这种架构的好处是同时启动多个App时,多个App进程可以访问共享内存。
Android App的进程也是一个DVM,内部有许多线程在执行,比如,主UI线程(Main Thread),垃圾回收线程等。其中主UI线程负责执行我们写的应用代码。对于只做很少的I/O操作或耗时操作的App,单一线程开发模式问题不大,但是如果有大量IO或者CPU计算的任务,我们就必须在其他线程内完成了。
因为主UI线程需要根据硬件刷新率[^3]同步用户界面的重绘。手机应用体验流畅要求界面帧率[^3]达到每秒60,也就是说每16.67毫秒就需要重绘一帧,这意味着如果我们在主线程上执行的任务超过16毫秒,就会出现丢帧现象,也就是界面会开始变卡。。。
Android异步执行任务的方法有以下几种:
AsyncTask AsyncTask是最常用的异步方法,功能结构设计的也很丰富,给使用者足够的控制,使用上主要是将异步执行的任务放在下面方法里。
protected Result doInBackground(Params... params) 然后调用.execute(params)方法即可。
AsyncTask的执行逻辑在API Level 3只能串行执行, 在API Level 4改成了最多128个线程的线程池执行,API Level 11则改成了缺省所有的AsyncTask是在一个线程中顺序执行的,这样可以保证执行和提交的次序一致,如果希望能并发的执行,可以用下面的方法在线程池内执行:
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params); AsyncTask.THREAD_POOL_EXECUTOR是ThreadPoolExecutor的一个实例,配置是最少5个线程,最多128个。如果需要自己来配置线程池大小,你可以传递自己配置的一个实例到上述方法。
使用AsyncTask需要注意的几个问题:
碎片化问题 因为不同版本的Android AsyncTask缺省执行逻辑并不一样,可能在不同机型上表现不一致。如果要自己控制AsyncTask的并发度,解决这个问题的建议是复制Android SDK的AsyncTask源码自己实现一个AsyncTask。
Activity生命周期问题 Activity可能早于AsyncTask执行完被销毁,如果AsyncTask还继续执行,有可能会浪费资源,并且如果AsyncTask里引用了Activity或部分的View Hierarchy,还会造成引用的对象不会被垃圾回收而引起内存泄漏。通常AsyncTask会定义为Activity的一个匿名inner class,这会建立一个隐式的引用到Activity。
解决的方法是:
在Activity里的onPause方法里及时取消不需要再执行的AsyncTask(这种方法在切换到横屏时会重启异步任务,有点浪费) 更好的是使用retained headless fragment来解决生命周期问题,具体演示代码见参考链接 Async比较合适的是较短的(1,2秒),CPU密集计算或读写文件等阻塞IO操作。耗时较长的网络调用用Async不是最合适的。
Handler & HandlerThread Handler的异步编程是基于消息队列模型的。执行任务的线程称之为Looper线程,其他线程则将需要异步执行的任务发送给Looper线程–插入其消息队列,方法有:post(较方便使用,但每次需要创建新对象)或sendMessage(较高效,复用消息实例,适合执行大量类似的异步任务)
Looper Looper和它的名字意思一样就是Looper线程会永远循环,当没有消息的时候,Looper线程(消费者)会使用(Object.wait)方法等待其他线程(生产者)插入新的任务消息,这时候其他线程(Object.notify)
Android的主线程其实就是一个Looper线程。
需要注意的是,使用Handler和AsyncTask一样,要注意匿名inner class对Activity的隐式引用而造成内存泄漏,所以使用的时候要记得清理;
解决方法是使用对使用的Activity中的View对象用Weak Reference,并处理当View对象为null的情况。
Handler适合更长一点的(>2秒)的异步任务处理。
Loader Loader在Android编程框架中被广泛用于后台加载数据(从文件,数据库甚至网络)。
AsyncTaskLoader 具体的Loader实现。
CursorLoader 用户数据库数据后台加载。
Loader在使用上比较大的优势是和Activity的部分解耦,更见到的生命周期管理。
IntentService IntentService是Service的一个实现类。其内部实现包含了一个HandlerThread,当任务提交给IntentService时,会被加到队列并顺序处理。
public class MyIntentService extends IntentService { public MyIntentService() { super("thread-name"); } protected void onHandleIntent(Intent intent) { // executes on the background HandlerThread.
[Read More]提高Android开发效率的小贴士
Posted on February 10, 2014
| 1 minutes
| 47 words
查看日志 adb logcat
下面命令将只显示错误日志,和所有Tag=mytag的调试日志,-C 会用不同颜色区分不同级别的日志,但只有Android 4.3以后才支持。
adb logcat [-C] *:E <mytag>:D
远程调试 adb over TCP
首先在手机或Pad上执行以下命令(要求root)
su
setprop service.adb.tcp.port 5555
stop adbd
start adbd
再执行下面命令则可以看到手机的网络地址
在电脑上则执行
adb connect <mobile_phone_ip> 5555
adb shell
安装运行
gradle installDebug && adb shell am start -n com.laiwang.protocol.android/.MainActivity
Over