`
jandroid
  • 浏览: 1933799 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

Android 应用程序中使用 Internet 数据

阅读更多

简介:  您的很多 Android 应用程序都需要与 Internet 数据交互,这些数据采用各种格式。本文将带您构建一个 Android 应用程序,它可以使用两种流行数据格式 —XML 和 JavaScript Object Notation (JSON)— 以及来自 Google 的比较奇异的 protocol buffers 格式。您将了解到与每个格式相关的性能和编码利弊。

 

 

常用缩略词

  • Ajax: Asynchronous JavaScript + XML
  • API:应用程序编程接口
  • CSV:逗号分隔值
  • CSS:层叠样式表
  • DOM:文档对象模型
  • HTML:超文本标记语言
  • HTTP:超文本传输协议
  • IDL:接口描述语言
  • JSON:Javascript 对象标识
  • SAX:XML 简单 API
  • SDK:软件开发包
  • UI:用户界面
  • URL:统一资源定位符
  • XML:可扩展标记语言
  • 3G:第三代手机技术标准

Android 应用程序必须访问位于 Internet 上的数据,而 Internet 数据可以有几种不同的格式。本文将介绍在 Android 应用程序中如何使用三种数据格式:

  • XML
  • JSON
  • Google 的 protocol buffers

首先开发一个 Web 服务,将 CSV 数据转换成 XML、JSON 和 protocol-buffers 格式。然后构建一个样例 Android 应用程序,可以从 Web 服务中以任何一种格式提取数据并将其解析并显示给用户。

要进行本文中的练习,您需要最新的 Android SDK(参见 参考资料 ) 和 Android 2.2 平台。SDK 还要求您安装一个 Java™ 开发包(JDK);本文中使用了 JDK 1.6.0_17。您不需要有 Android 物理设备;所有代码都将在 SDK 的 Android 仿真器中运行。本文并没有教您如何进行 Android 开发,因此建议您熟悉 Android 编程。当然,只凭借 Java 编程语言的知识也可以完成本文的学习。

您还需要一个 Java web 应用程序服务器来运行 Android 应用程序使用的 Web 服务。此外,也可以将服务器端代码部署到 Google App Engine。参见 下载 部分获得完整的源代码。

Day Trader 应用程序

您将开发一个简单的 Android 应用程序,叫做 Day Trader。Day Trader 允许用户输入一个或更多的股票代码并获取其所代表股票的最新价格信息。用户可以指定数据使用的格式:XML、JSON 或 protocol buffers。实际的 Android 应用程序通常不会提供此选择,但是通过实现此功能,您可以了解如何让您的应用程序处理每一种格式。图 1 展示了 Day Trader 用户界面:


图 1. 运行中的 Day Trader 应用程序
运行中的 Day Trader 应用程序屏幕截图,带有 AAPL、IBM、MSFT 和 GOOG 的股票报价

文本框及其旁边的 Add Stock 按钮允许用户输入感兴趣的每支股票的代码。用户按下 Download Stock Data 按钮后,会从服务器请求所有这些股票的数据,在应用程序中解析并显示在屏幕上。默认情况下,获取的是 XML 数据。通过菜单,您可以在 XML、JSON 或 protocol buffers 数据格式间切换。

清单 1 显示用于创建 图 1 中所示 UI 的布局 XML:


清单 1. Day Trader 布局 XML
				
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
    <LinearLayout android:orientation="horizontal" 
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content">
        <EditText android:id="@+id/symbol" android:layout_width="wrap_content"
            android:layout_height="wrap_content" android:width="120dip"/>
        <Button android:id="@+id/addBtn" android:layout_width="wrap_content"
            android:layout_height="wrap_content" 
            android:text="@string/addBtnLbl"/>
    </LinearLayout>
    <LinearLayout android:orientation="horizontal" 
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content">
        <TextView android:layout_width="wrap_content" 
            android:layout_height="wrap_content" android:id="@+id/symList" />
        <Button android:id="@+id/dlBtn" android:layout_width="wrap_content" 
            android:layout_height="wrap_content" 
            android:text="@string/dlBtnLbl"
        />
       </LinearLayout>
    <ListView android:id="@android:id/list" 
        android:layout_height="fill_parent" android:layout_width="fill_parent"
        android:layout_weight="1"
        />
</LinearLayout>

清单 1 中的大部分代码都简单明了。可以看到几个小部件创建了 图 1 所示的输入和按钮。还会看到一个 ListView ,Android 小部件中真正的瑞士军刀。此 ListView 将用从服务器下载的股票数据填充。清单 2 显示了控制该视图的 Activity


清单 2. Day Trader 主活动
				
public class Main extends ListActivity {

    private int mode = XML; // default
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        final EditText input = (EditText) findViewById(R.id.symbol);
        final TextView symbolsList = (TextView) findViewById(R.id.symList);
        final Button addButton = (Button) findViewById(R.id.addBtn);
        final Button dlButton = (Button) findViewById(R.id.dlBtn);
        addButton.setOnClickListener(new OnClickListener(){
            public void onClick(View v) {
                String newSymbol = input.getText().toString();
                if (symbolsList.getText() == null || 
                        symbolsList.getText().length() == 0){
                    symbolsList.setText(newSymbol);
                } else {
                    StringBuilder sb = 
                                  new StringBuilder(symbolsList.getText());
                    sb.append(",");
                    sb.append(newSymbol);
                    symbolsList.setText(sb.toString());
                }
                input.setText("");
            }
        });
        dlButton.setOnClickListener(new OnClickListener(){
            public void onClick(View v) {
                String symList = symbolsList.getText().toString();
                String[] symbols = symList.split(",");
                symbolsList.setText("");
                switch (mode){
                case JSON :
                    new StockJsonParser().execute(symbols);
                    break;
                case PROTOBUF :
                    new StockProtoBufParser().execute(symbols);
                    break;
                default :
                    new StockXmlParser().execute(symbols);
                    break;
                }
            }
        });
    }
}

Activity 设置了 清单 1 中 XML 文件的布局,它将几个事件处理程序连接起来。首先,对于 Add Stock 按钮而言,代码读取文本框中的代码并将其添加到 symList TextView 中,用逗号分隔每个代码。接下来,对于 Download 按钮而言,处理程序从 symList TextView 中读取数据,然后 —基于 mode 变量— 使用三个不同的类之一从服务器下载数据。菜单设置 mode 变量的值;这个代码不是很重要,因此我在 清单 2 中省略了它。在了解各种数据下载/解析类之前,我先为您展示一下服务器如何提供此数据。


提供股票数据

应用程序服务器需要能够做两件事。第一,它必须获取股票代码列表并检索它们的数据。然后,它需要接受一个格式参数并基于该格式编码数据。对于 XML 和 JSON 格式而言,该服务器将返回作为文本的串行化的股票数据。对于 protocol buffers 而言,它必须发送二进制数据。 清单 3 显示了处理这些步骤的 servlet:


清单 3. Stock Broker servlet
				
public class StockBrokerServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, 
          HttpServletResponse response) throws IOException {
        String[] symbols = request.getParameterValues("stock");
        List<Stock> stocks = getStocks(symbols);
        String format = request.getParameter("format");
        String data = "";
        if (format == null || format.equalsIgnoreCase("xml")){
            data = Stock.toXml(stocks);
            response.setContentType("text/xml");    
        } else if (format.equalsIgnoreCase("json")){
            data = Stock.toJson(stocks);
            response.setContentType("application/json");
        } else if (format.equalsIgnoreCase("protobuf")){
            Portfolio p = Stock.toProtoBuf(stocks);
            response.setContentType("application/octet-stream");
            response.setContentLength(p.getSerializedSize());
            p.writeTo(response.getOutputStream());
            response.flushBuffer();
            return;
        }
        response.setContentLength(data.length());
        response.getWriter().print(data);
        response.flushBuffer();
        response.getWriter().close();
    }

    public List<Stock> getStocks(String... symbols) throws IOException{
        StringBuilder sb = new StringBuilder();
        for (String symbol : symbols){
            sb.append(symbol);
            sb.append('+');
        }
        sb.deleteCharAt(sb.length() - 1);
        String urlStr = 
                "http://finance.yahoo.com/d/quotes.csv?f=sb2n&s=" + 
                    sb.toString();
        URL url = new URL(urlStr);
        HttpURLConnection conn = 
                (HttpURLConnection) url.openConnection();
        BufferedReader reader = new BufferedReader(
                new InputStreamReader(conn.getInputStream()));
        String quote = reader.readLine();
        List<Stock> stocks = new ArrayList<Stock>(symbols.length);
        while (quote != null){
            String[] values = quote.split(",");
            Stock s = 
                      new Stock(values[0], values[2],
                           Double.parseDouble(values[1]));
            stocks.add(s);
            quote = reader.readLine();
        }
        return stocks;
    }
}

这是一个简单的 Java servlet,只支持 HTTP GET 请求。它读入股票的值和格式请求参数。然后调用 getStocks() 方法。该方法调用 Yahoo! Finance 获取股票数据。Yahoo! 只支持 CSV 格式的数据,因此 getStocks() 方法将其解析到一个 Stock 对象列表。清单 4 展示了这个简单的数据结构:


清单 4. 股票数据结构
				
public class Stock {    
    private final String symbol;
    private final String name;
    private final double price;
      //getters and setters omitted

    public String toXml(){
        return "<stock><symbol>" + symbol + 
"</symbol><name><![CDATA[" +
            name + "]]></name><price>" + price + 
"</price></stock>";
    }

    public String toJson(){
        return "{ 'stock' : { 'symbol' : " +symbol +", 'name':" + name + 
            ", 'price': '" + price + "'}}";
    }

    public static String toXml(List<Stock> stocks){
        StringBuilder xml = new StringBuilder("<stocks>");
        for (Stock s : stocks){
            xml.append(s.toXml());
        }
        xml.append("</stocks>");
        return xml.toString();
    }

    public static String toJson(List<Stock> stocks){
        StringBuilder json = new StringBuilder("{'stocks' : [");
        for (Stock s : stocks){
            json.append(s.toJson());
            json.append(',');
        }
        json.deleteCharAt(json.length() - 1);
        json.append("]}");
        return json.toString();
    }
}

每个 Stock 都有三个属性— symbolnameprice — 和几个便捷的方法,以便将其自己转换成 XML 字符串或 JSON 字符串。它提供了一个工具方法,用于将 Stock 对象列表转换成 XML 或 JSON。回到 清单 3 ,根据格式请求参数,Stock 对象列表被转换成 XML 或 JSON 字符串并被发送回客户端。

XML 和 JSON 用例非常类似和直接。对于 protocol buffers,您必须生成 protocol buffers 格式的代码读写对象。为此,您需要使用 protocol buffers 规范格式定义数据结构。清单 5 展示了一个示例:


清单 5. 股票的 Protocol buffers 消息
				
package stocks;

option java_package = "org.developerworks.stocks";

message Quote{
    required string symbol = 1;
    required string name = 2;
    required double price = 3;
}

message Portfolio{
    repeated Quote quote = 1;
}

protocol buffers 消息格式类似于接口描述语言 (IDL),它与语言无关,因此可以将其与各种语言一起使用。在本例中,运行 protocol buffers 编译器(protoc )将 清单 5 中的代码编译成要用于客户端和服务器的 Java 类。有关将 protocol buffers 消息编译成 Java 类的详细信息,请参阅 Protocol Buffers Developer Guide(参见 参考资料 )。

清单 3 中,一个名为 toProtoBuf() 的方法将 Stock 对象列表转换成一个 Portfolio 消息。清单 6 展示了该方法的实现:


清单 6. 创建组合消息
				
public static Stocks.Portfolio toProtoBuf(List<Stock> stocks){
    List<Stocks.Quote> quotes = new ArrayList<Stocks.Quote>(stocks.size());
    for (Stock s : stocks){
        Quote q = 
            Quote.newBuilder()
                .setName(s.name)
                .setSymbol(s.symbol)
                .setPrice(s.price)
                .build();
        quotes.add(q);
    }
    return Portfolio.newBuilder().addAllQuote(quotes).build();
}

清单 6 中的代码使用了从 清单 5 中的消息生成的代码 — QuotePortfolio 类。只需构建来自每个 Stock 对象的 Quote ,然后将其添加到 清单 3 中返回到 servlet 的 Portfolio 对象即可。在 清单 3 中,servlet 直接打开到客户端的流并使用生成的代码编写到流的二进制协议 buffers 数据。

现在,您了解了服务器如何创建要发送到 Android 应用程序的数据。接下来将学习应用程序如何解析此数据。


使用数据格式

清单 2 中的主 Activity 需要使用服务器可以发送的各种格式的数据。它还需要请求适当格式的数据并且数据一旦解析,就用它来填充其 ListView 。因此,无论数据格式是什么,大部分功能都是通用的。

首先,创建一个抽象的基类,封装此通用功能,如 清单 7 所示:


清单 7. 数据解析器基类
				
abstract class BaseStockParser extends AsyncTask<String, Integer, Stock[]>{
    String urlStr = "http://protostocks.appspot.com/stockbroker?format=";

    protected BaseStockParser(String format){
        urlStr += format;
    }

    private String makeUrlString(String... symbols) {
        StringBuilder sb = new StringBuilder(urlStr);
        for (int i=0;i<symbols.length;i++){
            sb.append("&stock=");
            sb.append(symbols[i]);
        }
        return sb.toString();
    }

    protected InputStream getData(String[] symbols) throws Exception{
        HttpClient client = new DefaultHttpClient();
        HttpGet request = new HttpGet(new URI(makeUrlString(symbols)));

        HttpResponse response = client.execute(request);
        return response.getEntity().getContent();
    }

    @Override
    protected void onPostExecute(Stock[] stocks){
        ArrayAdapter<Stock> adapter = 
            new ArrayAdapter<Stock>(Main.this, R.layout.stock, 
                      stocks );
        setListAdapter(adapter);
    }
}

清单 7 中的基类扩展了 android.os.AsyncTask 。这是一个常用的用于异步操作的类。它抽象出线程和处理程序的创建,用于请求主 UI 线程。它是基于其输入和输出数据类型参数化的。对于所有解析器而言,输入总是一样的:股票代码字符串。 输出也是一样的:Stock 对象数组。基类获取 format ,这是一个指定了要使用的数据格式的字符串。然后提供一个方法,发出适当的 HTTP 请求并返回一个流响应。最后,它覆盖 AsyncTaskonPostExecute() 方法并使用从解析器返回的数据为 ActivityListView 创建一个 Adapter

现在看到三个解析器的功能是通用的。我将为您展示更具体的解析代码,从 XML 解析器开始。


用 SAX 解析 XML

Android SDK 提供了几种使用 XML 的方式,包括标准 DOM 和 SAX。 对于一些对内存密集型情况,可以使用 SDK 的 pull-parser。大部分时候,SAX 是最快的方式。Android 包括一些便捷的 API 使得使用 SAX 更轻松。清单 8 显示了 Day Trader 应用程序的 XML 解析器:


清单 8. XML 解析器实现
				
private class StockXmlParser extends BaseStockParser{
    public StockXmlParser(){
        super("xml");
    }

    @Override
    protected Stock[] doInBackground(String... symbols) {
        ArrayList<Stock> stocks = new ArrayList<Stock>(symbols.length);
        try{
            ContentHandler handler = newHandler(stocks);
            Xml.parse(getData(symbols), Xml.Encoding.UTF_8, handler);
        } catch (Exception e){
            Log.e("DayTrader", "Exception getting XML data", e);
        }
        Stock[] array = new Stock[symbols.length];
        return stocks.toArray(array);
    }

    private ContentHandler newHandler(final ArrayList<Stock> stocks){
        RootElement root = new RootElement("stocks");
        Element stock = root.getChild("stock");
        final Stock currentStock = new Stock();
        stock.setEndElementListener(
            new EndElementListener(){
                public void end() {
                    stocks.add((Stock) currentStock.clone());
                }
            }
        );
        stock.getChild("name").setEndTextElementListener(
            new EndTextElementListener(){
                public void end(String body) {
                    currentStock.setName(body);
                }
            }
        );
        stock.getChild("symbol").setEndTextElementListener(
            new EndTextElementListener(){
                public void end(String body) {
                    currentStock.setSymbol(body);
                }
            }
        );
        stock.getChild("price").setEndTextElementListener(
            new EndTextElementListener(){
                public void end(String body) {
                            currentStock.setPrice(Double.parseDouble(body));
                }
            }
        );
        return root.getContentHandler();
    }
}

清单 8 中的大部分代码都在 newHandler() 方法中,该方法创建一个 ContentHandler 。如果熟悉 SAX 解析, 会知道 ContentHandler 通过响应 SAX 解析器触发的各种事件创建解析数据。newHandler() 方法使用 Android 便捷 API 指定使用事件处理程序的 ContentHandler 。代码只是侦听在解析器遇到各种标记时触发的事件,然后选取数据,放到 Stock 对象列表中。 创建 ContentHandler 后,调用 Xml.parse() 方法来解析基类提供的 InputStream 并返回 Stock 对象数组。这是快速解析 XML 的方法,但是 —即使使用 Android 提供的便捷 API— 它也是非常冗长的。


使用 JSON

XML 是 Android 上的一等公民,鉴于依赖于 XML 的 Web 服务的数量,这是个好事。很多服务还支持另一个流行格式 JSON。它通常比 XML 简洁一些,但也是人们可读的,使得它更易于使用,并且可以更轻松地将其用于调试使用它的应用程序。Android 包括一个 JSON 解析器。(您可以从 JSON.org 网站获得该解析器,只是要去除几个手机不需要的类)。 清单 9 显示了使用中的解析器:


清单 9. JSON 解析器实现
				
private class StockJsonParser extends BaseStockParser{
    public StockJsonParser(){
        super("json");
    }
    @Override
    protected Stock[] doInBackground(String... symbols) {
        Stock[] stocks = new Stock[symbols.length];
        try{
            StringBuilder json = new StringBuilder();
            BufferedReader reader = 
                new BufferedReader(
                            new InputStreamReader(getData(symbols)));
            String line = reader.readLine();
            while (line != null){
                json.append(line);
                line = reader.readLine();
            }
            JSONObject jsonObj = new JSONObject(json.toString());
            JSONArray stockArray = jsonObj.getJSONArray("stocks");
            for (int i=0;i<stocks.length;i++){
                JSONObject object = 
                    stockArray.getJSONObject(i).getJSONObject("stock");
                stocks[i] = new Stock(object.getString("symbol"), 
                        object.getString("name"), 
                        object.getDouble("price"));
            }
        } catch (Exception e){
            Log.e("DayTrader", "Exception getting JSON data", e);
        }
        return stocks;
    }
}

可以看到在 Android 中使用 JSON 解析器是多么简单。您将来自服务器的流转换成传递给 JSON 解析器的字符串。您遍历对象图并创建 Stock 对象数组。如果使用过 XML DOM 解析,这看起来很类似,因为编程模型几乎一样。

像 DOM 一样,JSON 解析器可以用于内存密集型应用。在 清单 9 中,所有来自服务器的数据都表示为字符串,然后作为 JSONObject ,最后作为 Stock 对象数组。换句话说,同一数据通过三种不同的方式表示。可以看到,对于大量数据而言,这可能是个问题。当然,一旦到达方法末尾,这三种数据表示方式中的两 种都会落在范围之外,被垃圾回收器回收。但是,只是触发更频繁的垃圾回收可能会对用户体验带来负面影响,造成处理速度下降。如果内存效率和性能很重要,使 用 protocol buffers 的解析器可能是个较好的选择。


使用 protocol buffers 处理二进制

Protocol buffers 是一个由 Google 开发的与语言无关的数据串行化格式,旨在比 XML 更快地通过网络传送数据。它是 Google 用于服务器对服务器调用的事实 标准。Google 将该格式及其用于 C++、Java 和 Python 编程语言的绑定工具以开源方式提供。

清单 3清单 6 中看到 protocol buffers 是二进制格式。如您所料,这使得数据很简洁。如果在客户端和服务器端启用 gzip 压缩,在使用 XML 和 JSON 时通常也可以得到类似的消息大小,但是 protocol buffers 仍然有一些大小上的优势。它还是一种可以迅速解析的格式。最后,它提供了一个相当简单的 API。 清单 10 显示了一个示例解析器实现:


清单 10. Protocol buffers 解析器实现
				
private class StockProtoBufParser extends BaseStockParser{
    public StockProtoBufParser(){
        super("protobuf");
    }

    @Override
    protected Stock[] doInBackground(String... symbols) {
        Stock[] stocks = new Stock[symbols.length];
        try{
            Stocks.Portfolio portfolio = 
                Stocks.Portfolio.parseFrom(getData(symbols));
            for (int i=0;i<symbols.length;i++){
                stocks[i] = Stock.fromQuote(portfolio.getQuote(i));
            }
        } catch (Exception e){
            Log.e("DayTrader", "Exception getting ProtocolBuffer data", e);
        }
        return stocks;
    }
}

清单 3 所示,您可以使用 protocol buffers 编译器生成的 helper 类。这与服务器使用的 helper 类相同。可以编译它一次,然后在服务器和客户端共享它。 这样,您可以更轻松地直接从服务器的流读取数据并将其转换成 Stock 对象数组。这种简单编程也具有非常出色的性能。现在看一下此性能与 XML 和 JSON 的比较。


性能比较

比较性能通常涉及某种微基准测试,此类基准测试很容易产生偏见或无意间得到不正确的结果。即使以公平方式设计微基准测试,很多随机因素也会对 结果产生影响。 尽管有这些问题,我还是要使用这样的微基准测试来比较 XML(大约 1300 ms)、JSON(大约 1150 ms)和 protocol buffers(大约 750 ms)。基准测试向服务器发送了一个关于 200 个股票的请求并测量了从发出请求到用于创建 ListViewAdapter 的数据准备就绪所需的时间量。对每个数据格式在两个设备上进行 50 次这样的操作:一个 Motorola Droid 和一个 HTC Evo,两个都通过 3G 网络。 图 2 显示了结果:


图 2. 比较数据格式速度
柱状图比较了数据格式速度:XML、JSON 和 protocol buffers

图 2 显示出,在此基准测试中 protocol buffers(大约 750 ms)比 XML (大约 1300 ms)几乎快两倍。很多因素影响着数据通过网络和被手持设备处理的性能。一个明显的因素是通过网络的数据量。二进制格式的 protocol buffers 比文本格式的 XML 和 JSON 在通过网络时小得多。然而,文本格式可以使用 gzip 进行有效地压缩,这是 Web 服务器和 Android 设备都支持的标准技术。 图 3 显示了在打开和关闭 gzip 时通过网络的数据大小:


图 3. 不同格式的数据大小
比较不同格式数据大小的柱状图:XML 和 JSON(原始或压缩状态)与 protocol buffers 之比较

图 3 应该增加了您对 XML 和 JSON 之类的文本内容的压缩效果的喜爱(更不用说 Web 格式、HTML、JavaScript 和 CSS 了)。protocol buffers 数据(大约 6KB)比原始 XML(大约 17.5KB)或 JSON(大约 13.5KB)数据小得多。但是一旦进行了压缩, JSON 和 XML(都是大约 3KB)实际上比 protocol buffers 小很多了。在本例中,它们都接近于 protocol-buffers 编码消息大小的一半了。

回到 图 2 , 速度的不同显然不能由通过网络的消息大小解释。protocol-buffers 消息比 XML 或 JSON 编码的消息大,但是通过使用 protocol buffers,您仍然能够削减半秒钟的用户等待时间。 这是否意味着应该在 Android 应用程序中使用 protocol buffers 呢?这样的决定很少是固定的。如果要发送的数据量很小,则三种格式间的差异也不大。对于大量数据而言,protocol buffers 可能会有所不同。但是,像这样精心设计的基准测试无法替代对您自己的应用程序的测试。


结束语

本文介绍了如何使用 Internet 上流行的两种数据格式 XML 和 JSON 的方方面面。还讲到了第三种可能性,protocol buffers。像软件工程中的其他内容一样,选择技术主要就是权衡利弊。当您为一个局限的环境(比如 Android)开发时,这些决定的结果往往被放大了。我希望您现在拥有的关于这些后果的额外知识能够帮助您创建出色的 Android 应用程序。

2
3
分享到:
评论

相关推荐

    Android应用源码之应用程序自动更新源码.zip

    在Android应用开发中,应用程序自动更新是至关重要的功能,它能确保用户始终使用的是最新、最安全的版本。本资源提供了Android应用源码,详细展示了如何实现这一功能。以下是基于提供的"应用程序自动检查更新源码"的...

    android 系统应用程序 网络数据转串口tcpToUart

    1. **Android应用程序开发**:Android是Google开发的开源移动操作系统,支持手机、平板电脑等设备。在Android平台上开发应用,主要使用Java或Kotlin语言,借助Android Studio集成开发环境。开发者需要了解Android ...

    基于LLVM的Android应用程序加固方法.pdf

    Android 应用程序的安全性问题是当前 Mobile Internet 领域中的一大难题,本文的方法可以提供一种可靠的解决方案。同时,该方法也可以应用于其他需要保护知识产权的领域,例如桌面应用程序、云计算等。 在 Android...

    Android应用源码之中文天气预报程序.zip

    在本压缩包“Android应用源码之中文天气预报程序.zip”中,我们主要探讨的是一个基于Android平台的中文天气预报应用程序的源代码。这个程序旨在为用户提供实时、准确的天气信息,包括温度、湿度、风向等关键气象数据...

    Android字典应用程序源代码

    总的来说,这个"Android字典应用程序源代码"涵盖了Android开发的基础知识,包括UI设计、数据存储、网络通信等多个方面,对初学者来说是学习Android应用开发的宝贵资源。通过分析和修改这个项目,你可以更深入地理解...

    Android应用程序的自动更新升级

    ### Android应用程序的自动更新升级 #### 一、引言 随着移动互联网的发展,应用程序更新成为提升用户体验、修复问题和引入新功能的重要手段。对于Android应用程序而言,具备版本检测和自动更新的功能不仅能够确保...

    遥控pc android应用程序

    标题中的“遥控PC Android应用程序”指的是使用Android设备作为控制器,远程操作个人计算机(PC)的应用程序。这种技术通常基于远程桌面协议(RDP)、VNC(Virtual Network Computing)或者其他类似的远程控制解决...

    android与WIFI模块的数据传输 数据透传

    本项目中,开发者被要求创建一个Android应用程序,用于配置HLK-RM04 WIFI模块,进行数据读取、参数设置以及系统时间同步。下面我们将详细探讨涉及的技术点。 首先,HLK-RM04是一款集成TCP/IP协议栈的WIFI模组,它...

    Android应用程序源代码CityWeather

    CityWeather是一款针对Android平台开发的应用程序,主要用于提供城市天气信息查询。通过分析其源代码,我们可以深入了解Android应用开发的关键技术和流程。以下将从多个角度详细阐述这个项目中的知识点。 1. **...

    android天气预报之Webservice应用程序

    总的来说,这个项目为学习Android与Web服务的交互提供了一个基础实例,展示了如何利用ksoap2库实现远程数据获取,以及如何在Android应用中显示和处理这些数据。对于想要深入理解Android网络编程和ksoap2使用的开发者...

    Android应用源码之获取网络数据到本地并查看-IT计算机-毕业设计.zip

    在Android应用开发中,获取网络数据并将其存储到本地是常见的功能之一,尤其在构建移动开发App时。这个"Android应用源码之获取网络数据到本地并查看"的项目,显然是一个面向毕业设计学习的示例,可以帮助学生理解...

    CountryRank,Android应用程序示例.zip

    CountryRank是一款开源的Android应用程序,它的源代码被封装在名为"CountryRank-master"的压缩包中。这个项目为开发者提供了一个学习和参考的实例,展示了如何在Android平台上开发一款能够展示各国排名的应用。通过...

    在Android app中集成nginx,非JNI

    配置文件应适应Android环境,比如指向Android应用的私有数据目录来存储日志和静态文件。 5. **权限设置**:在AndroidManifest.xml中添加必要的权限,如INTERNET权限,以及可能需要的写入外部存储权限,因为nginx...

    Android Studio实现天气预报小程序

    开发者可以通过它快速创建、构建、测试和发布Android应用程序。启动新项目时,选择"Empty Activity"模板,这将为你提供一个基础的项目结构。 2. **项目结构**:在创建项目后,你会看到如下的目录结构:`app`模块...

    Android入门程序_Intent的使用

    在Android开发中,Intent是一个非常核心且至关重要的概念,它充当了应用程序组件间通信的桥梁。本教程将深入探讨Intent的使用,引导Android初学者掌握这一基础知识点。 Intent主要用于启动或激活Android系统中的...

    Android应用程序之WebApp开发实战

    在Android平台上,WebApp开发是一项重要的技能,它允许开发者利用Web技术来构建应用...《Android应用程序之WebApp开发实战》这本书将为你提供更详尽的指导,包括案例分析和实战技巧,助你在WebApp开发领域更上一层楼。

    android 系统程序源码

    它是每个Android应用的核心配置文件,用于定义应用程序的基本属性、所需权限、组件(如活动、服务、广播接收器和内容提供者)以及它们之间的关系。下面将详细讨论`androidManifest.xml`在各个给定的子项目中的应用...

    如何在Android系统邮件应用程序中使用IMAP服务.docx

    ### 如何在Android系统邮件应用程序中使用IMAP服务 #### 一、引言 随着智能手机的普及和技术的进步,用户越来越依赖于移动设备进行日常通信。IMAP(Internet Mail Access Protocol)作为一种主流的邮件协议,提供了...

Global site tag (gtag.js) - Google Analytics