2017年9月19日 星期二

[Android] 如何修改預設output 的APK 名稱

編譯專案後會產生output apk,預設名稱會是 "app-release.apk"
但在開發專案的時後常會需要根據 build type 不同有對應的名稱,例如 xxx-release.apk
當然可以每次build出apk後,再去修改名稱,當個勤勞的工程師
可是一天我們會build上好幾上次的apk,每次都要做更改,光想就覺得累
我們可以利用修改Gradle 幫我們把這個行為自動化

在這邊用比較複雜的名稱格式來當範例
將APK名稱格式修改成 myProject_dev_debug_1.3.6_131016_1047.apk.
專案名稱_Flavors_buildType_versionName_ddMMyy_HHmm
這些是我們會用到的資訊

  • flavor
  • buildType
  • version
  • date

app/build.gradle

android {

    ...

    buildTypes {
        release {
            minifyEnabled true
            ...
        }
        debug {
            minifyEnabled false
        }
    }

    productFlavors {
        prod {
            applicationId "com.feraguiba.myproject"
            versionCode 3
            versionName "1.2.0"
        }
        dev {
            applicationId "com.feraguiba.myproject.dev"
            versionCode 15
            versionName "1.3.6"
        }
    }

    applicationVariants.all { variant ->
        variant.outputs.each { output ->
            def project = "myProject"
            def SEP = "_"
            def flavor = variant.productFlavors[0].name
            def buildType = variant.variantData.variantConfiguration.buildType.name
            def version = variant.versionName
            def date = new Date();
            def formattedDate = date.format('ddMMyy_HHmm')

            def newApkName = project + SEP + flavor + SEP + buildType + SEP + version + SEP + formattedDate + ".apk"

            output.outputFile = new File(output.outputFile.parent, newApkName)
        }
    }
}
reference :
https://stackoverflow.com/questions/28249036/app-release-apk-how-to-change-this-default-generated-apk-name/30332234#30332234

[Android] 用Command Line 執行APK 及 如何取得Package及Launch Activity name

在專案開發的時後,有時後會用到第三方的apk
但是沒辦法在裝置上直接執行它,因為apk被隱藏起來了
所以不會出現在Launch app的地方
那如果要Launch 隱藏app要怎麼做呢? 透過Command Line 執行apk


如何用Command Line 執行apk


指令結構 : adb shell am start -n package name/full activity name
$adb shell am start -n com.test.drm/com.test.drm.drmActivity


如何Command Line取得 Package Name 及 Launch Activity Name


  • 取得裝置內已安裝的Package Name
  • 指令結構 : adb shell pm list packages -f

    • -f : 一併列出apk檔案的存放位置
    • -s : 只列出系統套件(system package)
    • -3 : 只列出第三方套件 (3rd-party package)
    • FILTER : 只列出FILTER的套件名稱
    $ adb shell pm list packages -f

  • 取得 apk Launch Activity Name

    • 先用 adb shell pm list packages -f 取得apk 檔案的存放位置
    • 再執行 adb pull /apk檔案路徑/xxx.apk
    • 開啟Android Studio -> Build/Analyze APK...
    • 就可以查看AndroidManifest.xml

    2014年6月18日 星期三

    Object C 初體驗


    • 減號(或加號):代表函數、方法的開始
    例如C#方法的寫法是
    private void hello (boolean b_start){
        OOXX;
    }

    Object C的寫法是
    -(void)hello:(boolean)b_start{
        OOXX;
    }

    不過在Object C 是沒有private, public的區分,可都視為public
    而加號則是表示其它的函數可以直接調用這個類中的函數,而不用創建這個類的實例
    • 中括號[]
    中括號可視為要如何調用我們剛才寫的方法,通常在Object C 稱為[消息]。
    例如C#是可以這麼寫
    this.hello(true);

    Object C的寫法是
    [self hello:YES];

    • NS****
    當年賈伯斯被趕出蘋果時,所創立的公司Next Step,裡面一些開發包是很讓科學家喜歡的,這套函數庫也就是現在MAC OS 所使用的。
    而這套Function library 的開發團體比較自戀,所用的function name都是以Next Step的第一個字母命名NS****
    比較常見的就是
    NSLog
    NSString
    NSInteger
    NSURL
    NSImage

    問題:什麼是#import、@interface

    • #import
    這可以視為#include是一樣的。但最好是用#import,記住這個就好

    • @interface

    例如在C#寫一個抓孩子類的定義
    public class Kids : system
    {
        private string str_kidName = "My Kids";
        private string str_kidAge = "15";
        private bool bl_isCaughtkid ()
        {
            return true;
        }
    }

    用Object C表示:
    先寫一個Kid.h定義這個類

    @interface Kids:NSObject
    {
        NSString *str_kidName;
        NSString *str_kidAge;
    }
    -(BOOL)bl_isCaughtkid:;
    @end

    再寫一個Kid.m實現這個類

    #import "Kid.h"
    @implement Kids
    -(void) init:{
        str_kidName =@ "My Kids";
        str_kidAge = @"15";
    }

    -(BOOL)bl_isCaughtkid:{
        return YES;
    }
    @end

    問題:一個方法怎麼傳遞多個參數?
    一個方法可以包含多個參數,只是後面的參數都要有參數名稱。

    多個參數的寫法
    (方法的數據類型)函數名稱:(參數1數據類型)參數1數值名稱 參數2的名字:(參數2數據類型) 參數2數值名稱

    舉例、一個方法的定義

    -(void)setkids:(NSString *)myOldestKidName secondKid:(NSString *)mySecondOldestKidName thirdKid:(NSString *)myThirdOldestKidName

    一個方法的實現

    -(void)setkids:(NSString *)myOldestKidName secondKid:(NSString *)mySecondOldestKidName thirdKid:(NSString *)myThirdOldestKidName{
        大兒子名字 = myOldestKidName;
        二兒子名字 = mySecondOldestKidName;
        三兒子名字 = myThirdOldestKidName;
    }

    調用的時後

    Kids *mykids = [[Kids alloc] init];
    [mykids setkids:@"張大力" secondKid:@"張二力" thirdKid:@"張三力"];

    而如果你用c#寫這個方法,大致的寫法可能是
    public void setKids( string myOldestKidName, stringmySecondOldestKidName, stringmyThirdOldestKidName)
    {
    }
    調用的時候大概的寫法可能是:
    Kids myKids = new Kids();
    myKids.setKids (「張大力」「張二力」「張小力」);
    明白了吧?其實不怎麼難看懂。
    基本上,如果你能了解下面這段代碼的轉換關系,你Objective-C的語法也就懂了八成了:
    [[[MyClass allocinit:[foo bar]] autorelease];
    轉換成C#或者Java的語法也就是:
    MyClass.alloc().init(foo.bar()).autorelease();

    2012年3月26日 星期一

    CString的構造函數

    CString的構造函數
    CString( );
    例:CString csStr;

    CString( const CString& stringSrc );
    例:CString csStr("ABCDEF中文123456");
    CString csStr2(csStr);

    CString( TCHAR ch, int nRepeat = 1 );
    例:CString csStr('a',5);
    //csStr="aaaaa"

    CString( LPCTSTR lpch, int nLength );
    例:CString csStr("abcdef",3);
    //csStr="abc"

    CString( LPCWSTR lpsz );
    例:wchar_t s[]=L"abcdef";
    CString csStr(s);
    //csStr=L"abcdef"

    CString( const unsigned char* psz );
    例:const unsigned char s[]="abcdef";
    const unsigned char* sp=s;
    CString csStr(sp);
    //csStr="abcdef"

    CString( LPCSTR lpsz );
    例:CString csStr("abcdef");
    //csStr="abcdef"

    int GetLength( ) const;
    返回字符串的長度,不包含結尾的空字符。
    例:csStr="ABCDEF中文123456";
    printf("%d",csStr.GetLength()); //16

    void MakeReverse( );
    顛倒字符串的順序
    例:csStr="ABCDEF中文123456";
    csStr.MakeReverse();
    cout<//654321文中FEDCBA

    void MakeUpper( );
    將小寫字母轉換為大寫字母
    例:csStr="abcdef中文123456";
    csStr.MakeUpper();
    cout<//ABCDEF中文123456

    void MakeLower( );
    將大寫字母轉換為小寫字母
    例:csStr="ABCDEF中文123456";
    csStr.MakeLower();
    cout<//abcdef中文123456

    int Compare( LPCTSTR lpsz ) const;
    區分大小寫比較兩個字符串,相等時返回0,大於時返回1,小於時返回-1
    例:csStr="abcdef中文123456";
    csStr2="ABCDEF中文123456";
    cout< //0

    int CompareNoCase( LPCTSTR lpsz ) const;
    不區分大小寫比較兩個字符串,相等時返回0,大於時返回1,小於時返回-1
    例:csStr="abcdef中文123456";
    csStr2="ABCDEF中文123456";
    cout<//-1

    int Delete( int nIndex, int nCount = 1 )
    刪除字符,刪除從下標nIndex開始的nCount個字符
    例:csStr="ABCDEF";
    csStr.Delete(2,3);
    cout<// ABF
    //當nIndex過大,超出對像所在內存區域時,函數沒有任何操作。
    //當nIndex為負數時,從第一個字符開始刪除。
    //當nCount過大,導致刪除字符超出對像所在內存區域時,會發生無法預料的結果。
    //當nCount為負數時,函數沒有任何操作。

    int Insert( int nIndex, TCHAR ch )
    int Insert( int nIndex, LPCTSTR pstr )

    在下標為nIndex的位置,插入字符或字符串。返回插入後對象的長度
    例:csStr="abc";
    csStr.Insert(2,'x');
    cout< //abxc
    csStr="abc";
    csStr.Insert(2,"xyz");
    cout< //abxyzc
    //當nIndex為負數時,插入在對象開頭
    //當nIndex超出對象末尾時,插入在對象末尾

    int Remove( TCHAR ch );
    移除對象內的指定字符。返回移除的數目
    例:csStr="aabbaacc";
    csStr.Remove('a');
    cout< //bbcc

    int Replace( TCHAR chOld, TCHAR chNew );
    int Replace( LPCTSTR lpszOld, LPCTSTR lpszNew );

    替換字串
    例:csStr="abcdef";
    csStr.Replace('a','x');
    cout<//xbcdef
    csStr="abcdef";
    csStr.Replace("abc","xyz");
    cout<//xyzdef

    void TrimLeft( );
    void TrimLeft( TCHAR chTarget );
    void TrimLeft( LPCTSTR lpszTargets );

    從左刪除字符,被刪的字符與chTarget或lpszTargets匹配,一直刪到第一個不匹配的字符為止
    例:csStr="aaabaacdef";
    csStr.TrimLeft('a');
    cout<//baacdef
    csStr="aaabaacdef";
    csStr.TrimLeft("ab");
    cout< //cdef
    //無參數時刪除空格

    void TrimRight( );
    void TrimRight( TCHAR chTarget );
    void TrimRight( LPCTSTR lpszTargets );

    從右刪除字符,被刪的字符與chTarget或lpszTargets匹配,一直刪到第一個不匹配的字符為止
    例:csStr="abcdeaafaaa";
    csStr.TrimRight('a');
    cout<//abcdeaaf
    csStr="abcdeaafaaa";
    csStr.TrimRight("fa");
    cout<//abcde
    //無參數時刪除空格

    void Empty( );
    清空
    例:csStr="abcdef";
    csStr.Empty();
    printf("%d",csStr.GetLength()); //0

    BOOL IsEmpty( ) const;
    測試對象是否為空,為空時返回零,不為空時返回非零
    例:csStr="abc";
    cout<//0;
    csStr.Empty();
    cout<//1;

    int Find( TCHAR ch ) const;
    int Find( LPCTSTR lpszSub ) const;
    int Find( TCHAR ch, int nStart ) const;
    int Find( LPCTSTR pstr, int nStart ) const;

    查找字串,nStart為開始查找的位置。未找到匹配時返回-1,否則返回字串的開始位置
    例:csStr="abcdef";
    cout<//1
    cout<//3
    cout<//-1
    cout<//1
    cout<//-1
    cout<//3
    //當nStart超出對象末尾時,返回-1。
    //當nStart為負數時,返回-1。

    int FindOneOf( LPCTSTR lpszCharSet ) const;
    查找lpszCharSet中任意一個字符在CString對象中的匹配位置。未找到時返回-1,否則返回字串的開始位置
    例:csStr="abcdef";
    cout< //2

    CString SpanExcluding( LPCTSTR lpszCharSet ) const;
    返回對象中與lpszCharSet中任意匹配的第一個字符之前的子串
    例:csStr="abcdef";
    cout<//ab

    CString SpanIncluding( LPCTSTR lpszCharSet ) const;
    從對象中查找與lpszCharSe中任意字符不匹配的字符,並返回第一個不匹配字符之前的字串
    例:csStr="abcdef";
    cout<//abcd

    int ReverseFind( TCHAR ch ) const;
    從後向前查找第一個匹配,找到時返回下標。沒找到時返回-1
    例:csStr="abba";
    cout<//3

    void Format( LPCTSTR lpszFormat, ... );
    void Format( UINT nFormatID, ... );

    格式化對象,與C語言的sprintf函數用法相同
    例:csStr.Format("%d",13);
    cout<//13

    TCHAR GetAt( int nIndex ) const;
    返回下標為nIndex的字符,與字符串的[]用法相同
    例:csStr="abcdef";
    cout<//c
    //當nIndex為負數或超出對象末尾時,會發生無法預料的結果。

    void SetAt( int nIndex, TCHAR ch );
    給下標為nIndex的字符重新賦值
    例:csStr="abcdef";
    csStr.SetAt(2,'x');
    cout<//abxdef
    //當nIndex為負數或超出對象末尾時,會發生無法預料的結果。

    CString Left( int nCount ) const;
    從左取字串
    例:csStr="abcdef";
    cout< //abc
    //當nCount等於0時,返回空。
    //當nCount為負數時,返回空。
    //當nCount大於對象長度時,返回值與對象相同。

    CString Right( int nCount ) const;
    從右取字串
    例:csStr="abcdef";
    cout<//def
    //當nCount等於0時,返回空。
    //當nCount為負數時,返回空。
    //當nCount大於對象長度時,返回值與對象相同。

    CString Mid( int nFirst ) const;
    CString Mid( int nFirst, int nCount ) const;

    從中間開始取字串
    例:csStr="abcdef";
    cout<//cdef
    csStr="abcdef";
    cout<//cde
    //當nFirst為0和為負數時,從第一個字符開始取。
    //當nFirst等於對象末尾時,返回空字串。
    //當nFirst超出對象末尾時,會發生無法預料的結果。
    //當nCount超出對象末尾時,返回從nFirst開始一直到對象末尾的字串
    //當nCount為0和為負數時,返回空字串。

    LPTSTR GetBuffer( int nMinBufLength );
    申請新的空間,並返回指針
    例:csStr="abcde";
    LPTSTR pStr=csStr.GetBuffer(10);
    strcpy(pStr,"12345");
    csStr.ReleaseBuffer();
    pStr=NULL;
    cout< //12345
    //使用完GetBuffer後,必須使用ReleaseBuffer以更新對象內部數據,否則會發生無法預料的結果。

    void ReleaseBuffer( int nNewLength = -1 );
    使用GetBuffer後,必須使用ReleaseBuffer以更新對象內部數據
    例:csStr="abc";
    LPTSTR pStr=csStr.GetBuffer(10);
    strcpy(pStr,"12345");
    cout<//3(錯誤的用法)
    csStr.ReleaseBuffer();
    cout<//5(正確)
    pStr=NULL;
    //CString對象的任何方法都應在ReleaseBuffer之後調用

    LPTSTR GetBufferSetLength( int nNewLength );
    申請新的空間,並返回指針
    例:csStr="abc";
    csStr.GetBufferSetLength(20);
    cout<//abc
    count< //20;
    csStr.ReleaseBuffer();
    count<//3;
    //使用GetBufferSetLength後可以不必使用ReleaseBuffer。

    2010年9月1日 星期三

    在Linux(ubuntu) 中Eclipse 安裝Android ADT & SDK

    我們已經裝好了Eclipse 在Linux (ubuntu)
    要在Eclipse 寫Android 程式
    還需要再安裝ADT (Android Development Tools)
    還有Android SDK
    首先要先裝ADT 才能裝Android SDK
    Step1 安裝Android ADT (Android Development Tools) -Android 的開發工具
    1. 點選Help -> Install New Software..
    2. 在Available Software 下 按下 右邊的一個"Add" 按鈕
    3. 跳出一個Add Repository 視窗,填入下列資訊
    <<在線安裝>>
    在"Name"的欄位填入: ADT

    按下ok ,接著eclipse 就會搜尋合適的版本
    下方會出現development Tools 的選項 ,請全選後按install 再按Next 就會開始安裝
    如果在這時後有出現error
    <<就要使用離線安裝的方法>>
    下載後的ADT解壓縮,接著一樣的方法進入到 Add Repository視窗
    這時後按旁邊的"Local"按鈕,選我們解完壓縮的ADT
    一樣"Name" 填入 ADT, "Location" 已經自動填上了
    之後的步驟就跟在線安裝是一樣的
    Step 2. 下載安裝Android SDK
    1. 先到Android 官網下載SDK,下載完後解壓縮
    2. 接著進到Eclipse -> Window -> Preferences
    3. 在跳出的Preferences 視窗左邊的欄位選擇Android
    4. 接著在右邊的SDK Location 欄位按下"Browse", 選擇解壓縮完的SDK
    5. 按下"Apply" 和 "OK" 就會開始安裝SDK
    這樣就結束SDK 和ADT的安裝
    可以開始寫Android 的程式了~

    在Linux 中安裝Eclipse (for Android)

    因為案子的需求需要將Eclipse安裝到Linux系統中

    就順便筆記一下

    其實很簡單就到 Eclipse的官方網站下載Linux 版本的Eclipse

    背景環境: WINNDOWS XP 下使用Sun VirtualBox 進入Linux系統

    Step1. 下載安裝JDK


    在我的例子是選擇

    Platform: Linux

    下載完後到Linux系統裡執行安裝

    會得到一個包含jdk的文件夾,名字會類似jdk1.5 (會依下載版本不同而不一樣,在此處以jdk1.5版為例)

    接著打開終端機 用root的身份 依序輸入下列指令

    mv jdk1.5 /usr/local/lib ln
    -sf /usr/local/lib/jdk1.5/bin/java /usr/bin/java ln 
    -sf /usr/local/lib/jdk1.5/bin/javac /usr/bin/javac
    p.s root 的身份就是指在 jdk1.5存放的路徑執行

    Step2. 下載Eclipse


    下載版本: Eclipse IDE for Java EE Developers
    (注意! 如果不是下載這個版本很可能在安裝ADT的時後會出現error 無法成功)

    下載完後就放到Linux裡解壓縮

    會產生eclipse 資料夾

    直接點資料夾裡的eclipse.exe執行

    這時後會跳出一個error message 讓你無法正確的開啟eclipse

    內容是說你沒裝JDK,沒錯我們不是裝了嗎?

    在Linux裡我們還要再用終端機讓JDK再安裝到eclipse裡

    做法如下:

    1. 先進到jdk所在的目錄

    2.輸入下列指令

    -> sudo apt-get install java


    下一篇就是在Eclipse安裝Android 的ADT 和 SDK


    2010年8月13日 星期五

    Android 入門

    最近在看Android
    找了一些可以線上看的電子書
    覺得還蠻詳細的
    從環境的設置開始都教的很清楚
    想入門android可以看以下的連結

    我個人覺得第一個連結教的比較易懂
    也比較接近目前使用的android 版本

    在學Android前最好是先看Java
    有點Java的基礎概念架構
    因為Android 是base on java
    真有點後悔為什麼大學的時後沒有好好學小java
    T_T 應該說怎麼沒認真學程式