分类: Google Android

  • Jetpack 插件

    WordPress 的Jetpack 插件,是由automattic inc.开发的一个插件,automattic inc. 是美国旧金山的软件公司,wordpress.com的母公司。

    Jetpack 的mobile app可以通过Google Play 下载,如同wordpress mobile apo一样,不对中国开放。

  • myMPD Local Playback

    Add a httpd audio output in mpd.conf, refer to https://jcorporation.github.io/myMPD/references/local-playback

    # myMPD local playback
    audio_output {
        type        "httpd"
        name        "HTTP Stream"
        encoder     "vorbis"
        port        "8000"
        quality     "10.0"
        format      "44100:16:1"
        always_on   "yes"
        tags        "yes"
    }

    Enable Local playback in mympd menu:

    Settings/Features/Local playback/Enable

    Launch browser, play the selected music by both:

    play button: control the mpd play

    local button: link to the httpd output

    Test Environment:

    mpd: v0.23.15

    mympd: v14.1.1

    server os: Ubuntu 18.04.1

    client os: Android 13

    client browse: chrome/firefox

  • Android Activity Launch Mode

    Activity的launchMode:singleTop,singleTask与singleInstance

     

    相关内容,可以参见官方网址:http://developer.android.com/guide/components/tasks-and-back-stack.html

    如图所示,如果ABC三个Activity的launchMode都是standard,那么按照图示顺序调用后,堆栈为ABCBB;
    而如果界面ActivityB的launchMode为singleTop,同样的调用关系下,堆栈为ABCB,栈顶的B,被复用了。

    singleTop模式,适合于与用户交互时保持信心更新的界面Activity,比如联系人的搜索界面界面等;

    singleTop仅作为栈顶Activity时才可能被复用,同一个Activity在系统中,还是会存在多个的现象。
    singleTasksingleInstance,在整个系统中,仅会有一个对象存在,以节省内存开销。
    如果运行模式不是默认的standard模式,那么,该Activity需要重载onNewIntent的函数。
    standard和singleTop,对它的调用,不会引起任务切换;而singleTask和singleInstance,则相反。
    换句话说,而singleTask和singleInstance,其Activity的对象,仅可作为任务的根Activity而存在,
    而standard和singleTop,其Activity的对象,则可能存在Activity堆栈的任何位置。

    如图所示,当B的运行模式为singleTask和singleInstance时,所有对B的调用,
    都会跳转到以B为根的任务中进行,而与调用Activity所在的任务,毫无关联。

    singleTask和singleInstance唯一的区别是:
    singleInstance,其所在的任务中,包含且只包含一个该Activity的对象,不会再有其他的Activity对象;
    而singleTask,其任务中,则可能包含多个其他相关的Activity对象。

    singleTask和singleInstance适用于消耗内存较多的单实例界面,比如浏览器和音乐播放器等。

    摘自《Android开发精要》

  • 开源字体: source-han-sans (思源字体)

    source-han-sans (思源字体)

    Adobe 与 Google 联合开发的开源字体, 参见《Introducing Source Han Sans: An open source Pan-CJK typeface

    http://blog.typekit.com/

    下载:

    https://github.com/adobe-fonts/source-han-sans/

    许可:  1.001及其更早采用 Apache 2.0 license

    1.002及其以后采用 SIL Open Font License

     

    Google Noto Font:

    http://www.google.com/get/noto/

     

    https://github.com/googlei18n?query=noto

  • Build openjdk 7 on ubuntu 10.10

    sudo apt-get install git mercurial zip bzip2 unzip tar gawk
    sudo apt-get install ccache make gcc g++ ca-certificates ca-certificates-java
    sudo apt-get install libX11-dev libxext-dev libxrender-dev libxtst-dev
    sudo apt-get install libasound2-dev libcups2-dev libfreetype6-dev
    sudo apt-get install build-essential ruby-dev pkg-config
    sudo apt-get install openjdk-6-jdk
    sudo apt-get install fpm

    mkdir /build/openjdk
    cd /build/openjdk
    git clone https://github.com/hgomez/obuildfactory.git

    XBUILD=true ./obuildfactory/openjdk7/linux/standalone-job.sh

    # List output file
    ls OBF_DROP_DIR/openjdk7/
    j2re-image-x86_64-u80-b05-20150127.tar.bz2
    j2sdk-image-x86_64-u80-b05-20150127.tar.bz2

     

    # Install to /opt/openjdk7
    sudo mkdir /opt/openjdk7
    cd /opt/openjdk7
    sudo tar xvfj /build/openjdk/OBF_DROP_DIR/openjdk7/j2sdk-image-x86_64-u80-b05-20150127.tar.bz2

  • Android repo sync issus: gnutls_handshake failed

    The issus was caused by gnutls library,  if network bandwidth is low

     

    Fix:

    Build git with openssl from source:

    cat git_build.sh

    GIT_MAJOR=1.7.9
    GIT_MINOR=7
    GIT_VER=${GIT_MAJOR}.${GIT_MINOR}
    GIT_NAME=git-${GIT_VER}

    OPENSSL_VER=1.0.1i
    OPENSSL_NAME=openssl-${OPENSSL_VER}

    CURL_VER=7.38.0
    CURL_NAME=curl-${CURL_VER}

    EXPAT_VER=2.1.0
    EXPAT_NAME=expat-${EXPAT_VER}

    TARGET_DIR=/usr/local/git-${GIT_MAIN}
    TARGET_DIR=/tmp/local

    BUILD_OPENSSL=0
    BUILD_CURL=0
    BUILD_EXPAT=0
    BUILD_GIT=1

    if [ “${BUILD_OPENSSL}” == “1” ];then
      if [ ! -f ${OPENSSL_NAME}.tar.gz ];then
        wget http://www.openssl.org/source/${OPENSSL_NAME}.tar.gz
      fi

      if [ -d ${OPENSSL_NAME} ];then
        rm -rf ${OPENSSL_NAME}
      fi

      tar xvfz ${OPENSSL_NAME}.tar.gz
      cd ${OPENSSL_NAME}

      ./config no-shared no-dso –prefix=${TARGET_DIR}
      make -j4
      #make test
      sudo make install
      cd ..
    fi

    if [ “${BUILD_CURL}” == “1” ];then
      if [ ! -f ${CURL_NAME}.tar.gz ];then
        wget http://curl.haxx.se/download/${CURL_NAME}.tar.gz
      fi

      if [ -d ${CURL_NAME} ];then
        rm -rf ${CURL_NAME}
      fi

      tar xvfz ${CURL_NAME}.tar.gz
      cd  ${CURL_NAME}
      env PKG_CONFIG_PATH=${TARGET_DIR}/lib/pkgconfig ./configure  –disable-shared –prefix=${TARGET_DIR} –without-gnutls –with-ssl
      make -j4
      sudo make install
      cd ..
    fi

    if [ “${BUILD_EXPAT}” == “1” ];then
      if [ ! -f ${EXPAT_NAME}.tar.gz ];then
        wget http://sourceforge.net/projects/expat/files/expat/${EXPAT_VER}/${EXPAT_NAME}.tar.gz
      fi

      if [ -d ${EXPAT_NAME} ];then
        rm -rf ${EXPAT_NAME}
      fi
      tar xvfz ${EXPAT_NAME}.tar.gz
      cd ${EXPAT_NAME}
      ./configure –disable-shared –prefix=${TARGET_DIR}
      make
      sudo make install
    fi

    if [ “${BUILD_GIT}” == “1” ];then
      if [ ! -f v${GIT_VER}.tar.gz ];then
        wget http://github.com/git/git/archive/v${GIT_VER}.tar.gz
      fi

     
      if [ -d ${GIT_NAME} ];then
        rm -rf ${GIT_NAME}
      fi

      tar xvfz v${GIT_VER}.tar.gz
      cd ${GIT_NAME}
      make configure
     
      ./configure –prefix=${TARGET_DIR}  –with-curl –with-openssl=${TARGET_DIR} –with-lib=${TARGET_DIR}

      make -j4
      #make test
      sudo make install
    fi

  • Open Source Android SMS Gateway

    Android Handset

    Envaya: (outbound)

        http://sms.envaya.org/

        https://github.com/youngj/EnvayaSMS

     

    SMSSync (inbond)

         http://smssync.ushahidi.com/

     

    Increase the SMS Limit on Android:

    http://www.xda-developers.com/android/increase-the-sms-limit-on-android/

    Setting:

    sms_outgoing_check_max_count=999999999999999999

    Or:

    sms_outgoing_check_interval_ms=0

     

     

    Web Server:

    SMStoXMPP

        https://projects.jethrocarr.com/p/oss-smstoxmpp/

    Drupal

     

  • Android mount sdcard (again)

    ===>  execute_media_format
    android/packages/apps/Settings/src/com/android/settings/MediaFormat.java

    ===>  mountService.formatVolume(extStoragePath);
    android/frameworks/base/core/java/com/android/internal/os/storage/ExternalStorageFormatter.java

    ====>  formatVolume
    ====>  doFormatVolume
    android/frameworks/base/services/java/com/android/server/MountService.java

    ===> int CommandListener::VolumeCmd::runCommand
    ===> rc = vm->formatVolume(argv[2]);
    android/system/vold/CommandListener.cpp

    ==> int VolumeManager::formatVolume
    ==> mVolumes = new VolumeCollection();
    ==> return v->formatVol()
    android/system/vold/VolumeManager.h
    android/system/vold/VolumeManager.cpp

    ===> int Volume::formatVol
    ===> Fat::format(devicePath, 0))
    android/system/vold/Volume.cpp

    ===> int Fat::format(const char *fsPath, unsigned int numSectors)
    ===> static char MKDOSFS_PATH[] = “/system/bin/newfs_msdos”
    android/system/vold/Fat.cpp

    android/frameworks/base/services/java/com/android/server/NativeDaemonConnector.java

    # C code
    android/system/vold

    # Launch sd formater in setting
    adb shell
    am start -n com.android.settings/.MediaFormat

    ##############################################################################

    以下是打开“无线和网络设置”界面:

    Intent intent = new Intent(“/”);
    ComponentName cm = new ComponentName(“com.android.settings”,”com.android.settings.WirelessSettings”);
    intent.setComponent(cm);
    intent.setAction(“android.intent.action.VIEW”);
    activity.startActivityForResult( intent , 0);

    以下是可以直接打开的系统界面:

    com.android.settings.AccessibilitySettings 辅助功能设置
    com.android.settings.ActivityPicker 选择活动
    com.android.settings.ApnSettings APN设置
    com.android.settings.ApplicationSettings 应用程序设置
    com.android.settings.BandMode 设置GSM/UMTS波段
    com.android.settings.BatteryInfo 电池信息
    com.android.settings.DateTimeSettings 日期和时间设置
    com.android.settings.DateTimeSettingsSetupWizard 日期和时间设置
    com.android.settings.DevelopmentSettings 应用程序设置=》开发设置
    com.android.settings.DeviceAdminSettings 设备管理器
    com.android.settings.DeviceInfoSettings 关于手机
    com.android.settings.Display 显示——设置显示字体大小及预览
    com.android.settings.DisplaySettings 显示设置
    com.android.settings.DockSettings 底座设置
    com.android.settings.IccLockSettings SIM卡锁定设置
    com.android.settings.InstalledAppDetails 语言和键盘设置
    com.android.settings.LanguageSettings 语言和键盘设置
    com.android.settings.LocalePicker 选择手机语言
    com.android.settings.LocalePickerInSetupWizard 选择手机语言
    com.android.settings.ManageApplications 已下载(安装)软件列表
    com.android.settings.MasterClear 恢复出厂设置
    com.android.settings.MediaFormat 格式化手机闪存
    com.android.settings.PhysicalKeyboardSettings 设置键盘
    com.android.settings.PrivacySettings 隐私设置
    com.android.settings.ProxySelector 代理设置
    com.android.settings.RadioInfo 手机信息
    com.android.settings.RunningServices 正在运行的程序(服务)
    com.android.settings.SecuritySettings 位置和安全设置
    com.android.settings.Settings 系统设置
    com.android.settings.SettingsSafetyLegalActivity 安全信息
    com.android.settings.SoundSettings 声音设置
    com.android.settings.TestingSettings 测试——显示手机信息、电池信息、使用情况统计、Wifi information、服务信息
    com.android.settings.TetherSettings 绑定与便携式热点
    com.android.settings.TextToSpeechSettings 文字转语音设置
    com.android.settings.UsageStats 使用情况统计
    com.android.settings.UserDictionarySettings 用户词典
    com.android.settings.VoiceInputOutputSettings 语音输入与输出设置
    com.android.settings.WirelessSettings 无线和网络设置

    ##############################################################################
    Generate SD Card Image file

    #64G:
    dd if=/dev/zero of=64G.img  count=0 seek=128M

    #8G:
    dd if=/dev/zero of=64G.img  count=0 seek=16M

    #8G (with zero filled)
    dd if=/dev/zero of=64G.img count=16M

    ##############################################################################
    Loop device

    #List loop devices:
    losetup -a

    #Add a loop device
    losetup /dev/loop1 8G_zero.img

    #Delete loop device
    losetup -d /dev/loop1

    find . -type f |xargs grep sd_format
    find . -name *.java |xargs grep sd_format

    ###################################################################
    Modify sd_format of android/packages/apps/Settings/res/values, impact on:

    target R.java/Manifest.java: Settings (out/target/common/obj/APPS/Settings_intermediates/src/R.stamp)
    target Java: Settings (out/target/common/obj/APPS/Settings_intermediates/classes)
    Note: Some input files use or override a deprecated API.
    Note: Recompile with -Xlint:deprecation for details.
    Note: Some input files use unchecked or unsafe operations.
    Note: Recompile with -Xlint:unchecked for details.
    Copying: out/target/common/obj/APPS/Settings_intermediates/classes-jarjar.jar
    Copying: out/target/common/obj/APPS/Settings_intermediates/emma_out/lib/classes-jarjar.jar
    Copying: out/target/common/obj/APPS/Settings_intermediates/classes.jar
    Copying: out/target/common/obj/APPS/Settings_intermediates/noproguard.classes.jar
    target Dex: Settings
    Copying: out/target/common/obj/APPS/Settings_intermediates/noproguard.classes.dex
    target Package: Settings (out/target/product/generic/obj/APPS/Settings_intermediates/package.apk)
    ‘out/target/common/obj/APPS/Settings_intermediates/classes.dex’ as ‘classes.dex’…
    Processing target/product/generic/obj/APPS/Settings_intermediates/package.apk
    Done!
    Install: out/target/product/generic/system/app/Settings.odex
    Install: out/target/product/generic/system/app/Settings.apk
    Finding NOTICE files: out/target/product/generic/obj/NOTICE_FILES/hash-timestamp
    Combining NOTICE files: out/target/product/generic/obj/NOTICE.html
    target Java: SettingsTests (out/target/common/obj/APPS/SettingsTests_intermediates/classes)
    Note: Some input files use or override a deprecated API.
    Note: Recompile with -Xlint:deprecation for details.
    Installed file list: out/target/product/generic/installed-files.txt
    Target system fs image: out/target/product/generic/obj/PACKAGING/systemimage_intermediates/system.img
    Install system fs image: out/target/product/generic/system.img

    ******************************************************
    SD FORMAT

    ==> StorageVolumePreferenceCategory
    ==> mAllowFormat = mStorageVolume != null && !mStorageVolume.isEmulated()
    android/packages/apps/Settings/src/com/android/settings/deviceinfo/StorageVolumePreferenceCategory.java

    SD Card Mount

    => “Preparing SD card”
    => “Damaged SD card”
    ==> ext_media_checking_notification_title
    ==> ext_media_unmountable_notification_title
    frameworks/base/core/res/res/values/strings.xml
    frameworks/base/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
    ===>MEDIA_UNMOUNTABLE

    *****************************************************

    #/system/etc/vold.fatab
    #/system/etc/vold.conf

    =>fatab
    ==>system/vold/main.cpp
    ===>process_config
    ====>VolumeManager
    =====>system/vold/VolumeManager.cpp
    =======>CommandListener
    ========>system/vold/CommandListener.cpp

    ********************************
    FAT
    ===> system/vold/Fat.cpp
    ====> FSCK_MSDOS_PATH
    =====> Fat::check
    ======>system/vold/Volume.cpp
    =======>createDeviceNode
    =========>Volume::mountVol
    =========>DirectVolume::handleBlockEvent

    Volume::mountVol
    ==> No impact on SDCard Mount, just for security fs

    DirectVolume::handleBlockEvent
    ==>NetlinkEvent
    ===>system/core/include/sysutils/NetlinkEvent.h
    =====>NetlinkEvent.mSubsystem==”block”, send to volume manage ==> DirectVolume::handleBlockEvent
    ======>NlActionAdd
    ========>system/core/libsysutils/src/NetlinkEvent.cpp

    ==========>system/core/libsysutils/src/NetlinkListener.cpp
    ==========>NetlinkListener::onDataAvailable

    ============>system/core/libsysutils/src/SocketListener.cpp
    ============>system/core/include/sysutils/NetlinkListener.h
    ============>class NetlinkListener : public SocketListener

    ***************************************************************************************
    *** Triger of  NlActionAdd ***

    “add”:
    =>NetlinkEvent::parseAsciiNetlinkMessage,    system/core/libsysutils/src/NetlinkEvent.cpp
    ==>NetlinkEvent::decode
    ===>NetlinkListener::onDataAvailable,        system/core/libsysutils/src/NetlinkListener.cpp
    ====>SocketListener::runListener,            system/core/libsysutils/src/SocketListener.cpp
    =====>SocketListener::threadStart,           system/core/libsysutils/src/SocketListener.cpp
    ======>SocketListener::startListener,        system/core/libsysutils/src/SocketListener.cpp
    =======>main,                                system/vold/main.cpp
    =======>NetlinkHandler::start,               system/vold/NetlinkHandler.cpp

    *** Handle of NlActionAdd ***

    “NlActionAdd”
    =>DirectVolume::handleBlockEvent,            system/vold/DirectVolume.cpp
    ==>VolumeManager::handleBlockEvent,          system/vold/VolumeManager.cpp
    ==>NetlinkHandler::onEvent,                  system/vold/NetlinkHandler.cpp

    **************************************************************************
    Framework:   MountService

    frameworks/base/services/java/com/android/server/SystemServer.java
    =>public MountService(Context context),     frameworks/base/services/java/com/android/server/MountService.java
    ==>mContext.registerReceiver(mBroadcastReceiver, filter, null, null);
    ===>BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver()
    ====>action.equals(Intent.ACTION_BOOT_COMPLETED)
    =====>if (state.equals(Environment.MEDIA_UNMOUNTED)) {
    int rc = doMountVolume(path);
    if (rc != StorageResultCode.OperationSucceeded) {
    Slog.e(TAG, String.format(“Boot-time mount failed (%d)”,
    rc));
    }
    ======>private int doMountVolume(String path)
    =======>mConnector.doCommand(String.format(“volume mount %s”, path));

    ==>mConnector = new NativeDaemonConnector
    ===>class NativeDaemonConnector,    frameworks/base/services/java/com/android/server/NativeDaemonConnector
    ====>public void run(),             frameworks/base/services/java/com/android/server/NativeDaemonConnector.java
    =====>listenToSocket,               frameworks/base/services/java/com/android/server/NativeDaemonConnector.java
    ======>mCallbacks.onDaemonConnected();     (mCallbacks=MountService)
    =======>onDaemonConnected()         frameworks/base/services/java/com/android/server/MountService.java

    **********************************************************************************
    Sd Card Mount Summary:

    frameworks/base/services/java/com/android/server/MountService.java:
    private int doMountVolume(String path):

    Use case of doMountVolume

    Case 1:  private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver()
    ===> Boot up SD Card mount

    Case 2:  public boolean onEvent(int code, String raw, String[] cooked)
    ===>frameworks/base/services/java/com/android/server/NativeDaemonConnector.java
    ===>Callback
    ===>public boolean handleMessage(Message msg)
    ===> SD Card Insert mount

    Case 3: public int mountVolume(String path)
    ==> packages/apps/Settings/src/com/android/settings/deviceinfo/Memory.java
    ==> User Setting/Mount

    Case 4: public int mountVolume(String path)
    ===> frameworks/base/core/java/com/android/internal/os/storage/ExternalStorageFormatter.java
    ===> Factory Reset

  • Download android source code over SSH

    1) Install http proxy with socks support
    sudo apt-get install privoxy

    2) Install DNS cache server
    sudo apt-get install dnsmasq

    3) Install DNS socks proxy
    git clone https://github.com/jtRIPper/dns-tcp-socks-proxy.git
    cd dns-tcp-socks-proxy
    make

    4) Setup ssh connection to the external server, and listen on port 127.0.0.1:4567 (any one free)

    ssh -p proto -D4567 user@ssh_server

    5) Config privoxy listen on 127.0.0.1:8080, and forward to ssh socks at 127.0.0.1:4567:

    cat /etc/privoxy/config
    listen-address 127.0.0.1:8080
    forward-socks5 / 127.0.0.1:4567 .

    forward 192.168.*.*/ .
    forward 10.*.*.*/ .
    forward 127.*.*.*/ .

    6) Config dnsmasq with upstream server point to dns-tcp-socks-proxy first

    cat /etc/dnsmasq.conf

    resolv-file=/etc/resolv-dnsmasq.conf
    strict-order
    server=/221.24.172.in-addr.arpa/internal_dns_ip
    server=/61.24.172.in-addr.arpa/internal_dns_ip
    server=/62.24.172.in-addr.arpa/internal_dns_ip
    server=/63.24.172.in-addr.arpa/internal_dns_ip
    interface=eth0
    bind-interfaces
    log-queries
    log-dhcp

    With such configuration, dnsmasq will listen on eth0 interface and 127.0.0.1, and forward the query to the DNS resolver defined in /etc/resolv-dnsmasq.conf.
    the strict-order directory force dnsmasq to select the dns server according to the order of item defined in /etc/resolv-dnsmasq.conf

    cat /etc/resolv-dnsmasq.conf
    nameserver 127.0.0.2
    nameserver 172.24.63.211
    nameserver 172.24.63.212

    7) Config dns-tcp-socks-proxy listen to dnsmasq, and forward the query to the ssh socks, here 127.0.0.1:4567

    cat dns_proxy.conf
    socks_port = 4567
    socks_addr = 127.0.0.1

    listen_addr = 127.0.0.2
    listen_port = 53

    set_user = nobody
    set_group = nobody

    resolv_conf = /etc/dns_proxy/resolv.txt
    log_file = /dev/null

    8) Config the local dns resolver to 127.0.0.1
    cat /etc/resolv.conf
    nameserver 127.0.0.1

    9) Sync android source code over SSH
    repo sync

    10) Note, with such configuration, we have:
    http/https local proxy at 127.0.0.1:8080, forward to the external server via socks
    dns local cache proxy at 127.0.0.1:53, forward to the external server vis socks