Pages:  1 2 ... 5 6 7 8 9 ... 21 22
lytsing – Page 7 – lytsing's Blog

Author: lytsing

  • Downlodas 之 ByUri.startDownloadByUri

    很久以前写过一篇《How to Use Android Downloads Provider》,到了Android 2.2(froyo),Android 提供了更优雅的接口:

    public static long startDownloadByUri(Context context,
                                          String url,
                                          String cookieData,
                                          boolean showDownload,
                                          int downloadDestination,
                                          boolean allowRoaming,
                                          boolean skipIntegrityCheck,
                                          String title,
                                          String notification_package,
                                          String notification_class,
                                          String notification_extras)

    当然这些接口都是hide的,做ROM系统开发的才可以直接使用,用mmm方式编译。签于这个原因,一些国内第三方电子市场直接拿Downloads组件的代码修改成自己的提供使用。代码实现在:

    [deli@violet frameworks]$ find . -type f -name Downloads.java
    ./base/core/java/android/provider/Downloads.java
    ./base/core/java/android/net/Downloads.java

    还有 packages/providers/DownloadProvider

    startDownloadByUri 即这个函数很容易理解,有网友给我发email说不知道如何使用,我贴出系统升级使用的代码片段,希望对大家有帮助。

    [deli@violet update]$ cat Download.java

    /*
     * Copyright (C) 2010 lytsing.org
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *      http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
    
    package com.google.android.gsf.update;
    
    import com.google.android.gsf.R;
    
    import android.content.Context;
    import android.util.Log;
    import android.net.Downloads;
    
    public class Download {
    
        private final Context mContext;
    
        private String mNotificationClass;
    
        private String mNotificationPackage;
    
        public Download(Context context) {
            mContext = context;
            mNotificationPackage = context.getPackageName();
            mNotificationClass = SystemUpdateService.Receiver.class.getName();
        }
    
        public boolean downloadUpdate(String url, boolean showDownload, boolean allowRoaming) {
            removeAllDownloads();
            try {
                if (Downloads.ByUri.startDownloadByUri(
                            mContext,
                            url,
                            null,
                            showDownload,
                            2,
                            allowRoaming,
                            true,
                            mContext.getString(R.string.system_update_downloading_notification_title),
                            mNotificationPackage,
                            mNotificationClass,
                            null)== -1) {
                    Log.w("update.Download", "Could not insert download entry into provider");
                    return false;
                } 
    
                Log.i("update.Download",new StringBuilder()
                        .append("Started a new update download: ").append(url).toString());
            } catch (Exception e) {
                Log.e("update.Download", "Could not start update download", e);
                return false;
            }
    
            return true;
        }
    
        public Downloads.StatusInfo getStatus(String url) {
            return Downloads.ByUri.getStatus(mContext, url, 24 * 3600 * 1000);
        }
    
        public void removeAllDownloads() {
            Log.v("update.Download", "deleting all update downloads");
            try {
                Downloads.ByUri.removeAllDownloadsByPackage(mContext, mNotificationPackage,
                        mNotificationClass);
            } catch (Exception ex) {
                Log.e("update.Download", "Couldn\'t delete downloads", ex);
            }
        }
    }
  • 电子市场 Google 软件精选管理器

    很多手拿Android手机的人不明白这个软件是干啥的,其实,就是Market Updater,我也不明白为什么中文会叫成这样。在Broncho的时候,反编译过这个MarketUpdater.apk,以后我也不干这坏事了,把成果贴出来吧: https://github.com/lytsing/MarketUpdater

    就30多行代码,它干的事情很少,监听 “com.android.vending.UPDATE_MARKET”, intent把下载后的apk url传过来,调用静默安装apk的方法。

    那么,谁发 “com.android.vending.UPDATE_MARKET” 这个intent action? 当然是电子市场了:

    <receiver 
        android:name=".InitializeMarketAction$DownloadBroadcastReceiver"
        android:permission="android.permission.SEND_DOWNLOAD_COMPLETED_INTENTS"
        android:exported="true">
    <receiver />

    大致的InitializeMarketAction.java代码:

    // From Vending.apk
    package com.android.vending;
    
    import android.content.BroadcastReceiver;
    import android.content.Context;
    import android.content.Intent;
    import android.net.Uri;
    
    public class InitializeMarketAction {
    
        public class DownloadBroadcastReceiver extends BroadcastReceiver {
    
            @Override
            public void onReceive(Context context, Intent intent) {
                final Uri contentUri = intent.getData();
                int status = DownloadManagerUtil.getStatus(context, contentUri);
                if (DownloadManagerUtil.isStatusAuthFailure(status)) {
                    new Thread() {
                        public void run() {
                            VendingApplication.getVendingApplication().invalidateAuthTokenBlocking(
                                    AuthService.ANDROID_SECURE);
                        }
                    }.start();
                    
                } else if (DownloadManagerUtil.isStatusSuccess(status)) {
                    setBackgroundRunnable(new Runnable() {
    
                        @Override
                        public void run() {
                            ServiceLocator.getCacheManager().clear();
                            Context app = VendingApplication.getVendingApplication();
                            app.sendBroadcast(new Intent("com.android.vending.UPDATE_MARKET",
                                    contentUri));
                        }
                        
                    });
                }
                
            }
        }
    }

    那电子市场是如何自我更新的呢? 这个问题问得好。待续。。。

  • Sqaure 网站所使用的技术

    从他们的网站的招聘信息,Quora问答社区获取到的信息,可以大致了解情况。

    早期的3人团队:
    Jack Dorsey写服务器端(Python on Google App Engine)
    Tristan O’Tierney 写iPhone客户端
    Jim McKelvey设计硬件。
    经过一个月的努力,三个创始人做出了第一个原型。

    目前跑的是:

    数据库:Redis and MySQL

    支付平台:Ruby on Rails, Sinatra, JRuby, MRI, and Java

    web: 宣传页面使用 html5,他们使用大量的js开源框架。

    服务器部署在 亚马逊 CloudFront 云服务。

    目前纯开发人员有大约有50人,可以从他们的开源项目看到:https://github.com/square

    他们的开源代码提供了ruby代码,iPhone、Android测试框架,Android SDK,js等。

    他们开发推崇TDD, Pair programming。

    他们的开发理念:Rethinking,Redefining。

  • Protobuf Demo

    操作系统:Fedora core 16

    下载安装

    Go to http://code.google.com/p/protobuf/ download the latest updates version

    $ wget http://protobuf.googlecode.com/files/protobuf-2.4.1.tar.bz2
    $ tar xvf protobuf-2.4.1.tar.bz2
    $ cd protobuf-2.4.1/
    $ ./configure && make && sudo make install

    一般默认安装在/usr/local 目录下,需要导入环境变量:

    编辑 ~/.bashrc 在后面添加:

    export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH
    export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig$PKG_CONFIG_PATH

    编译jar包:

    $ cd protobuf-2.4.1/
    $ sudo yum install maven
    $ mvn package

    在 target/ 目下下生成 protobuf-java-2.4.1.jar, 使用的时候,导入环境变量CLASSPATH 就行了。

    Ubuntu 11.10,安装也很简单:

    $ sudo apt-get install libprotobuf-dev libprotobuf-java
    $ export CLASSPATH=$CLASSPACH:/usr/share/java/protobuf.jar

    书写 .proto 文件
    一个比较好的习惯是认真对待 proto 文件的文件名。比如将命名规则定于如下:
    packageName.MessageName.proto

    下载 vim 编辑proto语法亮度插件: http://protobuf.googlecode.com/svn/tags/release-2.0.1/editors/proto.vim 按照里面的说明安装。或者照这个操作,https://github.com/garyharan/vim-proto

    服务器端与客户端socket通讯
    服务器段用C++实现,客户端 Java/C++,具体代码放在 github:https://github.com/lytsing/protobuf-demo 这里就不贴出来了。

    参考: Protocol Buffers的安装使用和C++入门示例

  • 解决电子市场 3.13版本 “您的设备与此商品不兼容”的问题

    Android market: Your device is not compatible with this item


    用 apktool 1.4.1 反编译Vending.apk 3.1.3版本,遇到错误,无法插入调试信息再打包重新安装。搜索反编译后的文件查找信息:

    您的设备与此商品不兼容。

    smali/com/android/vending/R$string.smali:.field public static final availability_restriction_hardware:I = 0x7f080191

    deli@deli-laptop:~/Desktop/a/Vending$ grep 0x7f080191 * -r
    smali/com/google/android/finsky/activities/DetailsAvailabilityRestrictionViewBinder.smali: const v3, 0x7f080191

    猜出大概代码:

    public bind(View view, Document document, int iconWidth, int iconRightMargin, DfeToc toc) {
    
    	TextView reason = view.findViewById(R.id.restriction_reason);
    	int restriction = document.getAvailabilityRestriction();
    
    	switch (restriction) {
    	case 4:
    		reason.setText(R.string.availability_restriction_hardware);
    		break;
    	}
    }
    
    public int getAvailabilityRestriction() {
    	boolean hasAvailability = mFinskyDoc.hasAvailability();
    	if (hasAvailability) {
    		int restriction = mFinskyDoc.getAvailability().getRestriction();
    		reutrn restriction;
    	}
    
    	return -1;
    }

    restriction的值是通过 setRestriction 设置,读取protobuf数据,也没弄清楚,因为无法插入调试信息。发现3.1.3版本比以前版本复杂多了。

    最后发现

      deli@deli-laptop:~$ diff build.prop build.prop~
      31c31
      < ro.build.fingerprint=N708_800_600/broncho_N708/N708_800_600/:2.2/FRF91/user.N708_800_600.20110917.133140:user/test-keys
      ---
      > ro.build.fingerprint=N708/broncho_N708/N708_800_600/:2.2/FRF91/user.N708_800_600.20110917.133140:user/test-keys

    ro.build.fingerprint=N708,N708这个是我们的项目名,临时修改编译脚本成N708_800_600,出现下划线,导致被google过滤掉了。搞第三方ROM的,注意了,别随意修改系统参数,除非你真的明白你在干啥东东。