Gradle For Android(四)Gradle编译中神秘的混淆

在日常开发中进行打包apk的一些往事,打包测试、打包上传应用商店,这些都避免不了。当然在这过程中,除了签名打包,当然少不了代码的混淆了。代码混淆,说白了就是代码压缩、代码混淆以及资源压缩的优化。依靠 ProGuard,将所有类名、方法名重命名为无意义的简单名称,增加了逆向工程难度。依靠Gradle插件,移除了没有使用的资源,减少了apk大小 。

一、Android Gradle 混淆中的配置

一般,在我们的application moudle中的gradle配置项buildTypes中,例如如下:

<pre class=”hljs java” data-original-code=”” release=”” {=”” release类型”=”” data-snippet-id=”ext.1744a3506a70e65a40398e84a3d3b3d4″ data-snippet-saved=”false” data-codota-status=”done”>

  1. release { //release类型
  2. minifyEnabled false
  3. // 启用混淆
  4. proguardFiles getDefaultProguardFile(‘proguard-android.txt’), ‘proguard-rules.pro’
  5. }

这里minifyEnabled表示启动混淆,一般启动混淆编译速度会比较慢,因此在编译debug版本的时候一般默认不开启。proguard-rules.pro这个表示该module默认的混淆文件,我们可以直接将混淆内容写在这里。另外,这里也要说下**shrinkResources **这个字段,当为true的时候,表示打开资源压缩,编译时会去掉没被使用的资源文件。

修改后的配置代码如下:

  1. buildTypes {//表示构建类型 一般有release debug 两种
  2. debug{
  3. buildConfigField 'String','STATE_TEST','"debug"'//buildConfigField
  4. resValue "string", "test_value", "AGradle_debug"//resValue
  5. }
  6. release { //release类型
  7. minifyEnabled true // 启用混淆
  8. shrinkResources true // 资源压缩
  9. proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
  10. buildConfigField 'String','STATE_TEST','"release"' //buildConfigField
  11. resValue "string", "test_value", "AGradle_release" //resValue
  12. }
  13. }

二、混淆规则举例

这里贴下网上认为比较”通用”的混淆规则如下:

  1. #指定压缩级别
  2. -optimizationpasses 5
  3. #不跳过非公共的库的类成员
  4. -dontskipnonpubliclibraryclassmembers
  5. #混淆时采用的算法
  6. -optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
  7. #把混淆类中的方法名也混淆了
  8. -useuniqueclassmembernames
  9. #优化时允许访问并修改有修饰符的类和类的成员
  10. -allowaccessmodification
  11. #将文件来源重命名为“SourceFile”字符串
  12. -renamesourcefileattribute SourceFile
  13. #保留行号
  14. -keepattributes SourceFile,LineNumberTable
  15. #保持所有实现 Serializable 接口的类成员
  16. -keepclassmembers class * implements java.io.Serializable {
  17. static final long serialVersionUID;
  18. private static final java.io.ObjectStreamField[] serialPersistentFields;
  19. private void writeObject(java.io.ObjectOutputStream);
  20. private void readObject(java.io.ObjectInputStream);
  21. java.lang.Object writeReplace();
  22. java.lang.Object readResolve();
  23. }
  24. #Fragment不需要在AndroidManifest.xml中注册,需要额外保护下
  25. -keep public class * extends android.support.v4.app.Fragment
  26. -keep public class * extends android.app.Fragment
  27. # 保持测试相关的代码
  28. -dontnote junit.framework.**
  29. -dontnote junit.runner.**
  30. -dontwarn android.test.**
  31. -dontwarn android.support.test.**
  32. -dontwarn org.junit.**

“通用”,当然真正实现通用,除了上面的混淆规则,需要根据项目需要添加自定义的混淆规则

例如:

  • 第三方库混淆规则。这个比较常见,直接接入官方说明文档。
  • model实体类,典型在转化json的时候,必须保证model不被混淆,因此需加入–keep public class

JNI中调用的类以及方法不可被混淆

  • WebView中JavaScript调用的接口不混淆
  • AndroidMainfest、四大组件以及Application的子类不混淆
  • Parcelable的子类和Creator静态成员变量不混淆,否则会产生Android.os.BadParcelableException异常
  • Layout布局使用的View构造函数、android:onClick等。

三、混淆结果的检测

在开启混淆后,通过混淆配置打包后,会在目录:

  1. <module>/outputs/mapping/<渠道名>/<编译类型>/..

如图所示:

%title插图%num
gradle.png

下面大概说明下:

  • dump.txt :描述APK文件中所有类的内部结构
  • mapping.txt :提供混淆前后类、方法、类成员等的对照表
  • seeds.txt:列出没有被混淆的类和成员

usage.txt: 列出被移除的代码

我们可以根据 seeds.txt 文件检查未被混淆的类和成员中是否已包含所有期望保留的,再根据 usage.txt 文件查看是否有被误移除的代码。建议读者都试下去查看下,必须有收获~

四、自定义混淆规则

(一) proguard 参数
  • include {filename} 从给定的文件中读取配置参数
  • basedirectory {directoryname} 指定基础目录为以后相对的档案名称
  • injars {class_path} 指定要处理的应用程序jar,war,ear和目录
  • outjars {class_path} 指定处理完后要输出的jar,war,ear和目录的名称
  • libraryjars {classpath} 指定要处理的应用程序jar,war,ear和目录所需要的程序库文件
  • dontskipnonpubliclibraryclasses 指定不去忽略非公共的库类。
  • dontskipnonpubliclibraryclassmembers 不跳过非公共的库的类成员

上面部分参数,日常移动开发的应用混淆中也不是经常使用到的,如果读者想进一步深入了解每个参数实际作用,可以去官网进行查阅,这里笔者不做太多说明哈。

(二)keep 参数
  • keep {Modifier(属性,例如public,以下说明一致)} {class_specification(具体类或者成员的位置,以下说明一致)} 防止类和成员被移除或者被重命名
  • keepclassmembers {modifier} {class_specification} 防止成员被移除或者被重命名
  • keepnames {class_specification} 防止成员被重命名)
  • keepclassmembernames {class_specification} 防止拥有该成员的类和成员被移除或者被重命名
  • keepclasseswithmembernames {class_specification} 防止拥有该成员的类和成员被重命名
(三)混淆的必须知道的一些规则

1、一般规则形式:

  1. [命令] [类] {
  2. [成员]
  3. }

:代表相关指定条件的类,例如

  • 具体的类
  • 访问修饰符(publicprotectedprivate
  • 通配符*,匹配任意长度字符,但不含包名分隔符(.)
  • 通配符**,匹配任意长度字符,并且包含包名分隔符(.)
  • extends,即可以指定类的基类
  • implement,匹配实现了某接口的类
  • $,内部类

成员:代表指定类后符合指定条件的成员变量,例如

  • 匹配所有构造器
  • 匹配所有域
  • 匹配所有方法
  • 通配符*,匹配任意长度字符,但不含包名分隔符(.)
  • 通配符**,匹配任意长度字符,并且包含包名分隔符(.)
  • 通配符***,匹配任意参数类型
  • ,匹配任意长度的任意类型参数。比如void test(…)就能匹配任意 void test(String a) 或者是 void test(int a, String b) 这些方法。
  • 访问修饰符(publicprotectedprivate

举个例子,假如需要将name.huihui.test包下所有继承Activitypublic类及其构造函数都保持住,可以这样写:

  1. -keep public class name.huihui.test.** extends Android.app.Activity {
  2. <init>
  3. }

2、常用自定义混淆规则

  • 不混淆某个类
  1. -keep public class name.huihui.example.Test { *; }
  • 不混淆某个包所有的类
  1. -keep class name.huihui.test.** { *; }
  • 不混淆某个类的子类
  1. -keep public class * extends name.huihui.example.Test { *; }
  • 不混淆所有类名中包含了“model”的类及其成员
  1. -keep public class **.*model*.** {*;}
  • 不混淆某个接口的实现
  1. -keep class * implements name.huihui.example.TestInterface { *; }
  • 不混淆某个类的构造方法
  1. -keepclassmembers class name.huihui.example.Test {
  2. public <init>();
  3. }
  • 不混淆某个类的特定的方法
  1. -keepclassmembers class name.huihui.example.Test {
  2. public void test(java.lang.String);
  3. }

五、自定义资源保持规则

前面说的通过shrinkResources true开启资源压缩后,未被使用的资源默认不会被打包进去。如果开发者是自定义保留指定的资源文件,可以在res/raw/ 路径下创建一个 xml 文件,例如 keep.xml,进行自定义混淆规则。

一般属性有:

  • tools:keep 定义哪些资源需要被保留(资源之间用“,”隔开)
  • tools:discard 定义哪些资源需要被移除(资源之间用“,”隔开)
  • tools:shrinkMode 开启严格模式

例如:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <resources xmlns:tools="http://schemas.android.com/tools"
  3. tools:keep="@layout/l_used*_c,@layout/l_used_a,@layout/l_used_b*"
  4. tools:discard="@layout/unused2"
  5. tools:shrinkMode="strict"/>

 

Spark安装与学习

摘要:Spark是继Hadoop之后的新一代大数据分布式处理框架,由UC Berkeley的Matei Zaharia主导开发。我只能说是神一样的人物造就的神器,详情请猛击http://www.spark-project.org/

Created 2012-05-09

Modified 2012-08-13

1 Scala安装

当前,Spark*新版本是0.5,由于我写这篇文档时,版本还是0.4,因此本文下面的所有描述基于0.4版本。

不过淘宝的达人已经尝试了0.5,并写了相关安装文档在此http://rdc.taobao.com/team/jm/archives/tag/spark

~~~~~~~~~~~~~~~以下开始我的安装文档~~~~~~~~~~~~~~

我使用的Spark的版本是0.4,只存在于github上,该版本使用的Scala版本是0.9.1.final。所以先到http://www.scala-lang.org/node/165下载scala-2.9.1.final.tar.gz。解压后放到本地 /opt 下面,在 /etc/profile 里添加

export SCALA_HOME=/opt/scala-2.9.1.final

export PATH=$SCALA_HOME/bin:$PATH

2 git安装

由于下载Spark和编译Spark需要git,因此先安装git,安装方法可以到Ubuntu软件中心直接装,也可以apt-get装。装好后需要到https://github.com 去注册一个帐号,我注册的是JerryLead,注册邮箱和密码,然后根据网站上的get-start提示生成RSA密码。

注意:如果本地之前存在rsa_id.pub,authorized_keys等,将其保存或着将原来的密码生成为dsa形式,这样git和原来的密码都不冲突。

3 Spark安装

首先下载*新的源代码

git clone git://github.com/mesos/spark.git

得到目录spark后,进入spark目录,进入conf子目录,将 spark-env.sh-template 重命名为spark-env.sh,并添加以下代码行:

export SCALA_HOME=/opt/scala-2.9.1.final

回到spark目录,开始编译,运行

sbt/sbt update compile

这条命令会联网下载很多jar,然后会对spark进行编译,编译完成会提示success

[success] Total time: 1228 s, completed May 9, 2012 3:42:11 PM

可以通过运行spark-shell来和spark进行交互。

也可以先运行测试用例./run <class> <params>

./run spark.examples.SparkLR local[2]

在本地启动两个线程运行线性回归。

./run spark.examples.SparkPi local

在本地启动运行Pi估计器。

更多的例子在examples/src/main/scala里面

3 Spark导出

在使用Spark之前,先将编译好的classes导出为jar比较好,可以

$ sbt/sbt assembly

将Spark及其依赖包导出为jar,放在

core/target/spark-core-assembly-0.4-SNAPSHOT.jar

可以将该jar添加到CLASSPATH里,开发Spark应用了。

一般在开发Spark应用时需要导入Spark一些类和一些隐式的转换,需要再程序开头加入

import spark.SparkContext

import SparkContext._

4 使用Spark交互模式

1. 运行./spark-shell.sh

2. scala> val data = Array(1, 2, 3, 4, 5) //产生data

data: Array[Int] = Array(1, 2, 3, 4, 5)

3. scala> val distData = sc.parallelize(data) //将data处理成RDD

distData: spark.RDD[Int] = spark.ParallelCollection@7a0ec850 (显示出的类型为RDD)

4. scala> distData.reduce(_+_) //在RDD上进行运算,对data里面元素进行加和

12/05/10 09:36:20 INFO spark.SparkContext: Starting job…

5. *后运行得到

12/05/10 09:36:20 INFO spark.SparkContext: Job finished in 0.076729174 s

res2: Int = 15

5 使用Spark处理Hadoop Datasets

Spark可以从HDFS/local FS/Amazon S3/Hypertable/HBase等创建分布式数据集。Spark支持text files,SequenceFiles和其他Hadoop InputFormat。

比如从HDFS上读取文本创建RDD

scala> val distFile = sc.textFile(“hdfs://m120:9000/user/LijieXu/Demo/file01.txt”)

12/05/10 09:49:01 INFO mapred.FileInputFormat: Total input paths to process : 1

distFile: spark.RDD[String] = spark.MappedRDD@59bf8a16

然后可以统计该文本的字符数,map负责处理文本每一行map(_size)得到每一行的字符数,多行组成一个List,reduce负责将List中的所有元素相加。

scala> distFile.map(_.size).reduce(_+_)

12/05/10 09:50:02 INFO spark.SparkContext: Job finished in 0.139610772 s

res3: Int = 79

textFile可以通过设置第二个参数来指定slice个数(slice与Hadoop里的split/block概念对应,一个task处理一个slice)。Spark默认将Hadoop上一个block对应为一个slice,但可以调大slice的个数,但不能比block的个数小,这就需要知道HDFS上一个文件的block数目,可以通过50070的dfs的jsp来查看。

对于SequenceFile,可以使用SparkContext的sequenceFile[K,V]方法生成RDD,其中K和V肯定要是SequenceFile存放时的类型了,也就是必须是Writable的子类。Spark也允许使用native types去读取,如sequenceFile[Int, String]。

对于复杂的SequenceFile,可以使用SparkContext.hadoopRDD方法去读取,该方法传入JobConf参数,包含InputFormat,key class,value class等,与Hadoop Java客户端读取方式一样。

6 分布式数据集操作

分布式数据集支持两种类型的操作:transformation和action。transformation的意思是从老数据集中生成新的数据集,action是在数据集上进行计算并将结果返回给driver program。每一个Spark应用包含一个driver program用来执行用户的main函数,比如,map就是一个transformation,将大数据集划分处理为小数据集,reduce是action,将数据集上内容进行聚合并返回给driver program。有个例外是reduceByKey应该属于transformation,返回的是分布式数据集。

需要注意的是,Spark的transformation是lazy的,transformation先将操作记录下来,直到接下来的action需要将处理结果返回给driver program的时候。

另一个特性是caching,如果用户指定cache一个数据集RDD,那么该数据集中的不同slice会按照partition被存放到相应不同节点的内存中,这样重用该数据集的时候,效率会高很多,尤其适用于迭代型和交互式的应用。如果cache的RDD丢失,那么重新使用transformation生成。

7 共享变量

与Hadoop的MapReduce不同的是,Spark允许共享变量,但只允许两种受限的变量:broadcast和accumulators。

Broadcast顾名思义是“广播”,在每个节点上保持一份read-only的变量。比如,Hadoop的map task需要一部只读词典来处理文本时,由于不存在共享变量,每个task都需要加载一部词典。当然也可以使用DistributedCache来解决。在Spark中,通过broadcast,每个节点存放一部词典就够了,这样从task粒度上升到node粒度,节约的资源可想而知。Spark的broadcast路由算法也考虑到了通信开销。

通过使用SparkContext.broadcast(v)来实现对变量v的包装和共享。

scala> val broadcastVar = sc.broadcast(Array(1,2,3))

12/05/10 10:54:21 INFO spark.BoundedMemoryCache: Asked to add key ((1,a5c2a151-185d-4ea4-aad1-9ec642eebc5d),0)

12/05/10 10:54:21 INFO spark.BoundedMemoryCache: Estimated size for key ((1,a5c2a151-185d-4ea4-aad1-9ec642eebc5d),0) is 12

12/05/10 10:54:21 INFO spark.BoundedMemoryCache: Size estimation for key ((1,a5c2a151-185d-4ea4-aad1-9ec642eebc5d),0) took 0 ms

12/05/10 10:54:21 INFO spark.BoundedMemoryCache: ensureFreeSpace((1,a5c2a151-185d-4ea4-aad1-9ec642eebc5d), 12) called with curBytes=12, maxBytes=339585269

12/05/10 10:54:21 INFO spark.BoundedMemoryCache: Adding key ((1,a5c2a151-185d-4ea4-aad1-9ec642eebc5d),0)

12/05/10 10:54:21 INFO spark.BoundedMemoryCache: Number of entries is now 2

broadcastVar: spark.broadcast.Broadcast[Array[Int]] = spark.Broadcast(a5c2a151-185d-4ea4-aad1-9ec642eebc5d)

创建broadcast变量后,可以通过.value来访问只读原始变量v。

scala> broadcastVar.value

res4: Array[Int] = Array(1, 2, 3)

另一种共享变量是Accumulators,顾名思义就是可以被“added”的变量,比如MapReduce中的counters就是不断累加的变量。Spark原生支持Int和Double类型的累加变量。

通过SparkContext.accumulator(v)来创建accumulator类型的变量,然后运行的task可以使用“+=”操作符来进行累加。但是task不能读取到该变量,只有driver program能够读取(通过.value),这也是为了避免使用太多读写锁吧。

创建0的accumulator版本。

scala> val accum = sc.accumulator(0)

accum: spark.Accumulator[Int] = 0

对生成的RDD进行累加,这次不要reduce了。

scala> sc.parallelize(Array(1,2,3,4)).foreach(x => accum += x)

12/05/10 11:05:48 INFO spark.SparkContext: Starting job…

scala> accum.value

res7: Int = 20

8 安装Mesos

Spark-0.4推荐的Mesos版本是1205738,不是*新版的Mesos,我想*新版应该也可以,这里暂且使用1205738。

首先下载Mesos

得到mesos目录后,先安装编译所需的软件

apt-get install python2.6 python2.6-dev

很遗憾,虽然Ubuntu 11.04上有python 2.7,但webui(mesos的web界面)需要python 2.6,因此要装

apt-get install libcppunit-dev (安装cppunit)

确保g++版本大于4.1

如果缺automake,那么安装

apt-get install autoconf automake libtool

由于系统是Ubuntu 11.04 (GNU/Linux 2.6.38-8-generic x86_64)-natty,可以直接使用./configure.template.ubuntu-natty-64。但我使用的JDK是Sun的,因此修改./configure.template.ubuntu-natty-64里面–with-java-home为/opt/jdk1.6.0_27。

总体如下:

cp configure.template.ubuntu-natty-64 configure.template.ubuntu-my-natty-64

修改configure.template.ubuntu-my-natty-64得到如下内容

1 #!/bin/sh

2 export PYTHON=python2.7

3

4 $(dirname $0)/configure \

5 –with-python-headers=/usr/include/python2.7 \

6 –with-java-home=/opt/jdk1.6.0_27 \

7 –with-webui \

8 –with-included-zookeeper $@

编译mesos

root@master:/opt/mesos# ./configure.template.ubuntu-my-natty-64

完了之后

root@master:/opt/mesos# make

9 配置Mesos和Spark

先在slave1、slave2、slave3和master上安装mesos,我这里安装在/opt/mesos。

进入conf目录,修改deploy-env.sh,添加MESOS_HOME

# This works with a newer version of hostname on Ubuntu.

#FULL_IP=”hostname –all-ip-addresses”

#export LIBPROCESS_IP=`echo $FULL_IP | sed ‘s/[][]∗ .*/\1/’`

export MESOS_HOME=/opt/mesos

修改mesos.conf,添加

# mesos-slave with –help.

failover_timeout=1

进入/opt/spark,修改conf/spark-env.sh,添加

# variables to set are:

# – MESOS_HOME, to point to your Mesos installation

# – SCALA_HOME, to point to your Scala installation

# – SPARK_CLASSPATH, to add elements to Spark’s classpath

# – SPARK_JAVA_OPTS, to add JVM options

# – SPARK_MEM, to change the amount of memory used per node (this should

# be in the same format as the JVM’s -Xmx option, e.g. 300m or 1g).

# – SPARK_LIBRARY_PATH, to add extra search paths for native libraries.

export SCALA_HOME=/opt/scala-2.9.1.final

export MESOS_HOME=/opt/mesos

export PATH=$PATH:/opt/jdk1.6.0_27/bin

export SPARK_MEM=10g (根据自己机器的内存大小设置,指示Spark可以使用的*大内存量)

iOS关掉横屏后某单个页面横竖屏切换

在你想支持横竖屏的viewController里面重写两个方法:

// 支持设备自动旋转
– ( BOOL )shouldAutorotate
{
return  YES;
}

// 支持横竖屏显示
– (NSUInteger)supportedInterfaceOrientations
{
return  UIInterfaceOrientationMaskAll;
}
这样在这个viewController中就可以横竖屏切换了。

但是,如果你window的rootViewController是一个navigationController,可能会出现以下问题:

navigationController只支持竖屏,但是你push到了某个新的controller中,这个controller支持横竖屏,当你在新的controller中切换到横屏后(也有可能在切换到横屏然后pop回来后),这时候程序会闪退,因为你的navigationController不支持横屏。

这需要写一个UINavigationController的子类,在这个类中重写方法:

– ( BOOL )shouldAutorotate
{
return  [self.viewControllers.lastObject shouldAutorotate];
}

– (NSUInteger)supportedInterfaceOrientations
{
return  [self.viewControllers.lastObject supportedInterfaceOrientations];
}

– (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return  [self.viewControllers.lastObject preferredInterfaceOrientationForPresentation];
}
然后用这个类去创建实例作为window的rootViewController,这样就可以避免这个问题了。

服务器部署项目流程

一 、操作软件介绍:
首先我们得下载并且安装一个 TeamViewer 10的软件,TeamViewer是一个在任何防火墙和NAT代理的后台用于远程控制,桌面共享和文件传输的简单且快速的解决方案。为了连接到另一台计算机,只需要在两台计算机上同时运行 TeamViewer 即可而不需要进行一个安装的过程。该软件*次启动在两台计算机上自动生成伙伴 ID。只需要输入你的伙伴的 ID 到TeamViewer,然后就会立即建立起连接。

二 、项目整理
我们找到myelipse中编译成功的项目,点击Servers,找到你当前Tomcat中你部署的项目,右建项目,选择browse deployment location,这样你就成功进到你编译好的项目,将项目复制一份放到另一个位置,进到项目WEB-INF—lib,把lib里的架包全部删除,接着WEB-INF—classes
1.找到application-context.xml改成application-context.xml.MySQL(因为我们本地的数据库是mysql,服务器上数据库Oracle,所以这里要把oracle的配置上传上去)
2.application-context.xml.oracle改成application-context.xml(修改理由同上)
3. 打开data.properties找到project_name,将后面的项目名,改成你服务器上项目名字,确保同名。(当然首先你得清楚,你的服务器的项目是什么!)
4.完成上面操作后,将项目名字改为服务器上项目的名字,压缩成zip文件。~~好的,取经才刚开始!

三 、开始服务器部署操作:
1.  打开 TeamViewer,在伙伴ID输入ID,按照步骤并输入正确密码后,接下来你就成功的连接到另一台计算机了(我们简称-*台服务器),然后你可以将本地需要上传的文件,通过*台服务器界面上的——文件传输,将你本地计算机的项目上传到*台服务器,接着就可以在*台服务器上操作了,把传输过来的项目复制一份,开始——运行——输入mstsc——确认后会弹出一个远程桌面链接——写上第二台服务器的IP(10.17.68.196)——(密码——a1b2@sys)一系列操作后,就来到第二台服务器了。
2.把在*台服务器复制的项目,粘贴放到第二台服务器上(备注:可以在某个位置,新建一个文件夹,以后你的项目就可以全部放在这里了)。
3.点击桌面上—–快捷方式 到 SecureCRT.exe的图标,利用SecureCRT,使用linux命令就可以愉快的将文件上传到服务器,或将文件下载到本地了。

四  SecureCRT上的linux命令操作
一 、 常用命令:
ls -sl查看权限
chmod   +x startup.sh让这个有权限
less  日志名字
netstat -an |grep
ls    (查看当前目录全部)
cd  ( 进入根目录)
cd ../( 回到上级目录)pwd
rz     ( 上传文件)
mv (重命名 a b)平时-ef
rm -rf xxx(删除文件或文件夹)
unzip(解压压缩文件-zip类型的
vi(查看文件) vi   文件名  i(i:开始修改) 修改后按esc  shift: wq(wq:进行保存)

二、 具体操作详细:
1.输入: cd  /opt/apache-tomcat-7.0.53_2   (进到tomcat_2服务器)
2.输入: cd ../webapps/                    (webapps里就是放项目的位置)
3.然后你就可以看到公司的项目了,找到你的项目,就根据上面的常用命令,进行你要做的操作吧。
4.操作完毕后,接着进到tomcat-7.0.53_2的bin里,进到bin后录入:ps  -ef|grep  java,这样你就可以看到当前tomcat-7.0.53_2的进程了,  再接着录入 kill  -9  …(…表示tomcat-7.0.53_2的进程,注意:一定要是tomcat-7.0.53_2的进程。)
5. 输入 ./startup.sh (重启服务器)

web项目如何部署到服务器?

写好上位机程序后,如何部署到服务器?
(这里我用的是tomcat服务器)
首先说明一点:为了程序测试是否连接到下位机,我编写了一个命名为gprs的java文件,这个可以用下位机连接是否成功。程序见附录,下面说具体的部署的步骤:

把web项目导出为war文件。步骤:选中web文件的项目->右键->Export->Myeclipse->WAR file如下图:
%title插图%num

选择导出的位置,这里我为方便查找,选择为桌面。

%title插图%num

把gprs.java文件导出为 Runnable JAR 文件。

步骤:选中java项目中的gprs.jar文件->右键->Export->java->Runnable JAR file,然后选择next

%title插图%num

Launch configuation 选择的是你的主清单属性(就是你要运行的main方法所在的类,如果找不到就把main方法跑一边),Export destinaction 把导出的文件存放到哪里(不是像下载东西直接选个地址就完了,还要指定文件名和后缀  例如  c:\test.jar)Library handling 的三个选项(建议选第二个)

finish(去你指定的地方就可以找到文件了不用担心你依赖的jar会一起导出了)

Library handling 的三个选项:

Extract required libraries into generated jar:提取需要的库(以解压的形式)放到生成的 jar文件中,生成的jar文件较小 Package required libraries into generated jar:将所有需要的Jar包放到生成的 jar 文件中,生成的jar文件较大 Copy required libraries into a sub-folder next to the generated jar:将需要的jar包拷贝到一个子文件夹中

%title插图%num

发送到服务器

以上两个文件导成功后,登录自己的云服务器,并把上面的war文件通过远程桌面或者第三方软件(qq、微信、网盘等),从本地主机发送到服务器上,并把war文件放在tomcat中webapps目录下,并解压;把jar文件,放在c盘->Administeration目录下即可。

调试,运行。

首先,打开cmd,然后:输入:java -jar xxxx.jar (xxx代表的是导出的jar文件名称)。保证没有报错即可。

然后,通过网络调试助手,建立TCP的client。然后输入服务器的静态IP地址和端口号(在java文件中设置好的端口号)。检测是否是否能服务器连接成功。

*后,连接成功后,打开服务器的tomcat,在服务器的浏览器端输入:

http://47.93.7.53:8080/demo_bridge0807
http://服务器的静态IP:8080/war文件的名称

以上步骤就完成了环境搭建。

欢迎大家批评指教!

iOS音频格式转换工具库:ExtAudioConverter

前段时间的工作,和iOS的音频相关,需要一个功能:将音频从wav格式转为mp3格式。这个需求不是很强,但却不太好实现。

于是我写了一个音频格式转换的开源库,这个库包含了iOS/OS X支持的所有音频格式,另外也支持mp3格式(使用lame实现)。它仿照OS X上的afconvert命令的参数设置,未来会比afconvert应用范围更大。

开源库名叫ExtAudioConverter,基于ExtAudioFile实现。链接在这里:https://github.com/lixing123/ExtAudioConverter

如何使用:

在项目里添加“AudioToolbox.framework”;
把”ExtAudioConverter.h”和”ExtAudioConverter.m”添加到项目;
测试:
ExtAudioConverter* converter = [[ExtAudioConverter alloc] init];
converter.inputFile = @”/your/input/file”;
converter.outputFile = @”/your/output/file”;
[converter convert];

代码在iOS和OS X上测试通过。

一些可选的参数:
1. 采样率

converter.outputSampleRate = 44100;
1
声道数
converter.outputNumberChannels = 2;
1
位深
converter.outputBitDepth = BitDepth_16;
1
设置文件格式
converter.outputFileType = kAudioFileWAVEType;
1
设置数据格式
converter.outputFormatID = kAudioFormatLinearPCM;
1
关于文件格式和数据格式的说明文档,在这里:https://developer.apple.com/library/ios/documentation/MusicAudio/Conceptual/CoreAudioOverview/SupportedAudioFormatsMacOSX/SupportedAudioFormatsMacOSX.html

简单来讲,一种文件格式对应一种或者多种数据格式,如mp3 file format只对应mp3 data format,caf(Core Audio Format)格式则对应几乎所有data format。因此工具库默认的output file format就是caf格式。

现在还没有bit rate(比特率)的设置接口。后面将根据需要添加。

iOS8/9的Notification新特性

在iOS8和iOS9下,notification增加了一些新的特性,使之更加强大:
– iOS8增加了下拉时的Action按钮,像微信一样;
– iOS9增加了像信息一样的可以下拉直接输入;

iOS8为了实现action按钮,增加了4个类,一起完成这个功能:
– UIUserNotificationSettings;
– UIUserNotificationType:alert/sound/badge
– UIUserNotificationCategory;
– UIUserNotificationAction;

闲话少说,还是代码讲的清楚:

//初始化action
UIMutableUserNotificationAction* action1 = [[UIMutableUserNotificationAction alloc] init];
//设置action的identifier
[action1 setIdentifier:@”action1″];
//title就是按钮上的文字
[action1 setTitle:@”title1″];
//设置点击后在后台处理,还是打开APP
[action1 setActivationMode:UIUserNotificationActivationModeBackground];
//是不是像UIActionSheet那样的Destructive样式
[action1 setDestructive:NO];
//在锁屏界面操作时,是否需要解锁
[action1 setAuthenticationRequired:NO];

UIMutableUserNotificationAction* action2 = [[UIMutableUserNotificationAction alloc] init];
[action2 setIdentifier:@”action2″];
[action2 setTitle:@”title2″];
[action2 setActivationMode:UIUserNotificationActivationModeForeground];
[action2 setDestructive:NO];
[action2 setAuthenticationRequired:NO];

//一个category包含一组action,作为一种显示样式
UIMutableUserNotificationCategory* category = [[UIMutableUserNotificationCategory alloc] init];
[category setIdentifier:@”category1″];
//minimal作为banner样式时使用,*多只能有2个actions;default*多可以有4个actions
[category setActions:@[action1,action2] forContext:UIUserNotificationActionContextMinimal];

NSSet* set = [NSSet setWithObject:category];
UIUserNotificationSettings* settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound
categories:set];
//注册notification设置
[[UIApplication sharedApplication] registerUserNotificationSettings:settings];

//添加一个notification,10秒后触发
UILocalNotification* notification = [[UILocalNotification alloc] init];
//设置notifiction的样式为”category1″
[notification setCategory:@”category1″];
[notification setFireDate:[NSDate dateWithTimeIntervalSinceNow:10]];
[notification setAlertBody:@”this is an alert”];
[[UIApplication sharedApplication] scheduleLocalNotification:notification];

结果是这个样子的:

这时候点击action1,alert就直接消失了,因为action1的setActivationMode是background的;而点击action2,app就会被打开;
无论哪个action,系统打开的时候都会调用AppDelegate的-(void)application: handleActionWithIdentifier: forLocalNotification:(nonnull UILocalNotification *)completionHandler:方法;如果直接点击alert的话,会调用application: didFinishLaunchingWithOptions:方法,而options参数里就包含了alert的信息;

几个要注意的地方:

push notification的时候,如何指定alert的样式,即category?
只需要在push的内容里添加category的Identifier:
“aps”:{
“alert”:”This is a notification”,
“category”:<category的Identifier>
}

APP正在运行的时候,收到了notification,如何接收?
此时会调用application:didReceiveLocalNotification:方法;而系统不会有任何操作,不会发出声音、添加badge icon、也不会弹出alert;

alert可以设置一个alertLaunchImage,可以替代系统默认的launch image;

APP的badge number如何自动+1:
苹果没有提供这个方法,因此我们要在服务器上保存某个用户的badge number,在推送时+1;

能不能像信息那样,下拉直接回复?
iOS8没有这个功能,*新的iOS9可以:

action.behavior = UIUserNotificationBehaviorTextInput;
1
iOS8时,增加了在指定地点弹出的功能:[notification setRegion:];

如何确定用户有没有禁止发送notifications:
设置notificationCategory后,检查AppDelegate有没有调用下面的方法:

– (void) application: didRegisterUserNotificationSettings:

从零开始,如何完整的搭建一个网站和在服务器上部署项目!

一、准备工作:
1、有一个能在本地Tomcat上成功部署访问的项目。
2、申请一个服务器,可以直接搜索阿里云的服务器,注册购买。服务器建议使用Linux系统的,centos或者ubantu的都可以,因为系统占用存储空间小,操作起来方便。
3、申请一个域名,也可以在购买服务器的同时在阿里云注册一个域名,其实都是在万网注册的,阿里说到底也是中间商,只是没有差价而已,而且以后使用这个域名也会有一点点方便,免去了验证绑定的过程。
二、服务器绑定域名
登陆阿里云找到自己的服务器,然后绑定域名记得备案,备案完之后后面才可以通过域名去访问网站或者项目。
%title插图%num三、服务器环境搭建
这时候需要安装一个链接阿里云服务器的工具,推荐一个叫MobaXterm的工具,适合初学者,下载可以直接使用,自学的话可以使用xshell,有版权,在此不做过多介绍,个人觉还是很好用的工具。
服务器环境搭建其实就是在Linux系统上安装java环境还有MySQL数据库,Tomcat,具体可以查看这个
连接:https://blog.csdn.net/weixin_42164766/article/details/82804147
很详细,我之前也按这个操作过,可行。
其实这个安装java环境和Tomcat和在Windows上也没差太多,都很简单,装完之后测试一下环境看看,是否可行。注意如果是使用MySQL数据库,*好是使用版本安装到5.6以上,避免以后在入运行SQL文件时倒入不了本地数据。
四、连接服务器数据库
通过Navicat连接服务器数据库,只要在Navicat新建连接,服务器IP地址,端口号(端口号注意,在上边界图中的那个服务器安全设置,开放数据库端口,不然会显示无法连接数据库)。这时候就可以在本地操作服务器数据库了。很爽!
五、部署项目到服务器
也很简单,直接把项目先在开发工具上打包成war包,不清楚在自己百度一下,很简单。把war包直接导入到服务器Tomcat安装路径下的的webapps这个文件夹下,用之前MobaXterm这个工具可以直接粘贴复制。完成之后*好重启一下Tomcat,然后在Tomcat下编辑server.cnf这个文件,将访问路径指向域名,项目路径直接绑定到你上传的那个项目,先不多解释这个问题,可以百度,不清楚再问我也行。对了,还有一个重要的的点,就是把server.cnf这个文件的Tomcat端口port直接绑定为80 端口,这样就可以直接通过域名访问项目了,不然还得写www.XXXX.com:8080/项目名。
六、访问项目
直接在浏览器数据域名即可访问网站或者web项目了。

黑客是如何入侵服务器的

黑客是如何入侵别人电脑的?
黑客控制别人的电脑方式大概有几个角度
1.如果是一台web服务器的话,可以从web漏洞;数据库以及中间件的漏洞入手
2.如果是一台个人pc电脑的话,可以从系统的漏洞入手,大部分以缓冲区溢出执行任意命令为主
3.还可以有其他角度,比如office宏病毒,编辑器插件漏洞入手,这都是比较常用的手段。
%title插图%num

什么是KMS

KMS 就是 内核模式设置,Kernel mode-setting, for setting up screen resolution in the Linux kerne
传统上,Linux 是由用户空间的程序设置视频模式的,(也就是分辨率)
所以,切换终端的时候 ….. (Ctrl+Alt + F2)
会闪屏

并伴随着分辨率的切换

但是, tty2 – tty6 之间的切换又非常的迅速,没有分辨率的切换

有没有可能使 X 界面和 tty 之间也可以快速切换呢?

有!!
这就是 KMS
把 X-server 中切换视频模式的代码移植到内核中来,并在引导的初期就切换视频模式

表现就是,终端和X 图形界面使用相同的分辨率!
而且,X-server 启动的时候非常平滑!