Author Archives: lytsing

How to Use Android Downloads Provider

“Good programmers write solid code, while great programmers reuse the code of good programmers”
— W. Jason Gilmore, the author of “Beginning PHP and MySQL”

In Android Platform, it supports some ways to download files from URLs via HttpURLConnection or HttpClient, or DownloadProvider.When you write an android programm with Eclipse, try to import:

import android.provider.Downloads

The Eclipse gives a red error prompting and complains:

The import android.provider.Downloads cannot be resolved

Oops…

The download manager is not part of the public SDK, and there are no relational API description in Android developers Reference.Comment in sources frameworks/base/core/java/android/provider/Downloads.java, says: “For 1.0 the download manager can’t deal with abuse from untrusted apps, so this API is hidden.” Refer to the document description from: packages/providers/DownloadProvider/docs/index.html. we Know that Browser / Gmail / Market / Updater depend on the download manager. Yes, show some screenshots in the market:

use downloadprovider in android market

android market downloads shows in the statebar.

We maybe can’t compile with Eclipse, but we can write an Android.mk makefile, use mmm to do it.

DownloadProvider is very easy to use.First, declare permission in AndroidManifest.xml:

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

And then just need to fill some field values:

ContentValues values = new ContentValues();
String url = "http://lytsing.qiniudn.com/wp-content/uploads/2010/06/android_downloadprovider_market.jpg";
values.put(Downloads.URI, url);
values.put(Downloads.MIMETYPE, "image/jpeg");
values.put(Downloads.FILENAME_HINT, getFullFilename("android_downloadprovider_market.jpg"));
values.put(Downloads.TITLE, "screenshot");
values.put(Downloads.DESCRIPTION, "screenshot file for DownloadProvider Demo");
values.put(Downloads.VISIBILITY, Downloads.VISIBILITY_VISIBLE);
values.put(Downloads.NOTIFICATION_CLASS, "org.lytsting.android.downloads.DownloadReceiver");
values.put(Downloads.NOTIFICATION_PACKAGE, "org.lytsting.android.downloads");
getContentResolver().insert(Downloads.CONTENT_URI, values);

private String getFullFilename(String filename) {
    return Environment.getExternalStorageDirectory().toString() + "/download/" + filename);
}

Notes

Downloads.FILENAME_HINT, for a demo, here, I put the file into SD Card, the download directory, without checking any exception.
Downloads.NOTIFICATION_CLASS, you want to write a DownloadReceiver class, which extends BroadcastReceiver, and handle the message Downloads.DOWNLOAD_COMPLETED_ACTION or Downloads.NOTIFICATION_CLICKED_ACTION. like this:

public class DownloadReceiver extends BroadcastReceiver {
    static final String TAG = "DownloadReceiver";

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d(TAG, intent.getAction());
        if (intent.getAction().equals(Downloads.NOTIFICATION_CLICKED_ACTION)) {
            Intent activityIntent = new Intent(Intent.ACTION_VIEW);
            activityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            activityIntent.setClass(context, Downloads.class); // Downloads Activity
            try {
                context.startActivity(activityIntent);
            } catch (ActivityNotFoundException ex) {
                Log.d(TAG, "no activity for Downloads.NOTIFICATION_CLICKED_ACTION" + ex);
            }
        } else if (intent.getAction().equals(Downloads.DOWNLOAD_COMPLETED_ACTION)) {
            // balabala
        }
    }
}

By here, we need to modify the AndroidManifest.xml, add:

<receiver
    android:name=".DownloadReceiver"
    android:permission="android.permission.SEND_DOWNLOAD_COMPLETED_INTENTS"
    android:exported="true" >
    
    <intent-filter>
        <action
            android:name="android.intent.action.DOWNLOAD_COMPLETED">
        </action>
    </intent-filter>
    <intent-filter>
        <action
            android:name="android.intent.action.DOWNLOAD_NOTIFICATION_CLICKED">
        </action>

        <category
            android:name="android.intent.category.DEFAULT">
        </category>
        <data
            android:scheme="content">
        </data>
    </intent-filter>
</receiver> 

Maybe, you don’t like show the the Download state in status bar, just change Downloads.VISIBILITY_VISIBLE to Downloads.VISIBILITY_HIDDEN

and even, maybe you would like to show the download progress in the Activity, little case.

Cursor c = getContentResolver().query(
        Downloads.CONTENT_URI, new String[] {
        Downloads._ID,
        Downloads.CURRENT_BYTES,
        Downloads.TOTAL_BYTES,
        Downloads.STATUS }, 
        " " + Downloads.MIMETYPE + " = 'image/jpeg'", null,
        Downloads._ID);

if (c == null) {
    return;
}

// Columns match projection in query above
final int idColumn = 0;
final int currentBytesColumn = 1;
final int totalBytesColumn = 2;
final int statusColumn = 3;

c.moveToFirst();
long totalBytes = c.getLong(totalBytesColumn);
long currentBytes = c.getLong(currentBytesColumn);

c.close();

Add a ProgressBar and a Handler to display and refresh the progress, I suppose you should know how to do. You also can write a class extends ContentObserver to observer the download status.

The last step, delete the history data:

getContentResolver().delete(Downloads.CONTENT_URI,
                 "(" + Downloads.TITLE + " = 'screenshot')", null);

This code snippet should be write into a function in really code.

Read the code packages/apps/Browser for a more complete example.

Update:Since Android 2.2, the Downloads’s api has changed, they put some variables input a sub class which named Impl, so you should check it in the source code.

如何学习Android应用程序的开发

昨天一同学问我,如何快速的学习Android应用程序开发? 之前的一位同事也问过我,我也只是大概的说说看哪些资料。为避免更多的人问我,所以有必要写写。

1. 开发环境搭建。自行Google。英文好的,看官方网 http://developer.android.com/ 访问不了的,可以访问它的镜像 http://androidappdocs.appspot.com/index.html

2. 在模拟器上运行 ApiDemos,全部点一遍,看看Android都提供了些什么界面效果,心里有个印象。最好把ApiDemos的代码,看它个两三遍。我到过深圳南山书城,看了好几本国内出的Android书籍,一本书都没翻多久,就看完了,没啥看头,因为大部分内容ApiDemos都有了呀。

3. Java的学习。
Android应用程序是用Java写的,像我这样从C/C++阵营过来的,开始真的很抵触。《Thinking in Java》 ??? No! 没时间玩这东西,当做参考书还行,不懂就翻翻。宝岛台湾的林信良老师写的《Java学习笔记》,还不错。
http://caterpillar.onlyfun.net/Gossip/JavaGossip-V1/JavaGossip.htm
http://caterpillar.onlyfun.net/Gossip/JavaGossip-V2/JavaGossip2.htm
大约花一个礼拜的晚上时间学习,基本够用。

4. 学习资料
(1) 网站
官网 developer.android.com,英文差的同学,也要硬着头皮看,在网上搜来搜去,其实大部分东西都是从这拷贝过去的,从而浪费了大把的时间。国内的android论坛,好像就javaeye文章质量高一点,其他的不知道。我一直上国外的 http://www.anddev.org/ 它有两个版面 Novice Tutorials和Code Snippets for Android,有教程,可以下载代码编译运行,初学者最喜欢这样的了。不像一些网站,下载代码还要扣积分等其他7788的,一看就没什么好感。

(2) 书籍
就只推荐三本,其他的没看过,不好评论。
Mark L. Murphy: 《The Busy Coder’s Guide to Android Development》
Chris Haseman:《Android Essentials》
高煥堂:《Android 應用框架原理與程式設計36 技》

初学者最好不要第一本书就看高的书,因为一些东西他讲起来莫名其妙,搞复杂了,一看developer.android.com英文原版的资料,噢!英文描述这么简单啊。

(3) Blogs
请参看 http://wiki.andmob.org/blogs

(4) 阅读代码
除了上面所说的ApiDemos的代码,还有SDK下提供的Samples目录下其他示例代码,还有Google公司提供的Demo代码,它们在:
http://code.google.com/p/apps-for-android/

———–
2010/6/11 补充内容:今天在网上找chrome代码阅读,看到Venus神庙的 Android学习入门http://www.cnblogs.com/duguguiyu/archive/2010/01/23/1654559.html
感觉不错,也推荐给大家,Venus神庙写作水平不错,比我好N倍。

Android Market的 Loading效果

在Android中,要实现Loading效果,一般情况下都使用ProgressDialog控件。ApiDemos/src/com/example/android/apis/view/ProgressBar3.java 提供两个demo:
Progressbar show Indeterminate
progressbar show Indeterminate No Title
仔细看了Android Market,发现却是不一样的,请看截图:
那到底如何实现呢?首先,我们创建一个布局文件,
res/layout/fullscreen_loading_indicator.xml, 其内容如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:gravity="center_vertical|center_horizontal"
    android:orientation="horizontal"
    android:id="@+id/fullscreen_loading_indicator"
    android:visibility="gone"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
    <ProgressBar
        android:layout_gravity="center_vertical"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        style="?android:attr/progressBarStyleSmall"
        >
    </ProgressBar>
    <TextView
        android:id="@+id/current_action"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="5.0dip"
        android:text="@string/loading"
        >
    </TextView>
</LinearLayout>
然后在main.xml 把它include 进来

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
    <LinearLayout
        android:orientation="vertical"
        android:id="@+id/main_info"
        android:visibility="gone"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        >
    </LinearLayout>
    <include
        android:visibility="visible"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        layout="@layout/fullscreen_loading_indicator"
        >
    </include>
</FrameLayout>
主程序 Loading.java:
package org.lytsing.android.loading;

import android.app.Activity;
import android.os.Bundle;
import android.widget.LinearLayout;

public class Loading extends Activity {

    private LinearLayout mLoadingLayout;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        // TODO: dismiss the loading, use this snippet code.
        //mLoadingLayout = (LinearLayout)findViewById(R.id.fullscreen_loading_indicator);
        //mLoadingLayout.setVisibility(View.GONE);
    }
}
运行的效果为:

Android 代码风格指南

翻译状态: 完成进度82%

本文的英文原始文档(Android Code Style Guidelines for Contributors)地址 : http://source.android.com/source/code-style.html

国内用户如果无法直接访问,请自行翻墙。第一次翻译Java类的文档, 如果有差错和不妥之处, 请不吝指出.

Android的代码风格规则

The rules below are not guidelines or recommendations, but strict rules. Android代码贡献者,如果他们不遵守这些规则,那么一般他们的代码不会被接受
并非所有现存的代码遵循这些规则,但所有的新代码希望能如此

Java 语言规则

我们遵循标准的Java编码约定。
我们还添加一些规则:
  1. 异常:不要在没有说明的情况下捕捉和忽略它们。
  2. Exceptions : 不要捕捉一般异常, except in library code at the root of the stack.
  3. Finalizers :一般不使用它们。
  4. Imports : 完全符合引入

Java库规则

这里有一些关于使用android Java库与工具的约定。在某些情况下,该约定在一些重要的方式已经发生了变化,老的代码可能在使用过时的模式或库。当使用这些代码,最好继续保持与已存在的风格一致(参见一致性)当创建新的组件从来不使用废弃库。

Java的风格规则

当所有文件都保持一致的风格时,程序就更容易维护。我们遵循标准的Java编码风格,他们由Sun公司为Java编程语言制定的编码约定,除少数例外,和增加一些。这些风格指南是全面而详细的,在Java社区很常用。

此外,我们执行下面的样式规则:
  1. 注释/Javadoc :使用标准样式写它
  2. 简短的方法 :不写超大的方法
  3. 字段(成员变量):要么是在该文件的顶部,或紧接在使用它们的方法前面。
  4. 局部变量 :限制作用域
  5. 引入 :android;第三方按字母顺序排列;java(x)
  6. 缩进排版 :4个空格,没有制表符(tab)
  7. 行长度 :100个字符
  8. 字段命名 : 非公有的,非静态字段以m开头,静态变量以s开头 。
  9. 括号 :开括号不要独占一行
  10. 注解 :使用标准的注解。
  11. Acronyms are words : Treat acronyms as words in names, yielding XmlHttpRequest , getUrl() , etc.
  12. TODO的风格 :“TODO:在这里写描述”
  13. 一致性 :看看你周围的
  14. 日志记录 :小心日志记录,它开销很大。

Javatests样式规则

1. 测试方法的命名 :testMethod_specificCase是正确的

用C++写ruby扩展

为了测试CDMA短信的发送方便,于是想到编译成lib,提供ruby使用。

SmsObject.h:
void SendSms(const char* msg, const char* number, char* out);

main.cpp:

//
// by deli 2009.6.11
//
#include <ruby.h>
#include "SmsObject.h"

static VALUE makepdu(VALUE self, VALUE arg1, VALUE arg2) {
    VALUE s;
    char pdu[512] = {0};
    char* msg = RSTRING(arg1)->ptr;
    char* number = RSTRING(arg2)->ptr;

    SendSms(msg, number, pdu);
    s = rb_str_new2(pdu);

    return s;
}

extern "C"
void __declspec(dllexport) Init_sms() {
    VALUE myModule = rb_define_module("CDMA");

    VALUE myClass = 
        rb_define_class_under(myModule, "SMS", rb_cObject);

    int arg_count = 2;
    rb_define_method(myClass, "makepdu", RUBY_METHOD_FUNC(makepdu), arg_count);
}

注意: C++要加上RUBY_METHOD_FUNC, C不用加。不然就会出现类似的错误:
error C2664: ‘rb_define_method’ : cannot convert parameter 3 from
‘unsigned long (unsigned long,unsigned long,unsigned long)’ to ‘unsigned long (_
_cdecl *)(…)’
None of the functions with this name in scope match the target type

test.rb:

#!/usr/bin/ruby 

require 'sms'

include CDMA

obj = SMS.new
pdu = obj.makepdu('什么都可以想,什么都可以不想,便觉得是个自由的人', '15338896034')

puts pdu

D:\Ruby\ruby-serial\sms>ruby test.rb
0000021002040702c54ce225a8d008420003200000013220c27602724487ea9f7a772b079ff86276
02724487ea9f7a772a706b079ff8627dfc4e4afcbb317a71540f53a98bb42275d00501a70801c00d
0101

大概就是这样。

Pages: Prev 1 2 3 ... 11 12 13 14 15 16 17 18 19 20 21 Next