zoukankan      html  css  js  c++  java
  • Android 杂记

    最近有个盘点用的东西,要放到移动设备,本来用 .Net Compact Framework,CAB 部署在 CE 系统的移动条码设备。技术太旧,我用了这个周末两天时间,把这东西在试试实现在安卓上面,给用户看看效果。

    b1 b2 b3

    Screenshot_2013-09-09-12-05-57

    b4 b5 b6

    b7

    很多很多的意外,大量 Gotcha… 分享一下我的惨痛经历。以下有错误、或各位大哥有更好做法,请留言赐教。

    1. IIS 上面用 ASMX,返回 JSON,原来在客户端 POST 时候是必须注明 Content-type 为 json,否则 ASMX 返回 XML。POST 没有标识为 json,即使你自己序列化,它也是返回 XML 包裹着 JSON。

    ASP.NET CODE:

    namespace Stocktake {
        /// <summary>
        /// Summary description for RecordService
        /// </summary>
        [WebService(Namespace = "http://xxx.com/")]
        [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
        [System.ComponentModel.ToolboxItem(false)]
        // To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line. 
        [System.Web.Script.Services.ScriptService]
        public class RecordService : System.Web.Services.WebService {
    
            [WebMethod]
            [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
            public StocktakeCode getStocktakeCode() {
                
                var result = new StocktakeCode() {
                    Code = "Testing",
                    Remark = "Some Remark"
                };
                return result;
            }
        }
    
        public class StocktakeCode {
            public string Code {
                get;
                set;
            }
            public string Remark {
                get;
                set;
            }
        }
    }

    这段服务器端代码,我拼了命找错处,StackOverflow、Google、百度,原来,是没有错的。TMD x 10000。问题是下面客户端的,之前没 addHeader()。

    ANDROID CODE:

    public class DataAccess {  
      public static String getStocktakeCode(StocktakeActivity activity)
        throws IOException {
        HttpHost target = new HttpHost(getHostName(activity), getServerPort(activity));
        HttpClient client = new DefaultHttpClient();
        HttpPost post = new HttpPost(getStockCodeWsPath(activity));
        post.addHeader("Content-type", "application/json; charset=utf-8"); //  THIS IS IMPORTANT
        HttpEntity results = null;
        try{
          HttpResponse response=client.execute(target, post);
          results = response.getEntity();
          return EntityUtils.toString(results);
        } catch (Exception e){
          throw new IOException("Web Service failed.");
        } finally{
          if(results!=null){
            try{
              results.consumeContent();
            } catch (IOException e){
              
            }
          }
        }
      }
    }

    2. web.config 要加 protocol … 我忘记了加。

    ASP.NET web.config XML:

    <webServices>
      <protocols>
        <add name="HttpPost"/>
      </protocols>
    </webServices>

    不熟悉  web 开发的我,这个也很要人命。

    3. MS 自动序列化为 JSON 时,多了个莫名其妙的 d:。客户端那边,必须用 getString 方式过滤掉。里面的字符才是我们要的。

    ANDROID CODE:

    JSONObject raw = new JSONObject(HttpPost_result);
    String text = raw.getString("d");

    4. Android 内,JSONObject 要取节点内的值用getString,遇上null 会抛JSONException异常。必须检查。

    ANDROID CODE:

    JSONObject raw = new JSONObject(HttpPost_result);
    if(!raw.isNull("d")){
      String text = raw.getString("d");
      JSONObject newObj = new JSONObject(text);
      TextView tv = (TextView)activity.findViewById(R.id.textViewStocktakeCode);
      tv.setText(newObj.getString("Code"));
      TextView tv2 = (TextView)activity.findViewById(R.id.textViewStocktakeRemark);
      tv2.setText(newObj.getString("Remark"));
      activity.setIsStocktakeAllowed(true);
    } else {
      //...
    }

    我这设计是,服务器可能返回对象(序列化为 JSON),也可能返回 null。返回 null 时候,服务器发出的响应 JSON 是 {d:null}。

    5. Android 内,启动 AsyncTask 必须用 execute()。可能各位安卓的大哥觉得理所当然吧,我没怎么看 documentation 就动手,结果我直接 doInBackground,在 onPreExecute 打断点不到。就这问题,查了 TMD 四小时…。

    ANDROID CODE:

    错误:

    String result = new StocktakeCodeWorker(StocktakeActivity.this).doInBackground((String[])null);

    正确:

    new StocktakeCodeWorker(StocktakeActivity.this).execute((String[])null);

    Execute 是 void 没返回值,要干就要在 Override onPostExecute 内。

    6. Android 内,用 intent 打开另一个程序等返回值,要指定 app 的话必须 setPackage。

    ANDROID CODE:

    Intent intent = new Intent("com.google.zxing.client.android.SCAN");
    intent.setPackage("com.google.zxing.client.android"); // THIS IS IMPORTANT
    intent.putExtra("SCAN_MODE","ONE_D_MODE");
    intent.putExtra("SCAN_FORMAT", "CODE_128");
    startActivityForResult(intent, SCAN_BARCODE_REQUEST);

    否则,有多个程序供应比如 com.google.zxing.client.android.SCAN 的话,画面会出现 app chooser 让用户选。我测试用的手机上,刚好就有(淘宝、和 ZXING 本身)。我在好几个 QQ 群上问为何,也问为何淘宝出现在 app chooser,无回复。我猜,应该是淘宝用了 ZXING 的代码,而且连开放 INTENT 的也拿了过来的原因。

    加上 setPackage 后,问题消失,app chooser 没有出现而直接运行了 ZXING。

    7. Android 的 Preferences 内,用 EditTextPreferences 即使指明 input type 是 number,保存的依然是 String。除非你一直直接用代码来保存 preferences 和读取 preferences,否则,SharedPreferences.getInteger 是废的。要自己 parse。

    ANDROID Preference XML:

    <EditTextPreference
        android:key="server_port"
        android:title="@string/preference_serverPort"
        android:summary="@string/preference_serverPortRemark"
        android:dialogTitle="@string/preference_serverPort"  
        android:inputType="number"
        android:defaultValue="80" />

    ANDROID CODE:

    public static int getServerPort(StocktakeActivity activity){
      SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(activity);
      String textResult = sp.getString("server_port", "80").trim();
      return Integer.parseInt(textResult);
    }

    8. 用 Eclipse 图形化界面添加 Permission ,android.permission.INTERNET,加完依然无法连。搜了一下 StackOverflow,试试手工直接修改 XML,把它删了再手写一次,又可以了… 原因不明。

    ANDROID Manifest XML:

    <uses-permission android:name="android.permission.INTERNET"/>

    真心不知道什么回事。

    这完全是为了做个 protocol 出来给用户试试看而已。已能用,不美观,代码不公开。其实最关键部分,已经在上面全都写了。过程没有乐趣,只有痛苦。被采纳的话,接下去给下面的人改。

  • 相关阅读:
    1037. 在霍格沃茨找零钱(20)
    1036. 跟奥巴马一起编程(15)
    Java基础(五)面对对象
    Java基础(四)方法和数组
    Java基础(三)选择和循环结构
    Java基础(一)
    工厂模式(Factory Pattern)
    git 基本操作
    CXF生成客户端遇到的问题
    简单的CRUD(二)
  • 原文地址:https://www.cnblogs.com/leptonation/p/3309040.html
Copyright © 2011-2022 走看看