zoukankan      html  css  js  c++  java
  • Android入门总结

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

    1. 基本开发方法
      Android开发一般使用的环境是Eclipse,安装Android的SDK和ADT插件,值得注意的是我在安装的过程中出想过只安装了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进行存储和修改,界面也不用编写,一个简单的示例如下所示:
      1 <?xml version="1.0" encoding="utf-8"?>
      2 <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
      3 <PreferenceCategory android:title="自动操作设置">
      4 <CheckBoxPreference
      5 android:key="AutoDelBeforeDownload"
      6 android:title="下载时自动清空原始记录"
      7 android:defaultValue="false"
      8 />
      9 <CheckBoxPreference
      10 android:key="AutoDelAfterUpload"
      11 android:title="上传时自动删除成功记录"
      12 android:defaultValue="false"
      13 />
      14 </PreferenceCategory>
      15 <PreferenceCategory android:title="远程服务地址设置">
      16 <EditTextPreference
      17 android:key="ServerIP"
      18 android:title="设置远程服务IP地址"
      19 android:summary="点击输入"
      20 android:dialogTitle="远程服务IP地址设置"
      21 android:defaultValue="192.168.30.223"
      22 />
      23 <EditTextPreference
      24 android:key="ServerPort"
      25 android:title="设置远程服务端口"
      26 android:summary="点击输入"
      27 android:dialogTitle="远程服务地址设置"
      28 android:defaultValue="8080"
      29 />
      30 </PreferenceCategory>
      31 </PreferenceScreen>

      在界面类中的onCreate()函数中添加如下代码即可:
        addPreferencesFromResource(R.xml.preferences);
      如果需要,可以重载onKeyDown()方法来在界面退出的时候设置系统环境变量,代码示例如下:

      1 @Override
      2 public boolean onKeyDown(int keyCode, KeyEvent event){
      3 if(keyCode == KeyEvent.KEYCODE_BACK){
      4 ConfigProcessor.getContextConfig(this);
      5 return super.onKeyDown(keyCode, event);
      6 }else{
      7 return super.onKeyDown(keyCode, event);
      8 }
      9 }
    3. KSOAP2的使用
      由于我所做的程序是依托现有系统实现了,因此一些数据要从现有的系统中去读取并返回一些数据,经过一些比较,选择了Web Service作为通讯工具。Android上对于Web Service的支持也比较好,KSOAP2是一个常用的包。当然,开发时要将ksoap2-android-assembly-2.4-...这个jar包引入到系统中。在使用的时候比较简单,代码示例如下:
      try {
      SoapObject rpc
      = new SoapObject(MobileConstant.NAMESPACE,
      MobileConstant.LOGIN_METHORT_NAME); //设置namespace和方法名称
      rpc.addProperty(
      "arg0", lName);  //设置参数
      rpc.addProperty(
      "arg1", pass);
      SoapSerializationEnvelope envelope
      = new SoapSerializationEnvelope(
      SoapEnvelope.VER11);
      AndroidHttpTransport ht
      = new AndroidHttpTransport(MobileContext
      .getInstance().getService_URL()); //wsdl的url

      envelope.bodyOut
      = rpc;
      envelope.setOutputSoapObject(rpc);
      ht.call(
      null, envelope);
      SoapObject result
      = (SoapObject) envelope.bodyIn;
      int cnt = result.getPropertyCount();
      if (cnt > 0) { //服务的返回值是一个数组,第一个元素是oid,第二个是用户的显示名
      String userOID
      = result.getProperty(0).toString();
      String userShowName
      = result.getProperty(1).toString();
      // 保存必须的上下文信息。
      MobileContext.getInstance().setLoginName(lName);
      MobileContext.getInstance().setUserOID(userOID);
      MobileContext.getInstance().setUserShowName(userShowName);
      // 保存用户名密码到文件
      SharedPreferences preferences = PreferenceManager
      .getDefaultSharedPreferences(
      this);
      SharedPreferences.Editor editor
      = preferences.edit();
      if (cb_isSave.isChecked()) {
      editor.putString(
      getResources().getString(R.string.saved_name),
      lName);
      editor.putString(
      getResources().getString(R.string.saved_password),
      pass);
      }
      else {
      editor.putString(
      getResources().getString(R.string.saved_name),
      "");
      editor.putString(
      getResources().getString(R.string.saved_password),
      "");
      }
      editor.commit();
      return true;
      }
      else {
      new AlertDialog.Builder(this)
      .setMessage(
      "用户名或密码错误!")
      .setTitle(
      "错误")
      .setNeutralButton(
      "关闭",
      new DialogInterface.OnClickListener() {
      public void onClick(DialogInterface dlg,
      int sumthin) {
      }
      }).show();
      return false;
      }
      }
      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;
      	}
      
  • 相关阅读:
    又爱又恨的eval
    http_build_query 这个方法会把值为NULL的给干掉
    allow_url_fopen设置
    纠结了下 B 和 STRONG标签区别
    Drupal 发邮件模块 drupal smtp 安装与设置
    php array_merge 和 两数组相加区别
    学历严格正相关于素质 Kai
    表语就是主语补语,靠 Kai
    一些真正有思想的up Kai
    光速不变且最大,换个思路想,非常合理,犹如天经地义【转载】 Kai
  • 原文地址:https://www.cnblogs.com/funnydavid/p/1918851.html
Copyright © 2011-2022 走看看