首页> android技术

android技术 存档

JTDS的no suitable driver found问题

2013年04月08日 分类目录 :android技术| web技术 0

      去年9月,由于项目需要,调查了一番android平台上通过JTDS直连服务器端的SQL server的技术实现,当时写了篇日志《android通过JTDS直连SQL Server》,之后由于优先度的缘故,相关功能模块的实现一直留到现在。

      这几天在学习相关功能模块的式样书的同时,做了个DEMO原型(上述日志中的DEMO的基础上)来测试一些技术点,在这过程中遇到了些小问题,这里记录一下。

      在我上次调查JTDS的时候,我使用的是jtds-1.2.6版本,因为当时没有把jar包留下备份,所以这次只能重新下载。于是照惯例去jtds项目网站下载jar包,然后看到现在最新版本是1.3,所以就没想太多直接用它了,悲剧也就此产生。当我将它放入原型项目中并运行应用时,Connection无限报NullPointerException,于是开始走Debug调查出问题的地方,最终发现在注册驱动时就已抛出异常(ClassNotFoundException),具体内容为“no suitable driver found”。

try {
 Class.forName(DBDefine.JTDS_NAME);// load the jtds driver
 } catch (ClassNotFoundException e) {
 e.printStackTrace();
 }

       当找到问题之后,我祭出Google大招,开始寻找解决办法,可惜国内外的技术博客、论坛等都没能解决我的问题(虽然相关问题有很多,但是网友给出的解决办法或指出的问题均不适用于我的实际情况)。正当我一筹莫展之时,无意间在jtds项目网站的Discussion中看到一个帖子,这才知道原来jtds1.3是基于jdk7.0的,并不支持jdk6.0,因此改用稍低一点的版本之后就OK了。

      总结,对于终端用户来说,软件越新可能性能等各方面都越好,但是对于开发者来说,更新不一定越好,新版本的依赖情况可能会更严重,还是选择合适的版本更好。

,

android recovery 刷机包制作

2013年04月03日 分类目录 :android技术 0

     我目前的手机是HTC某一代旗舰机one X,它携带了魔声音效系统,但是自我把系统刷成CM10.1之后,就没了这个音效体验,取而代之的是DSP管理器。最近偶然间在网络上看到一国人开发的音效系统——ViPER4Android,就想着试试看效果了(其实这些音效对我来说作用不大,我的耳朵感觉不出区别来)。由于官方建议HTC用户使用手动安装,而我又想要使其FX版和XHIFI版共存,所以就安装官方指南进行安装了。

      其实Viper的手动安装很简单,只是在手机上操作麻烦了点,再加上我喜欢折腾,每个Nighty版都会去刷,所以每次都把内核文件复制进system目录并改权限感觉麻烦了点,也太累了点。于是就想着做一个刷机包,每次刷机之后再把这些文件刷进去就省事多了。功夫不负有心人,经过参考了多篇教程文件以及某些刷机包,终于做出来了。

     由于我制作的是Viper4Android这个音效系统的刷机包,所以这里先介绍下这个套件,简单来说Viper就是一套Android系统上的音效驱动程序,他提供了一些可供自定义调整的参数设置。在开始制作刷机包之前,我们先从官网下载好必要的文件,由于我的刷机包中包含了FX版和XHiFi版,所以2个都要下载,下载后将其解压到一个目录下,方便后续操作。

http://vipercn.com/UploadFile/MySoft/Android/Man_FX_2.2.0.3.zip

http://vipercn.com/UploadFile/MySoft/Android/Man_XHiFi_2.0.0.6.zip

当获取到需要的资源之后,我们就可以开始制作刷机包的准备工作了。首先我们先新建一个文件夹,文件名任意。由于在这个刷机包中,我们需要做的是把一些文件放到/system目录下的相关文件夹里,所以需要在刚才新建的文件夹里创建好目录结构。根据官方手动安装指南,我们需要修改”/system/etc/audio_effects.conf”、“/system/vender/etc/audio_effects.conf”这两个文件(根据rom的不同有可能会有差异,这个请参考官方指南以及自已的rom),因此先根据结构创建好这些文件夹。除此之外,还需要把内核文件放到”/system/lib/soundfx”目录下,将APK文件放到”/system/app”目录下,因此同样先创建好这几个目录。最后的结构如下:

system/app/
system/lib/soundfx/
system/etc/
system/vender/etc/

之后就按照官方指南把相关的文件放入到相应的文件夹中。这样我们的刷机包的基本资源就准备就绪了。

      准备好刷机资源之后,我们需要在system同级目录下创建一个“META-INF”目录,里面将存放我们用到的刷机脚本以及一些签名文件(不知道该如何称呼他们,因为是完成签名之后生成的文件,所以这里姑且称之为签名文件吧)。现在就这个目录进行一些基础介绍,随便找一个刷机包(各位可以参照我下面提供的我自己做的刷机包),进入这个目录后,我们可以看到一个com目录(这个下面会再提到)、”CERT.RSA”、”CERT.SF”、”MANIFEST.MF”,后面3个文件都是我们完成签名之后自动生成的文件,所以不用去理会。接下来进入到com目录中,我们将看到google目录(根据刷机包的不同,可能会还有其他目录,这里先不管其他的),继续进入,看到一个android目录,这种目录结构是一些编程语言(比如android应用的java)所推荐的包结构,进入android目录之后我们将看到2个没有后缀的文件,一个是“update-binary”,另一个是“updater-script”,从文件名就可以看出前者是升级用到的2进制文件,后者是升级脚本。

      前一个文件因为是共通的,所以我们可以从其他刷机包中直接复制过来使用,而后者就需要根据实际情况进行改写了。当然,有时候为了简单也可以从其他刷机包中复制过来进行改写,但是要注意的是像制作我们这样的简单的刷机包时就别拿rom的来参考了。接下来我先贴出我写的脚本,由于是自己使用,所以比较简单,进度显示、文字显示和一些验证功能都省去了。

show_progress(0.500000, 0);
mount("ext4", "EMMC", "/dev/block/mmcblk0p12", "/system");
package_extract_dir("system", "/system");
set_perm(0, 0, 0644, "/system/vendor/etc/audio_effects.conf");
set_perm(0, 0, 0644, "/system/etc/audio_effects.conf");
set_perm(0, 0, 0644, "/system/lib/libv4a_fx_ics.so");
set_perm(0, 0, 0644, "/system/lib/libv4a_xhifi_ics.so");
unmount("/system");

      其中第一句是在recovery界面上显示进度,表示执行好这步之后进度前进50%;第二句是挂载/system目录,使我们可以访问该目录,其中第一个参数时挂载的文件系统,第二个是路径,第三个则是需要挂载的目录,这些参数都需要根据实际情况进行修改,这里不多做介绍;第三句是将刷机包中的system目录解压缩到/system目录下;4~7则是对相关文件进行权限设置,详细参数介绍请参考下面给出的链接文章,我不多做介绍(其实是因为我了解的也不多,不想误人子弟);最后一句则是解除之前的挂载。

      完成上面的操作之后,我们把”META-INF”和”system”目录压缩到一个压缩文件中,格式为zip。之后用下面提供的signapk.jar对其进行签名,由于我们只是自己使用,所以就使用testkey签名就可以了,如需要使用自己的私钥,可以去参考相关资料。下载好签名文件后,对其进行解压,并将之前制成的zip压缩包放到signapk.jar同一目录下,然后使用命令符执行下面的命令(执行前请先使用cd命令进入该目录,否则会找不到signapk.jar),viper.zip是源文件,请改为之前制成的压缩包,viper4andoir.zip则是目标文件,随便写一个就可以了。

java -jar signapk.jar testkey.x509.pem testkey.pk8 viper.zip viper4android.zip

      执行完成之后,我们就可以看到在该目录中生成了一个新的压缩包,名字是我们之前打的目标文件名(在我这里是viper4android.zip),而它正是我们所可以使用的最终刷机包。至此一个简单的刷机包就大功告成了。

参考文章:

  1. Android ROM 定制之 update-script语法介绍
  2. [HOW-TO] Create an update.zip
  3. An introduction to the Edify(Updater-Script) language

使用到的signapk以及我制作的刷机包:

  1. signapk
  2. viper4android(此版本只适用于cm10.1版的htc one x,其他版本切勿使用)

, , ,

Android Bitmap OOM系列(2):利用convertView改良GridView

2012年09月29日 分类目录 :android技术 0

      在上一篇日志《Android Bitmap OOM系列(1):GridView》中,我们已经成功的让GridView跑起来了,但是这是最最原始的实现方式之一,它的效率也是非常之低(我们的图片都是来自于项目中,而且都是微小图片,所以感受不到),一旦图片的分辨率比较大,而且图片数量多的话,应用很容易因为内存爆掉而导致FC(Force close)。这是因为我们在getView方法中始终是new 一个新的View出来,如此一来,一旦有100张图,我们就要new 100次,同时当我们滚动GridView的时候,即使是显示在界面上过的View也会重新new一次。而同时Dalvik虚拟机又未能及时回收已不用的内存,当到达极限时,内存也就理所当然地爆掉了。

      在写getView这个方法中的代码时,我们已经发现,getView有一个参数View(参数名为convertView),在android的ListView、Gridview中,convertView是一个很有用,而且很酷的参数。根据官方文档的解释,它是用来在可能的情况下重用旧的视图的。在使用之前,我们应该先检查这个view不是空的而且是一个适当的类型。所以呢,我们现在就来把getView给改写一下。改写后的代码如下:

View view=null;
if (convertView == null) {
	view = mInflater.inflate(R.layout.gridview, null);
        ImageView imageView = (ImageView) convertView.findViewById(R.id.image);
	imageView.setImageBitmap(bitmapList.get(position));
}else{
        view=convertView
}
return view;

    首先我们判断convertView是否为空,当为空时,就按照原来的逻辑去xml中寻找控件并实例化出来,然后把BItmap设置进ImageView,如果不为空,就直接将convertView赋给view。

    这次的改写就这么简单,当然这个还是简单的形式,因为我们现在只有一个ImageView而已,如果在项目中我们GridView的每一个View都是由多个控件组成(比如一个ImageView和一个TextView),那么我们还需要建一个holder来储存。首先我们需要建一个holder类(我比较喜欢直接写在adapter里作为内部类使用),它只包含2个成员变量

public class Holder{
           public TextView text;
           public ImageView image;
}

然后在getView中使用这个holder,首先我们先实例化Holder为null,然后如同上面那样判断convertView是否为空,并进行相应的实例化操作。所不同的是,这里我们不再需要new 一个ImageView出来了,我们直接把xml中读出来的ImageView赋值给Holder的成员变量image,TextView也一样。然后分别给他们设ImageBitamp和Text,之后把Holder设置到convertView里面去。当convertView不为空的时候,则从convertView中取出相应Holder的视图出来。

View view=null;
Holder holder=null;
if (convertView == null) {
	view = mInflater.inflate(R.layout.gridview, null);
        holder = new Holder();
        holder.image = (ImageView)convertView.findViewById(R.id.image);
	holder.image.setImageBitmap(bitmapList.get(position));
        convertVIew.setTag(holder);
}else{
        view=convertView.getTag();
}
return view;

, , , ,

Android Bitmap OOM系列(1):GridView

2012年09月22日 分类目录 :android技术 0

     在android平台作业至今,bitmap 的out of memory error(OOM)异常是最让人头疼的了,由于我们制造的是设计类应用,所以处处都会与bitmap产生交集。因此,在这个过程中,我们因为性能问题、因为异常处理,因为种种原因,不得不去不断改善bitmap的性能,也因此有了一些小体会、小经验。为了巩固在工作中学得的经验,从这篇日志起,我希望能够将这些经验记录下来,以供将来参考、回顾。

     Android的GridView控件应该算是和BItmap打交道相对较多的了(还有一个gallary),而它也是我工作中接触最多、最深入的控件(没有之一),因此,在这个系列中,我的一切功能都是以它为基础呈现在屏幕中的。GridView通常被人称之为九宫图,它是以m*n的矩阵布局呈现在我们面前,随着要呈现的内容的不断增多,这个矩阵也将越来越大,而随着这个矩阵的变大,我们的内存也将不断感受到压力,一旦没有正确地处理好内存管理,应用就会有崩溃的险情。因此,GridView虽说只是Android众多控件中的一个,但是学好它、用好它,可以极大地提高我们的能力。

      言归正传。在这篇日志中,我们的主要任务是让GridVIew能够跑起来,让它可以显示出图片来,为了简便起见,我们姑且只用android项目中的小绿人,在日后的进阶过程中会陆续涉及到从本地读取图片、从网络读取图片等。我们首先从界面布局开始,首先我们需要在main.xml(也可以根据需求创建自定义layout)中添加一个GridView元素,并赋予它一个独一无二的ID。

    <GridView
        android:id="@+id/gridView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:numColumns="3" >
    </GridView>

但是但有这个还不够,我们还需要创建一个定义gridView每一个格子的具体布局,这里我们创建一个gridview.xml,其根元素是LInearLayout,在这一版中,我们还需要给它定义一个ID,在后面会需要用到。而子元素则是ImageView(因为我们要解决的是OOM问题嘛)。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/ll"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="3dp" >

    <ImageView
        android:id="@+id/image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>

于是,界面设计部分就到这里为止了,接下来是代码部分,而这也是最重要的部分,最有趣的部分。要想让gridView显示出我们想让它显示的内容,我们需要一个adapter来管理它,因此,我们需要新建一个继承自Android提供的BaseAdapter的自定义类,并重写getCount、getView等方法,这里我们定义为GridViewAdapter。为了后面的操作更为方便,我们需要定义2个成员变量,一个是Context,它的作用下面会提到,另一个是容纳所有Bitmap的List,然后在构造函数中初始化它们,之前我曾提到过,在这个版本中为了方便,Bitmap选用了项目默认自带的小绿人,所以在构造的时候需要传一个Context进来,这点是需要说明的。

private final Context mContext;
private final ArrayList<Bitmap> bitmapList;

public GridViewAdapter(Context context) {
	super();
	mContext = context;
	bitmapList = new ArrayList<Bitmap>();
}

然后写一个初始化List的方法,为了体现出GridView的特性,可以把List设置得大一点,这里以100为例。

Bitmap bitmap = BitmapFactory.decodeResource(mContext.getResources(),R.drawable.ic_launcher);
for (int i = 0; i < 100; i++) {
	bitmapList.add(bitmap);
}

至此Adapter的准备工作就结束了,下面来看看Adapter里的几个必须重写的方法。

getCount():这个方法决定了getView(final int position, View convertView, ViewGroup parent) 的循环执行次数,默认为return 0,也就是不执行,我们需要把它改为return List的长度。这里要注意的是,如果List为空,或者size为0,getView也不会执行的,虽然不会报错,但是界面上不会有任何东西。

@Override
public int getCount() {
	return bitmapList.size();
}

getItem(int position):这个方面通常是在写OnItemClickListener时用到的,我们暂时用不到它,所以保持return null就可以了。

@Override
public Object getItem(int position) {
	return null;
}

getItemId(int position) :这个基本不会用到,保持原样吧。

@Override
public long getItemId(int position) {
	return 0;
}

最后是最重头的getView(final int position, View convertView, ViewGroup parent) ,它是一切的核心,也是最奇妙的部分。这里我们先看代码,再来解释:

@Override
public View getView(final int position, View convertView,ViewGroup parent) {
	View view = View.inflate(mContext, R.layout.gridview, null);
	LinearLayout ll = (LinearLayout) view.findViewById(R.id.ll);
	ImageView imageView = (ImageView)ll.findViewById(R.id.image);
	imageView.setImageBitmap(bitmapList.get(position));
	return ll;
}

在这个方法里,第一句是根据xml名字找到View,以便后面寻找到View上面的组件,进行相应的操作。当找到View之后,我们先根据ID取出gridView的根布局,还记得之前在gridview.xml的LinearLayout根元素里定义的ID吧,就是它。找到它之后再根据ID找到ImageView,取到之后,使用ImageView的setImageBitmap方法将前面创建的BItmap的List中的图片设置进去。完成之后return linearlayout就可以了。

完成这些之后,我们的gridView事实上已经能够显示图片了,但是我们还需要把adapter和gridview绑定起来。由于简单原则,这里我直接在activity里操作了。在activity中我们需要做的是在onCreate(Bundle savedInstanceState)方法中实例化GridView——通过main.xml中GridView元素的ID来获得,并实例化一个GridViewAdapter,然后通过gridView的setAdapter()方法将它们绑定起来,这样就完成了。

public void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
	setContentView(R.layout.main);
	gridView = (GridView) findViewById(R.id.gridView);
	GridViewAdapter adapter = new GridViewAdapter(this);
	gridView.setAdapter(adapter);
}

, , , ,

android通过jTDS直连SQL Server

2012年09月20日 分类目录 :android技术 4

      不知不觉距离上一次写技术文章已经快有4个月了,在这4个月间,我在android领域的编码能力有了一个质的提升,也在一些技术领域有了长足的进步,虽然屡屡想将这些进步记录下来,可是每次都由于各种原因没能坚持。今天,借着调查SQL Server连接的问题,尝试着重新拾起技术日志的记录习惯。

       早在进行Java Web培训的时候,就已经听过客户端不要直接与数据库产生交互,必须经过Servlet等中间层的衔接来实现。但是,在实际项目中,经常会由于客户方面、或者其他方面的要求,跳过Servlet直接与数据库进行交互。这不,这次我们的项目就在部分领域要求做如此改动。

       由于Android通过JDBC直接与数据库进行交互在之前都没有尝试过,因此并不确定是否可行,于是我在组长的安排下,做起了相关的调查,并做一个Demo以供参考。由于数据库使用的是Microsoft SQL Server,因此最后将jTDS作为主要调查方向。

什么是jTDS?

       jTDS是一套开源的100%纯Java实现的Microsoft SQL Server(6.5,7,2000,2005,2008) JDBC 3.0驱动程序,同时也支持SyBase(10,11,12,15),它基于FreeTDS实现,目前是SQL Server 和SyBase的最快的JDBC驱动。jTDS 100%兼容JDBC3.0,支持只向前和可滚动、可更新集(ResultSet),完全独立的并发Statement,且实现了全部DatabaseMetaData和ResultSetMetaData方法。

数据库驱动程序

        由于不同的dbms和jdbc驱动是不一样的,因此在编码的时候需要根据实际使用的dbms来选用相应的驱动程序。下面就仅列出部分主流的数据库的驱动程序:

  • MySQL:org.gjt.mm.mysql.Driver
  • postgreSQL:org.postgresql.Driver
  • Oracle:oracle.jdbc.driver.OracleDriver
  • Sybase:com.sybase.jdbc2.jdbc.sybDriver
  • Microsoft SQLServer:net.sourceforge.jtds.jdbc.Driver(开源版)com.microsoft.jdbc.sqlserver.SQLServerDriver(官方版)

       经过以上对jTDS的简单了解之后,下面正式进入android中使用jTDS JDBC驱动程序的教程部分。

        和Java Web项目使用JDBC驱动程序类似,在android中,同样包括了Connection、Statement、ResultSet三个部分。这里我们首先创建一个工厂类,它专门用来管理JDBC的操作,此处姑且命名为DBFactory。然后给DBFactory定义三个成员变量,分别为Connection、Statement和ResultSet。此外还可定四个常量,分别是驱动程序(即上述各数据库的相应驱动)、数据库地址、用户名、密码(用户名和密码仅限于demo使用,在正式项目中需要另外获取)

public final static String JTDS_NAME = "net.sourceforge.jtds.jdbc.Driver";
public final static String SERVER_NAME = "jdbc:jtds:sqlserver://localhost:1433/databasename";
public final static String LOGIN_NAME = "sa";
public final static String LOGIN_PASSWORD = "sa";

接下来,先写一个GetConnection()方法,实现数据库的连接

private Connection getConntection() {

    try {
       Class.forName(JTDS_NAME);// load the jtds driver
    } catch (ClassNotFoundException e) {
              e.printStackTrace();
    }

    try {
        // get the connection of the specified database, username and password
         conn = DriverManager.getConnection(SERVER_NAME, LOGIN_NAME, LOGIN_PASSWORD);
    } catch (SQLException e) {
            e.printStackTrace();
    }
    return conn;

}

      在这段代码中Class.forName()是使用Java的反射机制注册JDBC驱动程序,因为可能会找不到该类(通常是因为没有把jar包放到编译环境中去引起的),因此必须捕获ClassNotFoundException。注册完成之后,使用java.sql.DriverManager来获取数据库连接,传入的参数分别为数据库地址(此处以SQL Server为例),用户名,密码。

      光与数据库取得联系并没有实际意义,它的价值是让我们可以直接从数据库获取数据,接下来就来看看SQL语句执行的方式,此处我们先假设在databasename下面有一张表【test】,我们需要获取该表中的所有数据。

private void selectAll() {
        Statement stmt = conn.createStatement();// create a Statement which can  send SQL to DBMS
                String sql = "SELECT* FROM [Test]";
                rs = stmt.executeQuery(sql); // execute the SQL
                while (rs.next()) {
                   String str =rs.getString(0)+rs.getString(1)+rs.getString(2);
                   list.add(pop);
                   str = null;
                }
}

       在这个方法中, Statement stmt = conn.createStatement();表示创建一个用来执行静态SQL语句的对象,当Statement创建成功之后,我们可以使用它的executeQuery()方法来获取记录集,此处需要传入一句静态SQL语句,并将结果赋值给一个ResultSet,然后遍历ResultSet来获取每一条记录,由于我们检索的是全部记录,因此需要加检索出来的结果集添加到一个List(成员变量)中去,以便于将其显示在界面中(通常是放到ListView里)。

       当SQL语句执行完毕之后,我们应该及时关闭数据库连接(当然,在实际项目中并不一定这样)。

private void close() throws SQLException {
                if (resultSet != null) {
                        resultSet.close();
                }
                if (statement != null) {
                        statement.close();
                }
                if (conn != null) {
                        conn.close();
                }

        }

       至此,android通过jTDS直接连接SQL Server部分的主要代码就结束了,由于只是一个demo,因此我并没有使用任何提高效率的技术,写的是最最简单的代码,在实际应用中,我们还需要加入连接池等技术来提高效率。

       事实上,说是android连接SQL Server,其实这部分操作与平台无关,我们并没有用上任何android特有的类,全部都是jdk中的类,因此,以上代码同样适用于javaSE、javaEE项目。

jTDS下载地址:http://sourceforge.net/projects/jtds/files/

demo项目下载:https://docs.google.com/open?id=0B7J8sQVOiVlyQmQ5RHNoMEJMUUk(压缩包中不包含jtds jar包,请自行另行下载)

, ,

Android中颜色相关类的使用体会

2012年05月23日 分类目录 :android技术 3

       上一次写博客已经是3月初的事情了,这2个多月来,除了毕业论文的忙碌之外,还由于对博客的兴趣不高,所以始终没写过只言片语。今天,论文答辩前的最后狂欢,就这几个月对android.graphics.Color类的使用体会进行小小的总结。

       今年2月,第一次接触到android的开发,我被分配到的第一个工作是制造一个dialog,功能是颜色的选择,就如windows自带画图工具中的颜色选择dialog那样(界面,功能一模一样)。而这一做可谓是一发不可收拾,之后无论是二阶色、渐变效果,或者其他,凡是和颜色有关的组件全都集中到了我的手中。也正因如此,在这段日子的使用中,我对Color类产生了一些小体会,在这作为我android系列的第一篇日志,日后希望能够有机会不断更新我在android开发中的体会。

      根据android的API介绍,我们可知:Color类定义了一些创建和转换颜色int值的方法。android中的Color由4个元素组成:alpha(透明度)、red、green、blue(这三个是我们熟知的三原色)。Color类中的方法使用起来普遍非常之简单,所以没有进行详细介绍用法的必要,我在这里只想说说我对这个类的一些想法。在我对Color类的使用过程中,我一共遇到了2个不舒服的地方:

1.

static int alpha(int color)
Return the alpha component of a color int.

       在Color类中,有一个alpha(int color)的方法,利用这个方法,我们可以通过一个颜色的Int值来算出他的透明度(取值介于0..255),但是,在我的实践中,发现一个问题,这个方法的有效性似乎只限于由Color类创造出来的颜色。在我们的项目中,前人自定义了一个类,它与Color类的不同点在于透明度的取值范围是0..100的百分比,然后利用这个百分数与固体色进行换算出带有透明效果的真实颜色,虽然通过这个方法算出来的颜色能够被android识别,并能正确的现实出来,但是当我希望能够通过alpha(int color)方法重新得出它的透明度时,问题就出来了。虽然颜色能够被识别,但是由于该颜色并非由Color类创建,我通过alpha(int color)方法得到的alpha值永远都是固体色的255。

       我只是个android菜鸟,也没看过android里面的源码(包括sdk的),所以对为什么会出现这种情况不得而知。不过幸好,对于纯正的android开发来说,一般不会像我所遇到的使用自定义的计算方式来得到真实颜色的(由于我做的是移植工作,所以对于原项目中提供的类和方法,我不得不优先采用,即使sdk中已经有了相同功能的类库)。

2.

static int argb(int alpha, int red, int green, int blue)
Return a color-int from alpha, red, green, blue components.

    在我的项目中,还有一个颜色选择功能是上述功能的简版,即在默认提供的8个固体色中选择需要使用的颜色,并在文本框中设置百分比透明度,然后内部进行计算得出真实颜色。原先我预备使用的是Color类自有的方法,也就是argb(int alpha,int red,int green,int blue)来得到真实颜色,但是在使用过程中,我发现这一方法的使用体验很差,由于该方法是通过传入四个必备元素进行计算,我不得不再通过Color类提供的另外3个类来获得选中颜色的三原色数值,然后再重新算出真实颜色。

static int blue(int color)
Return the blue component of a color int.
static int green(int color)
Return the green component of a color int.
static int red(int color)
Return the red component of a color int.

       虽然这种操作在使用阶段问题并不大,性能的损耗也有限,但是对于写代码的人来说,却是很难受的。通常来说,我们有2种选择,1是定义3个临时变量来接三原色,然后连同alpha一同传入argb()方法,另一种是不显式定义临时变量,在使用argb方法时,在三原色的位置使用三原色的计算方法替代。无论是哪一种,都让代码的阅读产生不悦感。不知道为什么Color类为什么不直接提供个将alpha值和固体色Int值进行计算的方法呢?

      不过幸好,类似的功能在android.graphics.drawable.ColorDrawable中也有提供,而且相对比较简单。我们所需要做的是构造一个ColorDrawable类,带参不带参皆可,然后使用setColor()方法把颜色设置进去,再使用setAlpha()将alpha通道的值设进去。这样我们就可以得到一个加入了alpha值的颜色,在使用时,我们可以直接把ColorDrawable设置到paint里面去,也可以利用getColor()获得颜色的int值并加以使用。

       关于Color类的使用体会就谈到这了,对于编程技术文章来说,没有贴代码、没有截图辅佐应该算是不合格的吧?不过,正如我开篇所说,这篇日志的目的并非介绍技术,只是使用体会的存档,分享。望见谅!

, ,

Android应用项目目录结构一览

2012年02月05日 分类目录 :android技术 1

       在上一篇日志(Android应用开发环境搭建指引)中,我们搭建了一个Android应用开发环境,其中我们选用了官方提供支持的Eclipse平台作为集成开发环境。今天,我们将以经典的Hello World项目来熟悉Eclipse中创建的Android项目的目录结构及其作用。

一 创建Hello World项目

       Andorid项目创建三种方式:

  1. 菜单栏File->New->Android Project
  2. 工具栏Open a Wizard to help create a new android project图标
  3. 左侧Package Explorer窗体中右键弹出窗口New->Android Project

      无论通过上述3种方式中的哪种都会进入同一个Android 项目创建引导过程,因此,这一步就看个人习惯了。

当我们进入到Android Protect创建过程中后,我们将首先见到这个节目,一般来说,我们需要做的仅仅是在ProjectName处输入项目名字,然后按Next进入下一步。

这一步的任务是选择一个构建目标,其中Android平台为必选项,如果你的Android SDK中有多个SDK版本,选择其中一个就可以了。

继续下一步,这步我们需要指定一个PackageName,根据Java的命名习惯,包名为域名的倒写+项目名,如我的网站域名为wangqige.com,则包名为com.wangqige.helloworld。此外,如果需要创建一个测试项目来做Android项目测试的话,则需要勾上Create a Test Project。最后点Finish就可以了。

二    Android项目目录结构说明

Android Project目录主要由src、gen、res、AndroidManifest.xml几部分组成。除此之外还有一些文件及目录是我们暂时不需要接触或不会接触到的。接下来依次来看看各目录、文件的主要功效:

1)src目录,顾名思义,该目录是我们主要接触的,我们的应用源代码均被置于该目录下。

2)gen,此为Android自动生成文件夹,里面含有一个非常重要的.java文件——R.java,它是我们的代码和资源文件互相产生联系的重要依据。因此不可改动、不可删除该文件。

3)res目录,这是存放资源文件的地方。里面主要包括drawable、layout、values三个目录。

    1.drawable目录放置图片资源,在Android2.1以上该目录将细分为drawable-hdpi、drawable-ldpi、drawable-mdpi,这三个目录分别放置不同分辨率的图片资源。对于刚刚接触Android开发的我们,目前还不需要根据不同分辨率配置图片,因此只需要一个drawable就够了。

    2.layout目录放置Android应用布局XML文件,其中有一个main.xml,显然这是最主要的布局文件了。当然,在实际开发中,没有main.xml也不要紧,只需要程序能够正确加载到需要的布局文件就可以了。

    3.values目录主要放置文本资源文件,通常用于文本内容的国际化,以及避免出现硬编码(即在代码中直接编写文本内容)。

4)在这些文件夹之外,我们还需要注意AndroidManifest.xml,这是Android项目的核心。如果我们的应用需要获得特殊权限(例如发信息)则必须在该文件中进行声明以获得权限,此外,当我们的应用有多个Activity的时候,我们也需要将所有Activity在该文件中进行声明。

    事实上,以上这些只是默认生成的内容,根据我们的不同需要,我们还可以创建额外的目录来放置相关资源。而像AndroidManifest.xml以及这里我并未提及到的proguard.cfg、project.properties也都还有许多功能,这需要我们根据需求去进一步挖掘。

, , , , , ,

Android应用开发环境搭建指引

2012年02月04日 分类目录 :android技术 0

       由于工作的缘故,现在开始全面进入Android应用开发领域了。之所以在标题上加上“应用”两字,是因为本文基于Windows平台撰写,而Windows 平台无法进行Android编译,因此只能进行应用开发。如果还需要接触Android 源代码的话建议在Linux环境上搭建开发平台。

一    基础资源下载安装:

  1. 安装JDK6以上版本,推荐安装JDK6.0.27,这个版本比较稳定。下载地址为:http://www.oracle.com/technetwork/java/javase/downloads/index.html

            安装的时候建议直接安装在根目录下,不要安装在默认的Program Files目录下。之所以这样是因为Android是基于Linux的,Linux路径不支持空格字符,所以可能会产生问题

  2. 下载Eclipse, 推荐下载Eclipse for java developers版,下载地址:  http://www.eclipse.org/downloads/ (64位系统用户请下载对应版本)
  3. 下载Android SDK,推荐下载安装版,下载地址:http://developer.android.com/sdk/index.html
  4.         同样建议安装在根目录下,不要安装在Program Files目录下。

二    系统环境变量配置:

  1. JDK的配置请参阅《配置Java编译环境
  2. 在PATH中配置Android SDK工具,添加以下两个目录:X:\android-sdk\platform-tools;X:\android-sdk\tools。注:“X:\”部分请根据实际情况修改

        配置完之后打开CMD,输入java -Version 和android -h两个命令,检查是否配置成功。

三    Android SDK下载:

        之前我们已经安装了Android SDK,但是事实上里面是空的,我们并没有下载SDK,现在我们在准备工作完成的基础上可以下载SDK了。打开SDK Manager.exe,当Fetching完了之后我们可以看到列表中有一系列的资源可供下载:

       其中Tools文件夹中的2个必须安装,下面的N多不同版本的Android SDK则选其一即可,目前最新的是Android 4.0.3,但是对于我们来说,这个并不需要跟进,选择装机量较大的2.2或2.3即可。等将来4.0成为主流后再跟进也不迟。

四    ADT For Eclipse下载安装

       启动Eclipse(Win7用户请使用管理员身份),进入插件安装对话框(Menu栏Help->Install New Software)

        在地址栏输入 https://dl-ssl.google.com/android/eclipse/,并按回车键,稍等一会就会加载出可安装插件列表,全部安装上吧。

这里还有一点需要注意的,由于安装ADT的时候还需要一些依赖插件,因此必须确保Available Software site列表中http://download.eclipse.org/releases/indigo(旧版本eclipse用户请把indigo修改为相应版本)处于选中状态,如果列表中没有则自行ADD一个。

安装完成后重启Eclipse,启动后应该会弹出一个android sdk的配置窗口,把其中sdk路径改为之前安装的路径即可。

五    Android模拟器配置

        为了方便开发者进行调试,Android SDK还提供了一个模拟器工具,我们编译好的Android应用可以直接在这个模拟器中进行测试,而不需要放到真机上。打开AVD Manager工具,点New按键,进行简单的配置之后就可以创建出一个模拟环境了。

 

后记

        至此,Windows下Android应用开发环境就搭建好了,快去创建一个Hello World项目体验一下吧。

, , ,

将me501升级到android2.3系统

2011年03月15日 分类目录 :android技术 24

不知是不是折腾上瘾来了,不久前才刚刚从android1.5刷到android2.1,昨天就又折腾上android2.3了。刷之前在android论坛里看了不少贴,发现普遍都说这个版本做得很好,所以就心痒痒起来了,总体来说这次刷机还是非常的顺利的,这里写下一些我关于这次的版本的感觉。

这次我刷的不再是网友基于moto制作的rom包的修改版,而是彻头彻尾的第三方rom,经常关注android系统的人一定知道(至少听说过)CyanogenMod这个第三方android ROM制作组织,他们做的rom在全球范围内都非常受人喜欢,许多android手机入机后第一件事便是将原版系统更换成他们制作的版本。

从网友那得到的反馈,这一版本基本没什么严重影响我们使用体验的Bug,而且比一些2.1、2.2版本运行更流畅,尤其是对于像我这样的低端手机(moto me501)来说,它的流畅度更是优于moto 官方的1.5版,因此,对于me501用户来说,我非常推荐大家刷这个系统。

在刷android2.3之前,请先确定已经获得了手机的root权限,me501用户如果还没获取root权限,请先浏览《从一而终搞定me501刷android 2.1》中有关刷root权限的部分。

当你获取到root权限之后,让我们正式进入android2.3时代。

首先将刷2.3需要用到的两个压缩包下载并放到sd卡根目录下:wipedatacachesystem.zipGingerXT-rel9.zip。注:由于之前有多人按照我的日志里说的来刷机,但是始终停留在moto标志界面而联系我寻求帮助,最后发现是他们rom包下载错误,因此请在下载后确认压缩包大小,如果发现下载到的文件远小于网页上所显示的大小,请尝试重新下载。

将这两个压缩包放到sd卡中之后,重启手机并进入工程模式(当看到moto标志时按住照相键),出现黑屏+小字后按音量键“-”,然后滑动触摸板选择flash zip from sd,先刷wipedatacachesystem.zip,刷完后再刷GingerXT-rel9.zip,都刷完之后重启手机就行了,第一次进入系统时可能会在moto标志那停留很久,请不要担心(我差点因为这拔电池了,惭愧)。

下面先奉上几张截图,以觞各位看官:

接下来要说的是我们刷机完成后的一些注意事项,这也是本文最重要的部分(刷机过程由于和之前那篇日志中刷2.1系统有所重叠,所以没有细说):

  • 刷机完成之后第一件事情先将手机的时区调整到中国标准时间(设置—日期与时间,然后把自动那里的勾去掉,再在选择时区那里找到中国标准时间)
  • 然后安装一个电子市场,默认包中并没带google应用包,所以需要的朋友得自己去下。我虽然手机上安装了国内的安卓市场,但是从我的体验来看,它做得并不好,更新缓慢,我从市场里下载到的qq输入法竟然不是最新版。这里我推荐大家在电脑上安装豌豆荚,我们可以通过它在电脑上下载安装手机应用,非常方便且节约时间。
  • 在之前我们不得不安装一个apn控制程序来控制数据流量,而这个rom已经自带该功能,因此不必再费心安装了
  • 此包默认没有中文输入,所以请下载并安装中文输入法程序
  • 通讯录中没有记录,因此请从sim卡中导入(在通讯录界面按菜单键)
  • 窗口小插件似乎只支持安装在手机内存中的程序,因此像墨迹天气这样的有窗口小插件的程序建议安装在手机内存
  • 喜欢超频的人不必再安装setCPU,rom内置CPU设置功能(位于CM设置中)

对我而言,似乎智能手机的乐趣便是不断地刷机了,智能手机的娱乐功能早已被我的itouch4所剥夺,它只剩下了通信+在无wifi环境下上网聊QQ和看新闻的功能。从某种程度来说,我使用智能手机有点暴敛天物了。

, , ,

让android2.x安装程序到SD卡

2011年03月02日 分类目录 :android技术 2

现阶段的智能手机默认情况下都是将程序安装在手机内存(ROM)中,如果是像iphone这样有几个G、乃至于几十个G的话,我们没有什么感觉。但是像ME501这样的中低端手机,手机内存只有可怜的几百MB,如果我们装的程序多点(来一两个体积较大的游戏)的话,那就糟糕了。幸好,android2.0之后就允许我们把程序安装到SD卡上了。

在昨天的《从一而终搞定me501刷android2.1》中最后曾提到过在完成刷机后可以选择对SD卡进行分区或直接重启进入系统,本文中就将介绍SD卡分区并为手机设置默认程序安装到SD卡的过程。和之前那篇日志一样,本文仅是对网上已有资料的一个汇总、整理而已。

wait!wait!wait!怎么进到这个界面?如果在开机见到moto标志时按住照相键,等出现小字时按“音量-”键就行了。

当我们刷好机之后,选择Partition SD开始对SD卡进行分区:

点进去之后选择partition SD,然后是提示是否格卡!继续点确认

下一步选择分区大小(建议设为96就可以了,不能再大了)确认后提示为ext2—-512M(可根据需要进行调整,这就是你今后存文件程序的地方),2G的可以直接确定,2G以下的,酌情按上下键调整ext-2大小,以免fat32分区容量太低)然后再按确定键出现partitioning sdcard,大约半分钟后即出现partitioning complete。

完成后重启手机进入系统,如果刷的是我在前一篇文章中所使用的那个ROM包的话,接下来的操作会非常之简单。

在手机里的应用程序中找到GScript Mod,里面自带了许多实用的命令,这里我们需要用到的是Enable Apps2SD和Move Dalvik-cache to SD,依次运行他们,第一次运行时会弹出root权限申请,只要授予权限就行了,全部完成之后,我们rom中的空间就会变大了。

如果你刷的包里没有这个GScript Mod,那可以安装app2sd小工具(http://u.115.com/file/f4c4e16d7b),依次选择move apps to SD和Move dalvik-cache to sd两项。

下图是我现在手机内存使用情况:

,