0%

翻自Android官方文档:http://developer.android.com/training/multiscreen/index.html Android运行在几百种不同屏幕尺寸的设备上,小到手机,大到电视机。所以,设计你的应用使它能够兼容所有的屏幕尺寸,让尽可能多的用户可以使用是非常重要的。 适配不同的设备类型是不够的。每种屏幕尺寸为用户交互提供了不同的可能和挑战,所以,为了满足用户并且让他们印象深刻,你的就算必须超越”支持多种屏幕”:必须为每种屏幕配置优化用户体验。 本课程向你展示如何实现为不同屏幕配置优化的用户交互。 每堂课的范例代码演示了为多屏优化的最佳实践。你可以下载,并应用到你的程序中。 本课程和相关的鸽子使用Fragment,Android 3.0以下版本需要下载support包 范例下载:http://developer.android.com/shareables/training/NewsReader.zip 1、支持不同的屏幕尺寸 本课程将引导您如何设计一个适配多个不同屏幕尺寸的布局(使用dp,RelativeLayout,屏幕尺寸和方向界定符,别名过滤器和点9图片) 2、支持不同的屏幕密度 本节向你展示如何支持有不同像素密度的屏幕(使用密度独立像素,提供适用不同密度的图片)注:后面的好理解,不同的drawable下放不同size的图片,前面的什么意思? 3、实现适配的UI Flow(个人理解UI Flow就是交互流程) 这节课向你展示了如何以适配多个屏幕大小/密度组合(运行时检测活动布局,根据当前的布局,处理屏幕配置更改)实现UI Flow的方式。注:个人理解,就是在Java代码中动态改layout

出现这个异常,是因为你的AbsLisView(ListView,GridView等)标签间加了其他的控件,比如,下面的代码就会报这个错:

 <ListView
        android:id="@+id/mainRatePicView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/wordview_mainrate"
        android:layout_marginTop="@dimen/appendrate_item_mainrate_margin_top"
        android:listSelector="@color/transparent">
    <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" />
</ListView>

在ListView标签间加了TextView标签

如果按网上大部分文章说的,item的高度固定,listview的高度match_parent,getView仍然重复调用,看看ListView的parent layout是不是RelativeLayout. 如果是RelativeLayout,而ListView的layout_width不是match_parent,即使写了xxdp,getView也会重复调.原因在于,在RelativeLayout中,控件真正的宽度同时受限于他相对的控件。所以解决方法是,把RelativeLayout换成LinearLayout或者宽度设为match_parent

有时候,我们在调用了execute()方法后,AsyncTask并没有马上执行,而是等了很久后才执行,这是为什么呢? 原因在于AsyncTask默认自己维护一个静态的线程池,而该线程池只允许同时执行一个线程,也就是说,不管多少个AsyncTask,只要是调用execute()方法,都是共享这个默认进程池的,你的任务必须在之前的任务执行完以后,才能执行。可以理解为,默认情况下,所有的AsyncTask在一个独立于UI线程的线程中执行,任务需要排队,先execute的先执行,后面的只能等。 解决方法是,自己来维护这个线程池和任务列队。 好处:不会与其他的AsyncTask冲突,可以随时取消在排队的未执行的任务。

LinkedBlockingQueue blockingQueue = new LinkedBlockingQueue();
ExecutorService exec = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, blockingQueue);
new LoadTask().executeOnExecutor(exec);

如果需要清除排队的任务,可以调blockingQueue.clear()。

翻自Android官方文档:http://developer.android.com/training/improving-layouts/smooth-scrolling.html 让ListView滑动流畅的要点在于让主线程(UI)脱离繁重的处理,确保磁盘访问,网络访问,SQL查询在分离的线程里。你可以开启StrictMode测试你的App状态。 使用后台线程 使用后台线程(工作线程)从主线程中分离繁重的任务,让主线程可以专注于UI绘制。在大多数情况下,AsyncTask提供了在主线程外执行任务的简单方法。AsyncTask自动排队请求,在execute()方法里顺序执行(AsyncTask默认共享一个static单线程池,所以是单线程的),你不需要自己创建管理线程池。 在下面的例子里,AsyncTask用于在后台线程载入图片,载入完成后,在UI线程应用。在载入的时候同时显示一个ProgressBar.

// Using an AsyncTask to load the slow images in a background thread
new AsyncTask() {
    private ViewHolder v;

    @Override
    protected Bitmap doInBackground(ViewHolder... params) {
        v = params[0];
        return mFakeImageLoader.getImage();
    }

    @Override
    protected void onPostExecute(Bitmap result) {
        super.onPostExecute(result);
        if (v.position == position) {
            // If this item hasn't been recycled already, hide the
            // progress and set and show the image
            v.progress.setVisibility(View.GONE);
            v.icon.setVisibility(View.VISIBLE);
            v.icon.setImageBitmap(result);
        }
    }
}.execute(holder);

从Android 3.0(API 11)开始,AsyncTask针对多核处理器增加了一个新特性,你可以通过调用executeOnExecutor()取代execute(),指定自己的线程池,实现多线程同时操作。 通过ViewHolder保留View对象 你的代码可能会在滑动ListView时频繁调用findViewById,这可能是降低性能.即使Apapter返回了一个复用的view(convertView不为空),你仍然需要查找对象并更新.一种避免重复findViewById的方法是使用ViewHolder设计模式. 一个ViewHolder对象在Layout的tag字段里保存了每个View组件的引用,所以你可以立即访问而不需要重新查找。首先,你需要定义一个ViewHolder类保存你的View:

static class ViewHolder {
  TextView text;
  TextView timestamp;
  ImageView icon;
  ProgressBar progress;
  int position;
}

然后填充ViewHolder并保存在Layout的tag里:

ViewHolder holder = new ViewHolder();
holder.icon = (ImageView) convertView.findViewById(R.id.listitem_image);
holder.text = (TextView) convertView.findViewById(R.id.listitem_text);
holder.timestamp = (TextView) convertView.findViewById(R.id.listitem_timestamp);
holder.progress = (ProgressBar) convertView.findViewById(R.id.progress_spinner);
convertView.setTag(holder);

现在你可以很轻松地访问每个view(通过getTag),节省处理器资源。

今天准备重新装一下服务器,so,完整步骤记录一下。 环境: ubuntu 12.04.4 Desktop 中文版 nginx 1.4.5 mysql 5.6.16 apache 2.4.7 jdk-7u51 mongodb 2.4.9 pure-ftpd 1.0.36 User manager for PureFTPd 2.1 都是64bit的,因为这个服务器是装在虚拟机上,主要是为了开发以及备份,so,选择了桌面版的ubuntu,但跟服务器版本没什么区别。 装好系统后 1,设置root密码,desktop默认是没有root密码的 sudo passwd root 2,更换软件源,我用了阿里的,怎么改参考: http://mirrors.aliyun.com/help/ubuntu 各位自己看着办,哪个快用哪个,搜狐,163都有。 改完更新源: sudo apt-get update 升级软件包,要不要升还是问一下服务器提供商吧(万一VPS升了启动不了,悲剧了) sudo apt-get upgrade 3,安装ssh服务(为了模拟真实的服务器,后面操作全用ssh) sudo apt-get install openssh-server 正常情况下,会自动启动ssh服务,输入 ps -e |grep ssh 会看到ssh-agent和sshd两个进程,不正常自己找原因。手工操作: sudo /etc/init.d/ssh {stop|start|restart} 下面的操作都用ssh进行。 ssh root@ip 4,安装screen screen的功能在于可以像用桌面一样,开启多个终端,同时执行多条命令,而且当因网络原因导致ssh断线后,正在执行的任务也不会终止。如果没有screen,编译源码之类的耗时操作也得开着ssh客户端,而且什么都干不了,干等。 apt-get install screen 通常用法,在执行其他操作前,先进screen: screen -S xxx xxx是一个会话的名字,screen支持建立多个会话。 此时自动进入xxx的会话,你可以执行任意命令,比如下载wget,可能需要时间很长,想回去先干点别的事,这时,可以: ctrl+a,d 先按ctrl+a,松开a,保持ctrl键按住,再按d键,此时,xxx会话就进入后台执行,你可以继续screen -S yyy创建其他会话。 或者,可以直接在xxx会话中screen -S yyy也行。 想要切换会话,可以先看会话列表: screen -ls 会显示所有会话(会话id.会话名) 再进入指定会话 screen -r 会话id或会话名 退出会话: exit 基本上记住以上几条命令就够用了。 5、往server传安装文件(直接在server上下载也行) scp -r /Users/xxx/Downloads/linux_server root@10.68.184.17:/root/ 这里传的是整个目录。 6,开始安装前,先确定我们的安装目录。 我的系统分区是/一个10G分区,/home一个50G分区,计划把服务器相关的软件以及数据都装在/home里。 软件装在/home/server/app/下,数据放/home/server/data/,日志放/home/server/data/,配置文件放/home/server/config/ 之所以不用各个软件默认的配置,是为了以后管理方便,以后备份服务器,只需要tar整个/home/server/目录就可以了。 创建目录: mkdir /home/server/ mkdir /home/server/app mkdir /home/server/data mkdir /home/server/config mkdir /home/server/config/httpd mkdir /home/server/config/mysql mkdir /home/server/config/mongodb mkdir /home/server/data/wwwroot mkdir /home/server/data/mysqldata mkdir /home/server/data/mongodbdata 下面如果有设置目录,但上面没创建的,请先创建,否则可能会失败。 后面三个分别是web目录mysql数据保存目录,mongodb数据保存目录。 7,安装jdk tar zxvf jdk-7u51-linux-x64.gz -C /home/server/app/ 解压出来后,路径为 /home/server/app/jdk1.7.0_51 配置环境变量,编辑/etc/rc.local(注:/etc/profile需要用户登录才会执行,所以不能放在profile文件里),我用的是vim,需要apt-get install一下,也要以用vi,在文件末尾加上: JAVA_HOME=/home/server/app/jdk1.7.0_51 export JRE_HOME=$JAVA_HOME/jre export CLASSPATH=.:$JAVA_HOME/lib:$JRE_HOME/lib:$CLASSPATH export PATH=$JAVA_HOME/bin:$JRE_HOME/bin:$PATH 保存后,重新加载一下环境变量 source /etc/rc.local 再java -version,可以看下是否设置成功. 8,安装mysql 解压源码跳过… 安装依赖: sudo apt-get install cmake libssl-dev libncurses5-dev gcc g++ chkconfig 编译,安装: cmake -DCMAKE_INSTALL_PREFIX=/home/server/app/mysql -DSYSCONFDIR=/home/server/config/mysql -DMYSQL_DATADIR=/home/server/data/mysqldata -DMYSQL_TCP_PORT=3306 -DMYSQL_UNIX_ADDR=/tmp/mysqld.sock -DEXTRA_CHARSETS=all make make install 建立用户组及初始化数据库: groupadd mysql useradd -r -g mysql mysql chown -R mysql:mysql /home/server/app/mysql cd /home/server/app/mysql/ ./scripts/mysql_install_db --user=mysql --ldata=/home/server/data/mysqldata/ chown -R root:mysql /home/server/app/mysql chown -R mysql:mysql /home/server/data/mysqldata 复制编辑配置文件: cp /home/server/app/mysql/my.cnf /home/server/config/mysql/my.cnf 编辑my.cnf: [mysqld] datadir=/home/server/data/mysqldata default-storage-engine=MyISAM pid-file=/home/server/data/mysqldata/mysql.pid 复制启动脚本,开机自启: cp support-files/mysql.server /etc/init.d/mysql chmod 755 /etc/init.d/mysql chkconfig mysql on 如果chkconfig时报/sbin/insserv: 没有那个文件或目录,做个软链接 ln -s /usr/lib/insserv/insserv /sbin/insserv 启动mysql: service mysql start或/etc/init.d/mysql start 修改默认root密码 mysqladmin -u root password "newpass" 9,安装Apache apache依赖apr,apr-util,下载地址http://apr.apache.org/,当前版本1.5.3,PCRE:http://sourceforge.net/projects/pcre/files/pcre/,当前版本8.34 安装 #apr tar zxvf apr-1.5.0.tar.gz cd apr-1.5.0/ ./configure make make install #apr-util tar zxvf apr-util-1.5.3.tar.gz cd apr-util-1.5.3/ ./configure --prefix=/usr/local/apr-util make make install #PCRE tar zxvf pcre-8.34.tar.gz cd pcre-8.34/ ./configure make make install #软链接,网上有文章指32位用第一行,64位用第二行,我在64位系统上只用第二行无效,后面启动apache会报错 ln -s /usr/local/lib/libpcre.so.1 /lib ln -s /usr/local/lib/libpcre.so.1 /lib64 编译安装Apache: tar zxvf httpd-2.4.7.tar.gz cd httpd-2.4.7 ./configure --prefix=/home/server/app/apache --sysconfdir=/home/server/config/httpd --enable-so --enable-ssl --enable-cgi --enable-rewrite --with-zlib --enable-mpms-shared=all --with-mpm=event make make install 编辑配置文件/home/server/config/httpd/httpd.conf,顶上加上两行: PidFile "/var/run/httpd.pid" ServerName localhost:8080 再把Listen 80换成8080,因为80要留给nginx. 复制启动文件: cp /home/server/app/apache/bin/apachectl /etc/init.d/httpd 启动apache: /etc/init.d/httpd start 可以通过 http://ip:8080/查看安装结果 10,安装mongodb 2.4.9(绿色免安装,解压即可): tar zxvf mongodb-linux-x86_64-2.4.9.tgz -C /home/server/app/ 创建配置文件: /home/server/config/mongodb/mongodb.conf: dbpath=/home/server/data/mongodbdata fork=true auth=true logpath=/home/server/app/mongodb-linux-x86_64-2.4.9/log.log logappend=true journal=true quiet=true pidfilepath=/home/server/data/mongodbdata/mongo.pid 启动mongodb: /home/server/app/mongodb-linux-x86_64-2.4.9/bin/mongod -config /home/server/config/mongodb/mongodb.conf 11,安装php 5.5.9 先装依赖: apt-get install libxml2 libxml2-dev libbz2-dev libcurl4-gnutls-dev libiconv需要手动编译装,下载地址:https://www.gnu.org/software/libiconv/#TOCdownloading 当前1.14 wget http://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.14.tar.gz tar zxvf libiconv-1.14.tar.gz cd libiconv-1.14/ ./configure make make install 以下是PHP常用到的lib,建议都装了. zlib(http://www.zlib.net/) libpng(http://sourceforge.net/projects/libpng/) freetype(http://download.savannah.gnu.org/releases/freetype/) libJpeg(http://www.ijg.org/files/) gd(https://bitbucket.org/libgd/gd-libgd/downloads) mcrypt(http://sourceforge.net/projects/mcrypt/files/Libmcrypt/2.5.8/) 安装方法都一样: tar zxvf xxxx.tar.gz cd xxxx ./configure make make install 正式安装: tar zxvf php-5.5.9.tar.gz cd php-5.5.9 ./configure --prefix=/home/server/app/php --with-config-file-path=/home/server/config/php --enable-fpm --enable-mbstring --enable-ftp --with-bz2 --with-jpeg-dir --with-png-dir --with-freetype-dir --with-libxml-dir --with-xmlrpc --with-zlib-dir --with-curl --enable-calendar --enable-sockets --enable-exif --with-iconv=/usr/local/lib --with-gd --enable-gd-native-ttf --with-apxs2=/home/server/app/apache/bin/apxs --with-mcrypt --with-mysql=/home/server/app/mysql --with-mysqli=/home/server/app/mysql/bin/mysql_config --with-mysql-sock=/tmp/mysql.sock make make install 复制配置文件 cp php.ini-production /home/server/config/php/php.ini mv /home/server/app/php/etc/php-fpm.conf.default /home/server/app/php/etc/php-fpm.conf 添加用户组: groupadd www useradd -g www -s /sbin/nologin -M www 设置php运行的用户: vi /home/server/app/php/etc/php-fpm.conf user = www group = www 上面的方法装好php后,会自动修改apache的配置文件/home/server/config/httpd/httpd.conf,添加php5_module. 编辑这个配置文件,修改以下配置 User www Group www DocumentRoot "/home/server/data/wwwroot" Directory也要跟着DocumentRoot改,DirectoryIndex 添加index.php. 上面是配置www根目录是apache运行的用户,还需要在 LoadModule php5_module modules/libphp5.so 下面添加一行以支持php解析: AddType application/x-httpd-php .php 保存后,因为刚刚已经启动了apache,所以要重启一下 service httpd restart 创建/home/server/data/wwwroot/index.php:

<?php
echo phpinfo();
?>

再访问http://ip:8080/应该就能看到phpinfo的输出了. php作为apache的模块来运行,所以只能看到apache进程,看不到php进程。 12,安装mongodb的php驱动 下载地址:https://github.com/mongodb/mongo-php-driver/archive/master.zip 安装autoconf: apt-get install autoconf 安装 unzip mongo-php-driver-master.zip cd mongo-php-driver-master export PHP_PREFIX="/home/server/app/php/" $PHP_PREFIX/bin/phpize ./configure -with-php-config=$PHP_PREFIX/bin/php-config make make install install成功后提示: Installing shared extensions: /home/server/app/php/lib/php/extensions/no-debug-zts-20121212/ 编辑/home/server/config/php/php.ini,加上 extension="/home/server/app/php/lib/php/extensions/no-debug-zts-20121212/mongo.so" 重启一下apache,再刷新phpinfo页面,可以看到mongodb. 13,安装nginx ./configure --user=www --group=www --prefix=/home/server/app/nginx --conf-path=/home/server/config/nginx/nginx.conf --with-http_stub_status_module --with-http_realip_module --with-http_addition_module --with-http_gzip_static_module --with-http_random_index_module --with-http_sub_module --with-http_dav_module --with-http_ssl_module --with-pcre=../pcre-8.34 make make install –with-pcre后面是pcre的源码,虽然前面已经装过,但在启动nginx时还是可能会报错,提示error while loading shared libraries: libpcre.so.1,按网上其他文章的方法ln做链接也没效果,但编译时指定源码路径解决了这个问题。 编辑/home/server/config/nginx/nginx.conf: 把A下面几行前的#号删除,apache端口改为8080: location ~ \.php$ { proxy_pass http://127.0.0.1:8080; } 再把root路径改为/home/server/data/wwwroot 启动nginx: /home/server/app/nginx/sbin/nginx 访问http://ip,可以看到一样的phpinfo()页面,说明配置成功 接下来配置权限: chown -R www:www /home/server/data/wwwroot/ chown -R mysql:mysql /home/server/data/mysqldata/ mongodb没找到指定用户来运行的方法,以后补上。 14、安装pure-ftpd(http://www.pureftpd.org/project/pure-ftpd)和User manager for PureFTPd(http://machiel.generaal.net/index.php?subject=user\_manager\_pureftpd&button=download): #不拷这些文件,configure会提示找不到mysqlclient cp /home/server/app/mysql/lib/libmysqlclient* /usr/lib/ ./configure --prefix=/home/server/app/pure-ftpd --with-mysql=/home/server/app/mysql/ CFLAGS=-O2 --with-quotas --with-cookie --with-virtualhosts --with-diraliases --with-sysquotas --with-ratios --with-altlog --with-paranoidmsg --with-shadow --with-welcomemsg --with-throttling --with-uploadscript --with-language=simplified-chinese make make install 把user manager for PureFTPd解压到/home/server/data/wwwroot/ftp下,通过http://ip/ftp/install.php访问安装。 在step3时,会报错,Create table admin Failed! Create table users Failed!无法创建表,这应该是个bug,但一直没解决,估计也不会解决了(V2.1是2005年发布的,都快10年了) 需要自己手动执行sql创建两个表(可以用phpmyadmin,安装过于简单,不介绍): CREATE TABLE IF NOT EXISTS `admin` ( `Username` varchar(35) NOT NULL DEFAULT '', `Password` char(32) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL DEFAULT '', PRIMARY KEY (`Username`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1; CREATE TABLE IF NOT EXISTS `users` ( `User` varchar(16) NOT NULL DEFAULT '', `Password` varchar(32) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL DEFAULT '', `Uid` int(11) NOT NULL DEFAULT '14', `Gid` int(11) NOT NULL DEFAULT '5', `Dir` varchar(128) NOT NULL DEFAULT '', `QuotaFiles` int(10) NOT NULL DEFAULT '500', `QuotaSize` int(10) NOT NULL DEFAULT '30', `ULBandwidth` int(10) NOT NULL DEFAULT '80', `DLBandwidth` int(10) NOT NULL DEFAULT '80', `Ipaddress` varchar(15) NOT NULL DEFAULT '*', `Comment` tinytext, `Status` enum('0','1') NOT NULL DEFAULT '1', `ULRatio` smallint(5) NOT NULL DEFAULT '1', `DLRatio` smallint(5) NOT NULL DEFAULT '1', PRIMARY KEY (`User`), UNIQUE KEY `User` (`User`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1; 一路到step6,复制Step B的文件内容到/home/server/config/pure-ftpd/pureftpd-mysql.conf。装完删除install.php. 复制源代码的configuration-file/pure-config.pl 到/home/server/app/pure-ftpd/sbin/pure-config.pl 编辑,修改第12行${exec_prefix}/sbin/pure-ftpd,改成: /home/server/app/pure-ftpd/sbin/pure-ftpd 其实for里的随便哪行都行,也可以删除只留一行,这里是在这些位置里查找pure-ftpd的安装目录,只留一个对的肯定是最快的,有性能强迫症的同学可以只留一行。 复制configuration-file/pure-ftpd.conf到/home/server/config/pure-ftpd/pure-ftpd.conf,并编辑MySQLConfigFile一行, 去掉#号,修改路径为/home/server/config/pure-ftpd/pureftpd-mysql.conf。 启动Pure-FTPd:/home/server/app/pure-ftpd/sbin/pure-config.pl /home/server/config/pure-ftpd/pureftpd-mysql.conf 启动脚本/root/webserver: #!/bin/bash PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin export PATH export LC_ALL=C # Check if user is root if [ $(id -u) != "0" ]; then printf "Error: You must be root to run this script!\n" exit 1 fi NGINXDAEMON=/home/server/app/nginx/sbin/nginx NGINXPIDFILE=/home/server/app/nginx/logs/nginx.pid MONGODBDAEMON=/home/server/app/mongodb-linux-x86_64-2.4.9/bin/mongod MONGODBCONF=/home/server/config/mongodb/mongodb.conf APACHEPID=/var/run/httpd.pid APACHEDEMON=/home/server/app/apache/bin/httpd MYSQLPID=/home/server/data/mysqldata/mysql.pid MONGOPID=/home/server/data/mongodbdata/mongo.pid PUREPIDFILE="/var/run/pure-ftpd.pid" PURECONFIGPL="/home/server/app/pure-ftpd/sbin/pure-config.pl" PURECONFIGFILE="/home/server/config/pure-ftpd/pure-ftpd.conf" function_start() { echo "Starting Nginx" if test -e "$NGINXPIDFILE";then nginx_pid=`cat "$NGINXPIDFILE"` #如果pid存在,且进程活着 if (kill -0 $nginx_pid 2>/dev/null);then echo "Nginx is Running" else $NGINXDAEMON fi else $NGINXDAEMON fi echo "Starting Mongodb" if test -e "$MONGOPID";then mongo_pid=`cat "$MONGOPID"` #如果pid存在,且进程活着 if (kill -0 $mongo_pid 2>/dev/null);then echo "Mongodb is Running" else $MONGODBDAEMON --config $MONGODBCONF >>/dev/null fi else $MONGODBDAEMON --config $MONGODBCONF >>/dev/null fi echo "Starting Apache" if test -e "$APACHEPID";then apache_pid=`cat "$APACHEPID"` #如果pid存在,且进程活着 if (kill -0 $apache_pid 2>/dev/null);then echo "Apache is Running" else $APACHEDEMON -k start fi else $APACHEDEMON -k start fi echo "Starting Mysql" if test -e "$MYSQLPID";then mysql_pid=`cat "$MYSQLPID"` #如果pid存在,且进程活着 if (kill -0 $mysql_pid 2>/dev/null);then echo "Mysql is Running" else service mysql start fi else service mysql start fi echo "Starting pureftpd" if test -e "$PUREPIDFILE";then pure_pid=`cat "$PUREPIDFILE"` #如果pid存在,且进程活着 if (kill -0 $pure_pid 2>/dev/null);then echo "pureftpd is Running" else $PURECONFIGPL $PURECONFIGFILE --daemonize >>/dev/null fi else $PURECONFIGPL $PURECONFIGFILE --daemonize >>/dev/null fi } function_stop() { echo "Stoping Nginx" if test -e "$NGINXPIDFILE";then nginx_pid=`cat "$NGINXPIDFILE"` #如果pid存在,且进程活着 if (kill -0 $nginx_pid 2>/dev/null);then kill $nginx_pid else echo "Nginx is not running"; fi else echo "Nginx is not running"; fi echo "Stoping Mongodb" if test -e "$MONGOPID";then mongo_pid=`cat "$MONGOPID"` #如果pid存在,且进程活着 if (kill -0 $mongo_pid 2>/dev/null);then killall mongod else echo "Mongodb is not running"; fi else echo "Mongodb is not running"; fi echo "Stoping Apache" if test -e "$APACHEPID";then apache_pid=`cat "$APACHEPID"` #如果pid存在,且进程活着 if (kill -0 $apache_pid 2>/dev/null);then $APACHEDEMON -k stop else echo "Apache is not running"; fi else echo "Apache is not running"; fi echo "Stoping Mysql" if test -e "$MYSQLPID";then mysql_pid=`cat "$MYSQLPID"` #如果pid存在,且进程活着 if (kill -0 $mysql_pid 2>/dev/null);then service mysql stop else echo "Mysql is not running"; fi else echo "Mysql is not running"; fi echo "Stoping pureftpd" if test -e "$PUREPIDFILE";then pure_pid=`cat "$PUREPIDFILE"` #如果pid存在,且进程活着 if (kill -0 $pure_pid 2>/dev/null);then kill $pure_pid else echo "pureftpd is not running"; fi else echo "pureftpd is not running"; fi } function_status() { if test -e "$NGINXPIDFILE";then nginx_pid=`cat "$NGINXPIDFILE"` #如果pid存在,且进程活着 if (kill -0 $nginx_pid 2>/dev/null);then echo "Nginx is running"; else echo "Nginx is not running"; fi else echo "Nginx is not running"; fi if test -e "$MONGOPID";then mongo_pid=`cat "$MONGOPID"` #如果pid存在,且进程活着 if (kill -0 $mongo_pid 2>/dev/null);then echo "Mongodb is running"; else echo "Mongodb is not running"; fi else echo "Mongodb is not running"; fi if test -e "$APACHEPID";then apache_pid=`cat "$APACHEPID"` #如果pid存在,且进程活着 if (kill -0 $apache_pid 2>/dev/null);then echo "Apache is running"; else echo "Apache is not running"; fi else echo "Apache is not running"; fi if test -e "$MYSQLPID";then mysql_pid=`cat "$MYSQLPID"` #如果pid存在,且进程活着 if (kill -0 $mysql_pid 2>/dev/null);then echo "Mysql is running"; else echo "Mysql is not running"; fi else echo "Mysql is not running"; fi if test -e "$PUREPIDFILE";then pure_pid=`cat "$PUREPIDFILE"` #如果pid存在,且进程活着 if (kill -0 $pure_pid 2>/dev/null);then echo "pureftpd is running"; else echo "pureftpd is not running"; fi else echo "pureftpd is not running"; fi } if [ "$1" = "start" ]; then function_start elif [ "$1" = "stop" ]; then function_stop elif [ "$1" = "restart" ]; then function_stop function_start elif [ "$1" = "status" ]; then function_status else printf "Usage: /root/webserver {start|stop|restart|status}\n" fi 添加开机启动: vi /etc/rc.local 添加 /root/webserver start 重启生效

画虚线一般写个xml:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="line" >
    <stroke
        android:dashGap="8dp"
        android:dashWidth="8dp"
        android:color="@color/appendrate_divider_color" />
</shape>

其中dashGap是空隙宽度,dashWidth是线的宽度,当dashGap也就是空隙宽度为0时,显示一条实线。然后在background或src中引用,但在android 4.0以上版本中会有BUG,发现不管dashGap设置多大,显示的都是一条实线。 解决方法: 关闭硬件加速。 可以在AndroidManifest.xml时的Application标签加上android:hardwareAccelerated=”false”,这样整件应用都关闭了硬件加速,虚线可以正常显示,但是,关闭硬件加速对性能有些影响,会感觉明显比没关卡。 也可以给虚线的view单独关闭硬件加速:

divider_under_pic.setLayerType(View.LAYER_TYPE_SOFTWARE, null);

今天一个不小心把这两天写的几个java文件给删了,因为为了测试改了其他同事负责的模块的代码,所以没有提交到git,悲剧啊。无意中发现eclipse自带了恢复历史文件功能,实在太强大了。在项目上点右键-从本地历史记录恢复,应该能找到被删除的文件了,还有标记备份时间。 可以在常规-工作空间-本地历史记录设置备份选项。

参考http://www.cnblogs.com/janken/archive/2012/04/05/2432930.html,做了个小修改,实现PHP,JAVA,Objective-c加解密结果相同。 原先Android版的客户端与服务端(PHP)通讯部分内容用DES加密,加密方法:http://www.pocketdigi.com/20121112/940.html 直接拷贝原文的源码,发现结果不同,原因在于,我在java和php里用的IvParameterSpec是动态的,就是key转成byte[],但原文是静态写死的。 上修改后的源码: 先是Base64: Base64.h:

#import 

@interface Base64 : NSObject
+(int)char2Int:(char)c;
+(NSData *)decode:(NSString *)data;
+(NSString *)encode:(NSData *)data;
@end

Base64.m

#import "Base64.h"

static const char encodingTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

@interface Base64()
+(int)char2Int:(char)c;
@end

@implementation Base64

+(NSString *)encode:(NSData *)data
{
    if (data.length == 0)
        return nil;
    
    char *characters = malloc(data.length * 3 / 2);
    
    if (characters == NULL)
        return nil;
    
    int end = data.length - 3;
    int index = 0;
    int charCount = 0;
    int n = 0;
    
    while (index <= end) {
        int d = (((int)(((char *)[data bytes])[index]) & 0x0ff) << 16)
        | (((int)(((char *)[data bytes])[index + 1]) & 0x0ff) << 8)
        | ((int)(((char *)[data bytes])[index + 2]) & 0x0ff);
        
        characters[charCount++] = encodingTable[(d >> 18) & 63];
        characters[charCount++] = encodingTable[(d >> 12) & 63];
        characters[charCount++] = encodingTable[(d >> 6) & 63];
        characters[charCount++] = encodingTable[d & 63];
        
        index += 3;
        
        if(n++ >= 14)
        {
            n = 0;
            characters[charCount++] = ' ';
        }
    }
    
    if(index == data.length - 2)
    {
        int d = (((int)(((char *)[data bytes])[index]) & 0x0ff) << 16)
        | (((int)(((char *)[data bytes])[index + 1]) & 255) << 8);
        characters[charCount++] = encodingTable[(d >> 18) & 63];
        characters[charCount++] = encodingTable[(d >> 12) & 63];
        characters[charCount++] = encodingTable[(d >> 6) & 63];
        characters[charCount++] = '=';
    }
    else if(index == data.length - 1)
    {
        int d = ((int)(((char *)[data bytes])[index]) & 0x0ff) << 16;
        characters[charCount++] = encodingTable[(d >> 18) & 63];
        characters[charCount++] = encodingTable[(d >> 12) & 63];
        characters[charCount++] = '=';
        characters[charCount++] = '=';
    }
    NSString * rtnStr = [[NSString alloc] initWithBytesNoCopy:characters length:charCount encoding:NSUTF8StringEncoding freeWhenDone:YES];
    return rtnStr;
    
}

+(NSData *)decode:(NSString *)data
{
    if(data == nil || data.length <= 0) {
        return nil;
    }
    NSMutableData *rtnData = [[NSMutableData alloc]init];
    int slen = data.length;
    int index = 0;
    while (true) {
        while (index < slen && [data characterAtIndex:index] <= ' ') {
            index++;
        }
        if (index >= slen || index  + 3 >= slen) {
            break;
        }
        
        int byte = ([self char2Int:[data characterAtIndex:index]] << 18) + ([self char2Int:[data characterAtIndex:index + 1]] << 12) + ([self char2Int:[data characterAtIndex:index + 2]] << 6) + [self char2Int:[data characterAtIndex:index + 3]];
        Byte temp1 = (byte >> 16) & 255;
        [rtnData appendBytes:&temp1 length:1];
        if([data characterAtIndex:index + 2] == '=') {
            break;
        }
        Byte temp2 = (byte >> 8) & 255;
        [rtnData appendBytes:&temp2 length:1];
        if([data characterAtIndex:index + 3] == '=') {
            break;
        }
        Byte temp3 = byte & 255;
        [rtnData appendBytes:&temp3 length:1];
        index += 4;
        
    }
    return rtnData;
}

+(int)char2Int:(char)c
{
    if (c >= 'A' && c <= 'Z') {
        return c - 65;
    } else if (c >= 'a' && c <= 'z') {
        return c - 97 + 26;
    } else if (c >= '0' && c <= '9') {
        return c - 48 + 26 + 26;
    } else {
        switch(c) {
            case '+':
                return 62;
            case '/':
                return 63;
            case '=':
                return 0;
            default:
                return -1;
        }
    }
}

@end

DESUtils.h:

#import 
#import 
#import "Base64.h"
@interface DESUtils : NSObject
+(NSString *)decryptUseDES:(NSString *)cipherText key:(NSString *)key;
+(NSString *) encryptUseDES:(NSString *)plainText key:(NSString *)key;
@end

DESUtils.m:

#import "DESUtils.h"

@implementation DESUtils
+(NSString *)decryptUseDES:(NSString *)cipherText key:(NSString *)key
{
    NSString *plaintext = nil;
    
    NSData *cipherdata = [Base64 decode:cipherText];

    unsigned char buffer[1024];
    memset(buffer, 0, sizeof(char));
    size_t numBytesDecrypted = 0;
    CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmDES,
                                          kCCOptionPKCS7Padding,
                                          [key UTF8String], kCCKeySizeDES,
                                          (Byte *)[[key dataUsingEncoding:NSUTF8StringEncoding] bytes],
                                          [cipherdata bytes], [cipherdata length],
                                          buffer, 1024,
                                          &numBytesDecrypted);
    if(cryptStatus == kCCSuccess) {
        NSData *plaindata = [NSData dataWithBytes:buffer length:(NSUInteger)numBytesDecrypted];
        plaintext = [[NSString alloc]initWithData:plaindata encoding:NSUTF8StringEncoding];
    }
    return plaintext;
}
+(NSString *) encryptUseDES:(NSString *)plainText key:(NSString *)key
{

     NSString *ciphertext = nil;
    NSData *textData = [plainText dataUsingEncoding:NSUTF8StringEncoding];
    NSUInteger dataLength = [textData length];
    unsigned char buffer[1024];
    memset(buffer, 0, sizeof(char));
    size_t numBytesEncrypted = 0;
    CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmDES,
                                          kCCOptionPKCS7Padding,
                                          [key UTF8String], kCCKeySizeDES,
                                          (Byte *)[[key dataUsingEncoding:NSUTF8StringEncoding] bytes],
                                          [textData bytes], dataLength,
                                          buffer, 1024,
                                          &numBytesEncrypted);
    if (cryptStatus == kCCSuccess) {
        NSData *data = [NSData dataWithBytes:buffer length:(NSUInteger)numBytesEncrypted];
        ciphertext = [Base64  encode:data];
    }
    return ciphertext;
}
@end

UIView没有setBackgroundImage方法,只有setBackgroundColor,但是图片可以转成UIColor,所以,设置方法:

[[self view] setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:@"bg_player"]]];