Android开发总结

    最近在做一些Android的程序,开发一个我们一个系统的手持端。虽说在2007Android平台刚刚推出的时候我就做过一些上面的开发,但是现在已经是2.3最新版本了,Android还是有大量的变化的,因此跟从头学起的差别不是很大。我并不想在这里教会别人怎么去开发,教程网上太多了,只是对于我用到的东西做一点总结,概略而不缺失难点的细节。

 

  1. 基本开发方法
    Android开发一般使用的环境是Eclipse,安装AndroidSDKADT插件,值得注意的是我在安装的过程中出想过只安装了2.2版本的SDK,于是开发只能使用这一版本的问题,希望朋友注意,最好能够安装一个比较全的版本。
    新建项目之后,会有项目的目录结构,AndroidManifest.xml文件是整个软件的配置文件,在这其中,一般需要配置的是程序需要的权限,语法格式如下:
        <uses-permission android:name="android.permission.INTERNET" />
        <uses-permission android:name="android.permission.RESTART_PACKAGES"/>
    你生成的apk文件在安装时会给用户提示是否授予这些权限,如果不在这个文件里说明,使用到诸如网络通讯、访问通讯录等功能时就会报错。
    activity也配置在这其中,比如:
    <activity android:name=".MainActivity"
            	android:label="@string/main_title">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
    可以设置Activity的标题,对应的类名等属性,新添加一个Activity就需要这里加入这个Activity的说明。
    然后,我们可以在res文件夹下的values文件夹下的strings.xml文件中定义我们自己想要的常量,在layout文件夹下定义界面的布局,就可以进行具体代码的开发工作了。
  2. Android上的数据存储
    Android上有多种数据存储方式,包括:
    a) 使用SharedPreferences。这种方式以NVP(键值对)的形式存储,而最终会存储到你定义的一个XML文件中,具体的方法可以搜索下相关资料,非常简单
    b)
    文件存储数据。Android的文件存储跟普通JAVA的文件存储一样,使用流的形式。
    c) SQLite
    数据库存储数据,类似于数据库表形式的存储方法,非常方便,因为精简,所以比普通的SQL还要舒服些。主要通过继承自SQLiteOpenHelper的一个类来实现创建删除数据库的操作,对应的增删改查在SQLiteDatabase中都有对应的接口,通过SQLiteOpenHelper子类的getReadable/WritableDatabase()方法获取。有趣的是除非空间已满和指定只读外,这两个方法获取的操作对象是一样的,而且我感觉这个方法获取的是缓冲池形式的操作对象,比如:
      SQLiteDatabase a = getReadableDatabase();
      SQLiteDatabase b = getReadableDatabase();
      b.close();
      a.query(...)  //此处操作a可能会报已关闭的错误。
    具体是否是这样的我没有仔细探究,我是在系统中维护另一个单例的SQLiteDatabase对象出现了类似的错误,所以推测内部实现是如此的。
    d)
    使用ContentProvider存储数据,一般用于程序之间共享数据。
    e)
    网络存储数据。
    此处需要额外说明的是我们在程序中通常会使用配置页面,Android提供了一个非常简单的实现方式,继承自
    PreferenceActivity的类可以用于设置参数界面,其配置文件为"PreferenceScreen"标签。这部分的参数存储和现实都不需要手动控制,会自动使用SharedPreferences进行存储和修改,界面也不用编写,一个简单的示例如下所示:
    <?xml version="1.0" encoding="utf-8"?>
    <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
        <PreferenceCategory android:title="自动操作设置">
            <CheckBoxPreference
                android:key="AutoDelBeforeDownload"
                android:title="下载时自动清空原始记录"
                android:defaultValue="false"
            />
            <CheckBoxPreference
                android:key="AutoDelAfterUpload"
                android:title="上传时自动删除成功记录"
                android:defaultValue="false"
            />
        </PreferenceCategory>
        <PreferenceCategory android:title="远程服务地址设置">
    	    <EditTextPreference
    	        android:key="ServerIP"
    	        android:title="设置远程服务IP地址"
    	        android:summary="点击输入"
    	        android:dialogTitle="远程服务IP地址设置"
    	        android:defaultValue="192.168.30.223"
    	    />
    	    <EditTextPreference
    	        android:key="ServerPort"
    	        android:title="设置远程服务端口"
    	        android:summary="点击输入"
    	        android:dialogTitle="远程服务地址设置"
    	        android:defaultValue="8080"
    	    />
        </PreferenceCategory>
    </PreferenceScreen>
    在界面类中的onCreate()函数中添加如下代码即可:
      addPreferencesFromResource(R.xml.preferences);
    如果需要,可以重载onKeyDown()方法来在界面退出的时候设置系统环境变量,代码示例如下:
    	@Override
    	public boolean onKeyDown(int keyCode, KeyEvent event){
    		if(keyCode == KeyEvent.KEYCODE_BACK){
    			ConfigProcessor.getContextConfig(this);
    			return super.onKeyDown(keyCode, event);
    		}else{
    			return super.onKeyDown(keyCode, event);
    		}
    	}
  3. KSOAP2的使用
    由于我所做的程序是依托现有系统实现了,因此一些数据要从现有的系统中去读取并返回一些数据,经过一些比较,选择了Web Service作为通讯工具。Android上对于Web Service的支持也比较好,KSOAP2是一个常用的包。当然,开发时要将ksoap2-android-assembly-2.4-...这个jar包引入到系统中。在使用的时候比较简单,代码示例如下:
    try {
    			SoapObject rpc = new SoapObject(MobileConstant.NAMESPACE,
    					MobileConstant.CHANGE_METHOD_NAME);
    			rpc.addProperty("arg0", MobileTools.joinStr(oids, "#$%"));
    			rpc.addProperty("arg1", "已关闭");
    			SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
    					SoapEnvelope.VER11);
    			AndroidHttpTransport ht = new AndroidHttpTransport(MobileContext
    					.getInstance().getService_URL());
    
    			envelope.bodyOut = rpc;
    			envelope.setOutputSoapObject(rpc);
    			ht.call(null, envelope);
    			SoapObject result = (SoapObject) envelope.bodyIn;
    			int cnt = result.getPropertyCount();
    			if (cnt > 0) {
    				int changeNum = Integer.valueOf(result.getProperty(0)
    						.toString());
    				if (changeNum == oids.length) {
    					if (MobileContext.getInstance().isAutoDelAfterUpLoad()) {
    						mdb.deleteByOid(oids);
    					}
    					new AlertDialog.Builder(this)
    							.setMessage(changeNum + "条数据信息全部上传成功!")
    							.setTitle("成功")
    							.setNeutralButton("关闭",
    									new DialogInterface.OnClickListener() {
    										public void onClick(
    												DialogInterface dlg, int sumthin) {
    										}
    									}).show();
    				} else {
    					new AlertDialog.Builder(this)
    							.setMessage(
    									oids.length + "条数据需要上传,成功上传" + changeNum
    											+ "条。")
    							.setTitle("提示")
    							.setNeutralButton("关闭",
    									new DialogInterface.OnClickListener() {
    										public void onClick(
    												DialogInterface dlg, int sumthin) {
    										}
    									}).show();
    				}
    			} else {
    				new AlertDialog.Builder(this)
    						.setMessage("用户名或密码错误!")
    						.setTitle("错误")
    						.setNeutralButton("关闭",
    								new DialogInterface.OnClickListener() {
    									public void onClick(DialogInterface dlg,
    											int sumthin) {
    									}
    								}).show();
    			}
    		} catch (Exception e) {
    			new AlertDialog.Builder(this)
    					.setMessage("远程服务请求失败,请检查网络连接或联系系统管理员!")
    					.setTitle("错误")
    					.setNeutralButton("关闭",
    							new DialogInterface.OnClickListener() {
    								public void onClick(DialogInterface dlg,
    										int sumthin) {
    								}
    							}).show();
    		}
    具体的解释就不多做了,包括SharedPreferences的使用都在里面了。
    此处遇到的还未解决的问题包括向服务器提交String[]形式的参数报错的问题,和如果服务不存在超时的问题。前者我不知道是否有办法解决,现在是用一个间隔符划分的字符串代替了数组的传输,后者应该加上一个多线程的进度条来实现比较好。如果有谁解决过这方面的问题,还请指教~
  4. 二维条形码的读取
    在设备上分配了一个唯一的编号,然后生成一个二维条形码,贴在机器上。这样,要求我们的手持程序可以解析二维条形码,读出其中的信息,Android上解读条形码的应用非常的简单,只需要同时安装一个BarcodeScanner.apk软件,在我们的程序里进行调用就可以了,调用代码如下:
    	private void doScanner() {
    		final boolean scanAvailable = MobileTools.isIntentAvailable(this,
    				"com.google.zxing.client.android.SCAN");
    		if (scanAvailable == false) {
    			new AlertDialog.Builder(this)
    					.setMessage("请先安装BarcodeScanner组件!")
    					.setTitle("提示")
    					.setNeutralButton("关闭",
    							new DialogInterface.OnClickListener() {
    								public void onClick(DialogInterface dlg,
    										int sumthin) {
    								}
    							}).show();
    			return;
    		}
    		Intent scannerIntent = new Intent(
    				"com.google.zxing.client.android.SCAN");
    		startActivityForResult(scannerIntent, 100);
    	}
    
    	public void onActivityResult(int requestCode, int resultCode, Intent intent) {
    		if (requestCode == 100) {
    			String resultStr = "读取失败";
    			if (resultCode == RESULT_OK) {
    				String contents = intent.getStringExtra("SCAN_RESULT");
    				String format = intent.getStringExtra("SCAN_RESULT_FORMAT");
    				resultStr = contents + "   " + format;
    			} else if (resultCode == RESULT_CANCELED) {
    				resultStr = "读取失败";
    			}
    			new AlertDialog.Builder(this)
    					.setMessage(resultStr)
    					.setTitle("条形码读取结果")
    					.setNeutralButton("关闭",
    							new DialogInterface.OnClickListener() {
    								public void onClick(DialogInterface dlg,
    										int sumthin) {
    								}
    							}).show();
    		}
    	}
    其中isIntentAvailable()函数用于验证某个需求的组件是否已经存在,其实现代码如下:
    	/**
    	 * Indicates whether the specified action can be used as an intent. This
    	 * method queries the package manager for installed packages that can
    	 * respond to an intent with the specified action. If no suitable package is
    	 * found, this method returns false.
    	 *
    	 * @param context The application's environment.
    	 * @param action The Intent action to check for availability.
    	 *
    	 * @return True if an Intent with the specified action can be sent and
    	 *         responded to, false otherwise.
    	 */
    	public static boolean isIntentAvailable(Context context, String action) {
    		final PackageManager packageManager = context.getPackageManager();
    		final Intent intent = new Intent(action);
    		List<ResolveInfo> list = packageManager.queryIntentActivities(intent,
    				PackageManager.MATCH_DEFAULT_ONLY);
    		return list.size() > 0;
    	}
     

你可能感兴趣的:(数据结构,应用服务器,android,网络应用,配置管理)