转载地址:http://www.infoq.com/cn/news/2011/04/xxb-maven-6-gradle

Maven面临的挑战

软件行业新旧交替的速度之快往往令人咂舌,不用多少时间,你就会发现曾经大红大紫的技术已经成为了昨日黄花,当然,Maven也不会例外。虽然目前它基本上是Java构建的事实标准,但我们也能看到新兴的工具在涌现,比如基于Goovy的Gradle,而去年Hibernate宣布从Maven迁移至Gradle这 一事件更是吸引了不少眼球。在此之前,我也听到了不少对Maven的抱怨,包括XML的繁冗,不够灵活,学习曲线陡峭等等。那Gradle是否能够在继承 Maven优点的基础上,克服这些缺点呢?带着这个疑问,我开始阅读Gradle的文档并尝试着将一个基于Maven的项目转成用Gradle构建,本文 所要讲述大概就是这样的一个体验。需要注意的是,本文完全是基于Maven的角度来看Gradle的,因此对于Ant用户来说,视角肯定会大有不同。

Gradle初体验

Gradle的安装非常方便,下载ZIP包,解压到本地目录,设置 GRADLE_HOME 环境变量并将 GRADLE_HOME/bin 加到 PATH 环境变量中,安装就完成了。用户可以运行gradle -v命令验证安装,这些初始的步骤和Maven没什么两样。Gradle目前的版本是1.0-milestone-1,根据其Wiki上的Roadmap,在1.0正式版发布之前,还至少会有3个里程碑版本,而1.0的发布日期最快也不会早于6月份。而正是这样一个看起来似乎还不怎么成熟的项目,却有着让很多成熟项目都汗颜的文档,其包括了安装指南、基本教程、以及一份近300页的全面用户指南。这对于用户来说是非常友好的,同时也说明了Gradle的开发者对这个项目非常有信心,要知道编写并维护文档可不是件轻松的工作,对于Gradle这样未来仍可能发生很大变动的项目来说尤为如此。

类似于Maven的pom.xml文件,每个Gradle项目都需要有一个对应的build.gradle文件,该文件定义一些任务(task)来完成构建工作,当然,每个任务是可配置的,任务之间也可以依赖,用户亦能配置缺省任务,就像这样:

复制代码
defaultTasks 'taskB'  task taskA << {     println "i'm task A" }  task taskB << {     println "i'm task B, and I depend on " + taskA.name }  taskB.dependsOn taskA
复制代码

运行命令$ gradle -q之后(参数q让Gradle不要打印错误之外的日志),就能看到如下的预期输出:

i'm task A i'm task B, and I depend on taskA

这不是和Ant如出一辙么?的确是这样,这种“任务”的概念与用法与Ant及其相似。Ant任务是Gradle世界的第一公民,Gradle对 Ant做了很好的集成。除此之外,由于Gradle使用的Grovvy脚本较XML更为灵活,因此,即使我自己不是Ant用户,我也仍然觉得Ant用户会 喜欢上Gradle。

依赖管理和集成Maven仓库

我们知道依赖管理、仓库、约定优于配置等概念是Maven的核心内容,抛开其实现是否最优不谈,概念本身没什么问题,并且已经被广泛学习和接受。那Gradle实现了这些优秀概念了么?答案是肯定的。

先看依赖管理,我有一个简单的项目依赖于一些第三方类库包括SpringFramework、JUnit、Kaptcha等等。原来的Maven POM配置大概是这样的(篇幅关系,省略了部分父POM配置):

复制代码
   <properties>         <kaptcha.version>2.3</kaptcha.version>     </properties>      <dependencies>         <dependency>             <groupId>com.google.code.kaptcha</groupId>             <artifactId>kaptcha</artifactId>             <version>${kaptcha.version}</version>             <classifier>jdk15</classifier>         </dependency>         <dependency>             <groupId>org.springframework</groupId>             <artifactId>spring-core</artifactId>         </dependency>         <dependency>             <groupId>org.springframework</groupId>             <artifactId>spring-beans</artifactId>         </dependency>         <dependency>             <groupId>org.springframework</groupId>             <artifactId>spring-context</artifactId>         </dependency>         <dependency>             <groupId>junit</groupId>             <artifactId>junit</artifactId>         </dependency>     </dependencies>
复制代码

然后我将其转换成Gradle脚本,结果是惊人的:

复制代码
dependencies {     compile('org.springframework:spring-core:2.5.6')     compile('org.springframework:spring-beans:2.5.6')     compile('org.springframework:spring-context:2.5.6')     compile('com.google.code.kaptcha:kaptcha:2.3:jdk15')     testCompile('junit:junit:4.7') }
复制代码

注意配置从原来的28行缩减至7行!这还不算我省略的一些父POM配置。依赖的groupId、artifactId、 version,scope甚至是classfier,一点都不少。较之于Maven或者Ant的XML配置脚本,Gradle使用的Grovvy脚本杀 伤力太大了,爱美之心,人皆有之,相比于七旬老妇松松垮垮的皱纹,大家肯定都喜欢少女紧致的脸蛋,XML就是那老妇的皱纹。

关于Gradle的依赖管理起初我有一点担心,就是它是否有传递性依赖的机制呢?经过文档阅读和实际试验后,这个疑虑打消了,Gradle能够解析 现有的Maven POM或者Ivy的XML配置,从而得到传递性依赖的信息,并且引入到当前项目中,这实在是一个聪明的做法。在此基础上,它也支持排除传递性依赖或者干脆 关闭传递性依赖,其中第二点是Maven所不具备的特性。

自动化依赖管理的基石是仓库,Maven中央仓库已经成为了Java开发者不可或缺的资源,Gradle既然有依赖管理,那必然也得用到仓库,这当然也包括了Maven中央仓库,就像这样:

repositories {     mavenLocal()     mavenCentral()     mavenRepo urls: "http://repository.sonatype.org/content/groups/forge/" }

这段代码几乎不用解释,就是在Gradle中配置使用Maven本地仓库、中央仓库、以及自定义地址仓库。在我实际构建项目的时候,能看到终端打印的下载信息,下载后的文件被存储在 USER_HOME/.gradle/cache/ 目录下供项目使用,这种实现的方法与Maven又是及其类似了,可以说Gradle不仅最大限度的继承Maven的很多理念,仓库资源也是直接拿来用。

Gradle项目使用Maven项目生成的资源已经不是个问题了,接着需要反过来考虑,Maven用户是否能够使用 Gradle生成的资源呢?或者更简单点问,Gradle项目生成的构件是否可以发布到Maven仓库中供人使用呢?这一点非常重要,因为如果做不到这一 点,你可能就会丢失大量的用户。幸运的是Gradle再次给出了令人满意的答案。使用Gradle的Maven Plugin,用户就可以轻松地将项目构件上传到Maven仓库中:

复制代码
apply plugin: 'maven' ... uploadArchives {     repositories.mavenDeployer {         repository(url: "http://localhost:8088/nexus/content/repositories/snapshots/") {             authentication(userName: "admin", password: "admin123")             pom.groupId = "com.juvenxu"             pom.artifactId = "account-captcha"         }     } }
复制代码

在上传的过程中,Gradle能够基于build.gradle生成对应的Maven POM文件,用户可以自行配置POM信息,比如这里的groupId和artifactId,而诸如依赖配置这样的内容,Gradle是会自动帮你进行转 换的。由于Maven项目之间依赖交互的直接途径就是仓库,而Gradle既能够使用Maven仓库,也能以Maven的格式将自己的内容发布到仓库中, 因此从技术角度来说,即使在一个基于Maven的大环境中,局部使用Gradle也几乎不会是一个问题。

约定优于配置

如同Ant一般,Gradle给了用户足够的自由去定义自己的任务,不过同时Gradle也提供了类似Maven的约定由于配置方式,这是通过 Gradle的Java Plugin实现的,从文档上看,Gradle是推荐这种方式的。Java Plugin定义了与Maven完全一致的项目布局:

  • src/main/java

  • src/main/resources

  • src/test/java

  • src/test/resources

区别在于,使用Groovy自定义项目布局更加的方便:

复制代码
sourceSets {     main {         java {             srcDir 'src/java'         }         resources {             srcDir 'src/resources'         }     } }
复制代码

Gradle Java Plugin也定义了构建生命周期,包括编译主代码、处理资源、编译测试代码、执行测试、上传归档等等任务:

Figure 1. Gradle的构建生命周期

相对于Maven完全线性的生命周期,Gradle的构建生命周期略微复杂,不过也更为灵活,例如jar这个任务是用来打包的,它不像Maven那 样依赖于执行测试的test任务,类似的,从图中可以看到,一个最终的build任务也没有依赖于uploadArchives任务。这个生命周期并没有 将用户限制得很死,举个例子,我希望每次build都发布 SNAPSHOT版本到Maven仓库中,而且我只想使用最简单的$ gradle clean build命令,那只需要添加一行任务依赖配置即可:

build.dependsOn 'uploadArchives'

小结

一番体验下来,Gradle给我最大的感觉是两点。其一是简洁,基于Groovy的紧凑脚本实在让人爱不释手,在表述意图方面也没有什么不清晰的地 方。其二是灵活,各种在Maven中难以下手的事情,在Gradle就是小菜一碟,比如修改现有的构建生命周期,几行配置就完成了,同样的事情,在 Maven中你必须编写一个插件,那对于一个刚入门的用户来说,没个一两天几乎是不可能完成的任务。

不过即使如此,Gradle在未来能否取代Maven,在我看来也还是个未知数。它的一大障碍就是Grovvy,几乎所有 Java开发者都熟悉XML,可又有几个人了解Groovy呢?学习成本这道坎是很难跨越的,很多人抵制Maven就是因为学起来不容易,你现在让因为一 个构建工具学习一门新语言(即使这门语言和Java非常接近),那得到冷淡的回复几乎是必然的事情。Gradle的另外一个问题就是它太灵活了,虽然它支 持约定优于配置,不过从本文你也看到了,破坏约定是多么容易的事情。人都喜欢自由,爱自定义,觉得自己的需求是多么的特别,可事实上,从Maven的流行 来看,几乎95%以上的情况你不需要自行扩展,如果你这么做了,只会让构建变得难以理解。从这个角度来看,自由是把双刃剑,Gradle给了你足够的自 由,约定优于配置只是它的一个选项而已,这初看起来很诱人,却也可能使其重蹈Ant的覆辙。Maven在Ant的基础上引入了依赖管理、仓库以及约定优于 配置等概念,是一个很大的进步,不过在我现在看来,Gradle并没有引入新的概念,给我感觉它是一个结合Ant和Maven理念的优秀实现。

如果你了解Groovy,也理解Maven的约定优于配置,那试试Gradle倒也不错,尤其是它几乎能和现有的Maven系统无缝集成,而且你也能享受到简洁带来的极大乐趣。其实说到简洁,也许在不久的将来Maven用户也能直接享受到,Polyglot Maven在 这方面已经做了不少工作。本文完全基于Maven的视角介绍Gradle这一构建工具的新秀,不过限于篇幅原因,无法深入Gradle的方方面面,例如 Gradle也支持多模块构建,它提供了GUI操作界面,支持Grovvy(理所当然)和Scala项目等等。有兴趣的读者可以自行进一步了解。

关于作者

许晓斌(Juven Xu),国内社区公认的Maven技术专家、Maven中文用户组创始人、Maven技术的先驱和积极推动者,著有《Maven实战》一 书。对Maven有深刻的认识,实战经验丰富,不仅撰写了大量关于Maven的技术文章,而且还翻译了开源书籍《Maven权威指南》,对Maven技术 在国内的普及和发展做出了很大的贡献。就职于Maven之父的公司,负责维护Maven中央仓库,是Maven仓库管理器Nexus(著名开源软件)的核 心开发者之一,曾多次受邀到淘宝等大型企业开展Maven方面的培训。此外,他还是开源技术的积极倡导者和推动者,擅长Java开发和敏捷开发实践。他的 个人网站是:http://www.juvenxu.com

分类: Gradle
posted @ 2014-10-28 16:00 小马歌 阅读(232) | 评论 (0)编辑 收藏
 
1、安装 
    Gradle安装和Maven一样方便,只需要,下载(http://www.gradle.org/downloads )==》解压==》配置环境变量(GRADLE_HOME & PATH),配置好环境变量之后记得使用 source命令使新的环境变量生效。配置成功之后,可以在命令行通过 “gradle -v"验证是否安装成功。 

2、Gradle编译Maven风格的java项目 
    首先,在项目根目录创建"build.gradle"文件,编译java项目需要使用gradle的java插件
Groovy代码  收藏代码
  1. apply plugin: 'java'  
,因为要集成maven的功能,需要添加maven插件
Groovy代码  收藏代码
  1. apply plugin: 'maven'[   
。 
    接着,配置项目的Repository,风格如下
Groovy代码  收藏代码
  1. repositories{  
  2.          mavenCentral();  
  3.     }  
,上面例子使用的是默认的maven的中央库,如果想用自己的本地库,可通过如下方式配置
Groovy代码  收藏代码
  1. def localMavenRepo = 'file://' + new File(System.getProperty('user.home'), '.m2/repository').absolutePath  
  2. repositories {  
  3.     // Use local Maven repo location. We don't need this if we only want to install  
  4.     // an artifact, but we do need it if we want to use dependencies from the local  
  5.     // repository.  
  6.     mavenRepo urls: localMavenRepo  
  7.     mavenCentral()  
  8. }  


    再然后,配置项目依赖的第三方库,配置模板如下:
Groovy代码  收藏代码
  1. dependencies{  
  2.           compile group: '<group-id>',name:'<artifact-id>',version:'<version>'  
  3.      }  
,举个例子,假设项目依赖了4.10版本的junit,那么配置就是
Groovy代码  收藏代码
  1. compile group: 'junit',name:'junit',version:'4.10'  
另外Depencies还可以按如下方式简写
Groovy代码  收藏代码
  1. compile  '<group-id>:<artifact-id>:<version>'  
例子
Groovy代码  收藏代码
  1. compile  'junit:junit:4.10'  


    最后,如何把自己的项目发布到Repository中,
Groovy代码  收藏代码
  1. uploadArchives {  
  2.    repositories {  
  3.        mavenDeployer {  
  4.            repository(url: "file://localhost/tmp/myRepo/")  
  5.        }  
  6.    }   
posted @ 2014-10-28 15:49 小马歌 阅读(899) | 评论 (0)编辑 收藏
 
     摘要: 一、寻找gradle的历程一开始的时候,我们只有一个工程,所有要用到的jar包都放到工程目录下面,时间长了,工程越来越大,使用到的jar包也越来越多,难以理解jar之间的依赖关系。再后来我们把旧的工程拆分到不同的工程里,靠ide来管理工程之间的依赖关系,各工程下的jar包依赖是杂乱的。一段时间后,我们发现用ide来管理项程很不方便,比如不方便脱离ide自动构建,于是我们写自己的ant脚本。再后来,...  阅读全文
posted @ 2014-10-28 15:47 小马歌 阅读(882) | 评论 (0)编辑 收藏
 

MavenVsGradle

版本3  单击查看文档历史记录
创建于: 2009-6-18 下午5:02 作者 Paul Gier - 最后修改:  2010-3-17 下午3:11 作者 Paul Gier

本文比较了两个构建工具:Maven和Gradle,并讨论了各自的优点和缺点。

Maven简介

Maven是一种扫大街的大妈都知道的Java构建工具。 如果你还不知道Maven是神马,可以去这嘎达看看。 Maven提供了一套大多数项目都适用的基本的配置方案。 Maven提供的构建过程可以默认,也可以在有需要时候定制。 这样做的好处是让生成配置文件(POM)变得很简单。 缺点是当涉及到自定义构建流程时,Maven就变得有局限性鸟。

Gradle简介

Gradle 是一个较新的构建工具基于Ant和Groovy。 Gradle提供了一些默认配置方案,比Maven更加灵活。 生命周期相关的一切构建都可以自定义。 有这玩意,你会觉得很爽的

比较

 

Maven使用XML来定义生成脚本。和Ant一样,这是一个安全的选择,因为大多数人都熟悉XML配置。 Gradle构建脚本是用Groovy写的。 用XML优势在于它可以更方便地定义构建逻辑是比较复杂的步骤不仅仅是不变的一系列。 用Groovy的好处就是写起来比XML标签简洁得多。 Groovy的毛病就是熟悉的XML的开发人员比groovy的多,这些爷们必需自己来写复杂的逻辑。

性能

 

一些 非正式的测试 表明Gradle 比Maven性能高不了,甚至还低一点。 让人抓狂的是这俩兄弟都似乎要明显慢于Ant。 使用Maven构建JBoss应用服务器比用Ant构建要多两倍的时间。

(Ant是明显的赢家,Maven和Gradle大约相同)

译者注:使用Gradle,在一个task里写了个循环 调用flex的mxmlc,才编译3个mxml文件,丫的就出现了Java heap space错误了。情何以堪啊

 

依赖配置

 

通常的Maven项目有一个单一的依赖的静态配置, 所以一个项目应该有只有一个单一的Artifact。 简单就是他的优势,但也缺乏弹性。 Gradle在这方面的更灵活。 可以在创建和处理的时候有多套依赖配置。 

(Gradle因为简单性和灵活性获胜,Maven和 Ant/Ivy次之)

 

使用Artifact仓库

 

Maven有自己的单一仓库格式。 Gradle可以使用Ivy仓库和Maven仓库。 部署到Maven仓库是非常容易,Ant和Gradle就需要你多动动脑经了。

(Maven Win,Gradle和Ant/Ivy老二)

 

加载构建系统的组件

 

Maven采取的做法是每个用于构建的组件(编译/jar等​​)都作为一个插件。 每个插件都有它自己的版本和依赖关系树。 Gradle的构建系统组件都是分散的。 Maven插件的优点是在于可以独立更新,无需整个系统更新。Gradle的模型的优点是,编译需要核心组件以外的组件时才下载。

 

Maven和Gradle在这点上都比Ant好。 Ant需要Ivy和一些麻烦的配置来实现。

(Maven和Gradle并列,Ant第二因为它需要更多的设置来加载额外的构建组件)

译者注:少造轮子

 

构建生命周期

Maven提供有限的构建生命周期访问。 插件可以连接到生命周期的特定阶段,而且只有在核心插件执行。 Gradle很容易这方面NB,因为它可以轻松地访问任何生成的一部分,并允许用Groovy代码处理。Ant也可以访问任何一部分构建,但是需要用任务来实现而不是代码,所以还是不如Gradle强大。

(Gradle毫无鸭梨,Ant老二,Maven最渣)

 

翻译至  http://community.jboss.org/wiki/MavenVsGradle
posted @ 2014-10-28 15:43 小马歌 阅读(2840) | 评论 (0)编辑 收藏
 
from:http://code.google.com/p/android-application-plug-ins-frame-work/

介绍

这个框架的初衷,是为了方便让程序模块化、插件化,将一个apk应用拆分为多个apk。
不明白这个插件化、模块化是怎么回事的话,可以看看腾讯微信的安卓客户端中的插件配置。
在这里我会以腾讯微信为例,如何使用这个框架。 (腾讯微信并不是真正的插件化,它是伪的,插件并非与它的主程序分离开,结果就是每次插件的更新,都必须以整个程序的更新为代价)

都能干啥

框架的思想,主要是通过apk清单文件中的sharedUserId属性来吧多个apk融合为单一的dalvik虚拟机,也就是融合为一个进程,这样就变相逾越了android框架中不同apk权限不同无法互通的鸿沟(rpc啦什么的其它的毕竟不如这个来的实在)。
从最简单的皮肤插件到复杂的涉及数据库的拓展功能,从普通activity跳转到把插件的activity转变为view并附加到主程序中的拓展功能,都是可以通过本框架来实现的,当然,本框架只是提供了一种途径,如何编码还得靠自己。
本人能力有限,可能有一些错误、疏漏或者不足之处,请不吝指教,我的博客地址在左下角,或者我的邮箱,都可以联系到我。
ps:下面会以腾讯微信为例,这里声明一下,本人没有对微信安卓客户端进行任意形式的反编译与破解工作,只是看球半天进行简单的猜测而已。

框架结构

本插件框架由三个包组成:

  • org.igeek.android.pluginframework 这个包种类是框架的主要操作类
    1. PluginBuilder 组装插件
    2. PluginDescription 组装用户自定义的插件描述
    3. PluginInvoke 插件功能调用
    4. PluginSearch 查找插件
  • org.igeek.android.pluginframework.annotation 未来可能会考虑使用注解
    1. PluginDescription 用于用户自定义描述类的注解
    2. PluginFeature 用于插件类的注解
    3. PluginMethod 用于插件类方法的注解
  • org.igeek.android.pluginframework.beans 框架内部使用的一些beans
    1. Plugin 插件包
    2. PluginFeature 插件类
    3. PluginFeatureMethod 插件方法
  • org.igeek.android.pluginframework.util 一些工具类
    1. XMLParse 插件包

如何使用

以腾讯微信为例,虽然从表面来看,它是插件化的多种功能的一种集成。但是,这都是虚的,每次更新时你会发现,哪怕一个小小的功能添加,都会让用户更新整个程序,截至目前(2011-12-17),微信让我更新到3.5,修复了一些小bug,增加了1个插件功能,以及其它的小改进,就得让我下载并升级整个程序,6.8m啊。。
在工程开发时,预留插件的使用、管理页面,如:

这是微信的插件浏览页面,所有可暴露在这里的插件都会被列出来

 这是微信的插件管理界面,可以卸载安卓,但这些都是虚的,可能只是把服务关了,并非真正的卸载

主程序(APK)

  • 、主程序清单
首先为工程想好一个名字,并在清单中加入sharedUserId属性,属性值就是想好的那个名字,例如微信:com.qq.weixin
   android:sharedUserId="com.qq.weixin"
  • 、为插件描述写一个类
 这就是插件描述

首先在主程序中单独建立一个包,并写一个类,这个类相当于一个bean,具有相应的插件描述信息的字段,如微信,那么这个bean的字段就有 插件名:漂流瓶 插件logo:那个人头 插件描述:描述信息...

这个类在主程序中不会很多的使用,只会读取框架返回的插件的bean。

  • 、引入本框架的jar包或导入源码

正式编码时,可在任何地方调用框架。具体步骤是这样的
1、查找插件 本框架是根据sharedUserId来查找插件。它首先会根据自身apk的sharedUserId值来查找系统中具有相同属性的包并加载。
  • ��以说,插件apk的sharedUserId值也应与主程序相同
        //首先,就是查找插件
        PluginSearch psearch=new PluginSearch();
        //第一次获得的是简要的插件描述
        List<Plugin>  plugins=psearch.getPlugins(this);
       
        //然后将插件再组装一下
        PluginBuilder pbuilder=new PluginBuilder(this);
        //将用户所定义插件描述融合进去
        plugins=pbuilder.buildPluginsDescrition(plugins);

这样就把所有插件找到手了,很简单吧?

1、调用插件 找到插件后肯定是调用,最简单应用,就是靠Button按钮来调用
比如微信的摇一摇,点了它就触发框架的插件调用
        @Override
        public void onClick(View v) {
                //新建一个插件调用类
                PluginInvoke pi=new PluginInvoke(AndroidPluginFrameworkActivity.this);
       
               
                //这是真正的调用
                //三个参数,第一个是Plugin类型,第二个是PluginFeature,第三个PluginFeatureMethod
                pi.invoke(plug, pf, fm);
               
        }
        });

插件程序(APK)

  • 、插件程序清单

同主程序的清单文件一样,sharedUserId必须有且和主程序的一样 插件的activity的意图过滤描述必须是这样 示例:

 <intent-filter>
                <category android:name="android.intent.category.DEFAULT" />
  </intent-filter>
  • 、插件程序的功能
插件可以包含任意类,如同一个普通的apk工程一样。
但是,向主程序提供调用的类,必须是个activity,方法必须是无返回值的,有且只有一个Context参数,框架会反射这个方法,并将主程序的context句柄传入,也就是,不管你用不用这个context,他都是被框架传入的。
如果主程序规定了描述类,也就是框架中需要PluginDescription来调用的bean,在插件工程中,也必须有主程序这个bean,包名也必须一样。插件程序可以直接继承或者更改这个bean的字段,方便主程序去获取这个插件的描述信息。这种方式,是避过框架,给主程序一种方便。
  • 、插件程序的plugin.xml配置
http://android-application-plug-ins-frame-work.googlecode.com/files/plugin.xml plugin.xml不能改名,必须放在工程的 assets 目录下。
内容大致是这样:
<?xml version="1.0" encoding="UTF-8"?>
<!-- 这个xml配置文件放在插件工程的 assets 目录下 -->


<!-- 插件提供的功能(类) -->
<plugin-features>

        <!-- 描述类,这个是自定义的 -->
        <!-- 这个描述类使用户定义的,在主程序中必须有,插件工程中也必须有,并被继承 -->
        <description name="org.pakage.name.and.description.name"/>
       
        <!-- 这是一个功能(类),必须是activity的子类 -->
        <feature name="org.pakage.name.and.activity.name1">
       
                <!-- 这是一个方法 -->
                <!-- name 方法名 -->
                <method need-context="true" name="methodName1" >描述信息</method>
                <method need-context="true" name="methodName2" >描述信息</method>
               
        </feature>
       
        <feature name="org.pakage.name.and.activity.name2">
                <method need-context="true" name="methodName1" >描述信息</method>
        </feature>
</plugin-features>
按着上面的套路来配置,就很容易了。

最后

上面说的比较泛,最好还是看看示例工程,里面包含了一个主程序和两个插件扩展,总共是4个工程,也就是说,在用户端是4个apkhttp://android-application-plug-ins-frame-work.googlecode.com/files/demo.zip
posted @ 2014-10-28 11:21 小马歌 阅读(233) | 评论 (0)编辑 收藏
 
人工光盘坏道 

目前最新的加密方法,原理是该VCD带防盗圈,这个圈的作用是在光头读盘到防盗圈处时是个坏道,从物理上让光驱读不过去,你会发现光盘可以显示容量,但打开目录却没有任何文件,市面上的无间道2、天地英雄、大块头有大智慧等最新VCD都是采用这种加密方法。

破解方法:

步骤1:首先我们需要CloneCD这个软件,下载地址:天极网下载频道。注意不能使用NERO等其他光驱软件,因为NERO读不过坏道,可能造成死机的情况。

首次运行在Language语言栏内选择SIMP.Chinese,界面显示为中文。点击“文件→读成映像文件”,在弹出的对话框中选择物理光驱的盘符,注意不能选择虚拟盘符。选择后CloneCD会对整个VCD进行扫描,由于制作的是视频镜像,所以选择multimedia audio cd,然后选择镜像文件保存目录,右面已经显示出扫描后光盘的容量、片断、轨道数等一些信息(图3)。

CloneCD将读取的整个光盘内容制作成镜像文件,中途在记录框中出现读取扇区失败的信息,同时光驱中会出现咔咔咔咔的响声音,这个是正常现象。cloneCD能制作镜像的原理就是能真实地按照1∶1 全盘复制CD,不管是否有保护或加密之类,它都会跳过人为设置的坏道把有用部分镜像制作出来。

跳过坏道大概用时两三分钟,视你的光驱读盘能力而定,在显示跳过伪扇区后经过十多分钟就可以把这个光盘制作成镜像文件,最后显示读取完成后在目录下会出现image.img等四个文件。

步骤2:已经得到了的IMG镜像文件,还不能使用其他虚拟光驱工具来打开它,这时你会发现还是一无所获。接下来的工作是提取镜像文件中的视频文件,我们还需要IsoBuster这个工具,下载地址:天极网下载频道运行IsoBuster,点击“file→open image file”来打开image.img文件,在主界面中应该出现光盘的卷标和目录结构,在track 01上右击,选“extract track 01→treat as video onlyextract but filter only m2f2 mpeg video frames(.mpg)”,然后选择文件存放目录,最后经过几分钟的时间就得到了原始的MPG视频文件,用来复制VCD或在PC上观看就任君选择了。
如果以上方法还不能解决,说明加密的是最新的技术,暂时还没破解的方法
posted @ 2014-10-27 09:45 小马歌 阅读(1390) | 评论 (0)编辑 收藏
 
from:http://www.ppst.cc/post_info/1389279044687141000000

  • 标签: android Android andriod 开源项目
posted @ 2014-10-22 19:56 小马歌 阅读(197) | 评论 (0)编辑 收藏
 
     摘要: from:https://typeblog.net/tech/2014/07/22/use-buck-to-build-your-app.htmlbuck 是Facebook推出的一款高效率的Android App/Java项目构建工具,目前仅支持 Unix/Linux 平台。因为它使用多线程编译方式,所以相对于其他的构建工具而言编译时间可以缩短50%甚至更多。buc...  阅读全文
posted @ 2014-10-22 19:34 小马歌 阅读(3671) | 评论 (0)编辑 收藏
 
     摘要: from:http://blog.csdn.net/signmem/article/details/17379427特色MySQL/Galera 是一种多主同步集群,但只限于使用 MySQL/InnoDB 引擎,并具有下面特点同步复制多个主服务器的拓扑结构可以在任意节点上进行读写自动控制成员,自动删除故障节点自动加入节点真正给予行级别的并发复制调度客户连接优势参考下面基于 DBMS 集群的解决方法...  阅读全文
posted @ 2014-10-16 14:18 小马歌 阅读(335) | 评论 (0)编辑 收藏
 

from:http://www.tuicool.com/articles/2UVBba

标签: InnoDB MySQL Percona XtraDB Cluster Percoba XtraDB ClusterPercona Software | 发表时间:2014-01-19 13:02 | 作者:appleboy

percona

本篇文章紀錄安裝 Percona XtraDB Cluster (簡稱 PXC) 及搭配 HAProxy 做分散流量系統,其實在業界已經很常看到 HAProxy + MySQL Cluster Database 解決方案,HAProxy 幫您解決負載平衡,並且偵測系統是否存活,管理者也就不用擔心 MySQL 服務是否會掛掉。本篇會著重於 HAProxy 設定部份,並且紀錄每一步安裝步驟。之前本作者寫過一篇 Galera Cluster for MySQL Multi-master Replication ,也可以參考。今天測試系統都會以 CentOS 為主,各位讀者可以直接開 Amazone EC2 來測試,測試完成再關閉即可。

安裝 Percona XtraDB Cluster

我們會使用官方 Percona 及 EPEL repositories 進行軟體安裝,底下是 Yum 安裝步驟

$ yum -y install Percona-XtraDB-Cluster-server Percona-XtraDB-Cluster-client Percona-Server-shared-compat percona-xtrabackup

如果系統已經有安裝過 MariaDB + Galera ,請務必先移除套件

完成安裝 PXC 套件後,接著設定 my.cnf 設定檔

[mysqld] server_id=1 wsrep_provider=/usr/lib64/libgalera_smm.so wsrep_cluster_address="gcomm://" wsrep_sst_auth=username:password wsrep_provider_options="gcache.size=4G" wsrep_cluster_name=Percona wsrep_sst_method=xtrabackup wsrep_node_name=db_01 wsrep_slave_threads=4 log_slave_updates innodb_locks_unsafe_for_binlog=1 innodb_autoinc_lock_mode=2

再開啟第 2 台或第 3 台 PXC 服務的時候,務必確認第 1 台已經正確開啟成功。上面設定檔是針對第 1 台做設定,之後新增 Node,請務必修改wsrep_cluster_address 填上你想要 Join 的 Cluster Server IP Address,另外每台的 server_id 及 wsrep_node_name 也會不同,請務必注意

第 2 台設定值

server_id=2 wsrep_cluster_address=gcomm://192.168.1.100 # replace this with the IP of your first node wsrep_node_name=db_02

第 3 台設定值

server_id=2 wsrep_cluster_address=gcomm://192.168.1.100 # replace this with the IP of your first node wsrep_node_name=db_03

根據 State Snapshot Transfer (簡稱 SST),我們使用 Xtrabackup ,當新的 Node 連上時,就會開始複製資料到新的 Node 上,成功複製完成,可以看到底下 Log 訊息

140117 11:56:05 [Note] WSREP: Flow-control interval: [28, 28] 140117 11:56:05 [Note] WSREP: Shifting OPEN -> PRIMARY (TO: 678691) 140117 11:56:05 [Note] WSREP: State transfer required:         Group state: 28e87291-da41-11e2-0800-34a03cad54a7:678691         Local state: 28e87291-da41-11e2-0800-34a03cad54a7:678684 140117 11:56:05 [Note] WSREP: New cluster view: global state: 28e87291-da41-11e2-0800-34a03cad54a7:678691, view# 33: Primary, number of nodes: 3, my index: 1, protocol version 2 140117 11:56:05 [Warning] WSREP: Gap in state sequence. Need state transfer. 140117 11:56:07 [Note] WSREP: Running: 'wsrep_sst_xtrabackup --role 'joiner' --address '122.146.119.102' --auth 'username:password' --datadir '/var/lib/mysql/' --defaults-file '/etc/my.cnf' --parent '965'' WSREP_SST: [INFO] Streaming with tar (20140117 11:56:07.517) WSREP_SST: [INFO] Using socat as streamer (20140117 11:56:07.519) WSREP_SST: [INFO] Evaluating socat -u TCP-LISTEN:4444,reuseaddr stdio | tar xfi - --recursive-unlink -h; RC=( ${PIPESTATUS[@]} ) (20140117 11:56:07.531) 140117 11:56:07 [Note] WSREP: Prepared SST request: xtrabackup|122.146.119.102:4444/xtrabackup_sst 140117 11:56:07 [Note] WSREP: wsrep_notify_cmd is not defined, skipping notification. 140117 11:56:07 [Note] WSREP: Assign initial position for certification: 678691, protocol version: 2 140117 11:56:07 [Note] WSREP: Prepared IST receiver, listening at: tcp://122.146.119.102:4568 140117 11:56:07 [Note] WSREP: Node 1 (db_01) requested state transfer from '*any*'. Selected 0 (db_02)(SYNCED) as donor. 140117 11:56:07 [Note] WSREP: Shifting PRIMARY -> JOINER (TO: 678692) 140117 11:57:36 [Note] WSREP: Synchronized with group, ready for connections 140117 11:57:36 [Note] WSREP: wsrep_notify_cmd is not defined, skipping notification. 140117 11:57:36 [Note] WSREP: 1 (db_02): State transfer from 0 (db_01) complete. 140117 11:57:36 [Note] WSREP: Member 1 (db_02) synced with group.

最後我們可以透過 MySQL Status 來看看是否有建立成功

mysql> show global status like 'wsrep_cluster_size'; +--------------------+-------+ | Variable_name      | Value | +--------------------+-------+ | wsrep_cluster_size | 3     | +--------------------+-------+ 1 row in set (0.00 sec)

看到 wsrep_cluster_size 出現正確的 Server 數量,就代表設定成功。

設定 HAProxy 負載平衡

上述完成了 3 台 Cluster 設定,接著所有的 Application 服務都需要直接跟此 Cluster 溝通,為了完成此需求,我們必須將 HAProxy 安裝在其中一台伺服器來做負載平衡,今天會介紹兩種設定方式,第一種是採用 round robin 方式,意思就是說所有的 Application 都可以連上並且寫入資料到三台機器,這狀況其實沒有錯誤,但是如果同時寫入三台機器,難免會出現 optimistic locking 而產生 rollback,如果可以確定不會產生 conflict,其實這方案是不錯的。第2種設定方式就是只寫入單一 Node,但是可以讀取三台機器,也就是 insert , update 都是在同一台 Node 完成,所以 Application 不用擔心會產生 rollback 情形。第1種設定在大部份的狀況底下都是可以運作很好的,所以其實也不用擔心。

底下是 /etc/haproxy/haproxy.cfg 設定

frontend stats-front bind *:8080 mode http default_backend stats-back  frontend pxc-front bind *:3307 mode tcp default_backend pxc-back  frontend pxc-onenode-front bind *:3308 mode tcp default_backend pxc-onenode-back  backend stats-back mode http balance roundrobin stats uri /haproxy/stats stats auth username:password  backend pxc-back mode tcp balance leastconn option httpchk server c1 192.168.1.100:3306 check port 9200 inter 12000 rise 3 fall 3 server c2 192.168.1.101:3306 check port 9200 inter 12000 rise 3 fall 3 server c3 192.168.1.102:3306 check port 9200 inter 12000 rise 3 fall 3  backend pxc-onenode-back mode tcp balance leastconn option httpchk server c1 192.168.1.100:3306 check port 9200 inter 12000 rise 3 fall 3 server c2 192.168.1.101:3306 check port 9200 inter 12000 rise 3 fall 3 backup server c3 192.168.1.102:3306 check port 9200 inter 12000 rise 3 fall 3 backup

從上述設定,可以看到我們定義了 3 個 frontend-backend ,其中stats-front 是 HAProxy Status Page,另外兩組則是針對 PXC 設定。看到此設定,可以知道系統會 Listen 3307 及 3308 兩個 port,其中 3308 會讓 App 使用一台 PXC Node 而已,此設定可以避免因為 optimistic locking 而產生 rollbacks,如果 Node 掛點,則會啟動其他 Node。然而如果是連接 3307 port,系統會直接對3台 node 寫入或讀取,我們使用 leastconn 取代 round robin ,這代表著 HAProxy 會偵測所有機器,並且取得現在連線數目最少的 Node 來給下一個連線。最後stats-front 是顯示 HAProxy 偵測及連線狀態,請務必設定帳號密碼。

完成設定,如何偵測 MySQL Server 是否存活,靠著就是 9200 port,透過 Http check 方式,讓 HAProxy 知道 PXC 狀態,安裝完 PXC 後,可以發現多了clustercheck 指令,我們必須先給 clustercheckuser 使用者帳號密碼

# Grant privileges required: $ GRANT PROCESS ON *.* TO 'clustercheckuser'@'localhost' IDENTIFIED BY 'clustercheckpassword!';

此 clustercheck 指令會在 Local 執行SHOW STATUS LIKE 'wsrep_local_state' MySQL 指令,回傳值為 200 或503 ,指令確定成功執行,最後步驟就是透過 xinetd 產生 9200 port 的服務。底下先安裝 xinetd 服務

$ yum -y install xinetd

產生 mysqlchk 設定

# default: on # description: mysqlchk service mysqlchk { # this is a config for xinetd, place it in /etc/xinetd.d/     disable = no     flags = REUSE     socket_type = stream     port = 9200     wait = no     user = nobody     server = /usr/bin/clustercheck     log_on_failure += USERID     only_from = 0.0.0.0/0     # recommended to put the IPs that need     # to connect exclusively (security purposes)     per_source = UNLIMITED }

上面步驟全部成功,請打開 URL 輸入 HAProxy Status 頁面,看到底下狀態,就是代表設定成功

Statistics Report for HAProxy

posted @ 2014-10-16 14:17 小马歌 阅读(236) | 评论 (0)编辑 收藏
仅列出标题
共95页: First 上一页 16 17 18 19 20 21 22 23 24 下一页 Last