Wednesday, December 28, 2016

Google Play Services

最後一項, 就係升級 Google Play Services.
本來以為只係改番個 version, 由 8.4.0 改成 10.0.1 就得, 點知出左 error.

(1) IAmHere

先由簡單既做起, IAmHere 無咁多野, 只係讀 location, 點解會出事?
如果直接改成 10.0.1, build 無問題, 出 APK 就會咁:

Error:Execution failed for task ':app:transformClassesWithDexForDebug'.
> com.android.build.api.transform.TransformException: com.android.ide.common.process.ProcessException: java.util.concurrent.ExecutionException: com.android.dex.DexIndexOverflowException: method ID not in [0, 0xffff]: 65536
網上搵下, 大致係因為係 DexIndex 上限係預設左 65535, 當你個 program 大多野加入去, 就會爆.
之前懶慣左, 成套 Google Play Services 加哂入去, 而 Google 又越加越多功能, 咪爆左囉.
解決方法, 一係加大佢, 一係就用少 D.

其實, Google play service 可以拆開黎加, 佢既 Setup Guide 有資料講有幾多舊既.
唔好咁懶了, 用左邊個咪加邊個囉.
就以 IAmHere 為例, 用得幾多 service?  咪就係一個 location service  咁大把, 唔駛成套加哂.
所以, 只要改成咁就得了:


  • compile 'com.google.android.gms:play-services-location:10.0.1'


(2) WhereAreYou

同樣, WhereAreYou 都係用左 location service 咁大把, 當然又係改番指定 location 就夠.
不過, 世事就係無咁完美既, 轉成 com.google.android.gms:play-services-location:8.4.0 無問題,
但一改成 10.0.1 就出錯了.
注意, Build Project 係無 error 既, 但係出 APK 就死得.

首先, 係會無哂 maps 既 service.  呢樣少事, google 將 maps 由 location 入面分左出黎, 加番呢句就得:
  • compile 'com.google.android.gms:play-services-maps:10.0.1'

不過, 之後就真係唔得了, 在 FindLocationActivity.jav 入面用到既 getMap() 既 method 無左了.
網上睇家陣要改用 getMapAsync(), 但 async mode 既做法又唔同了.

首先, getMapAsync 係 Async call, 咁本來放佢後面既 code, 就要拆出黎, 放去一個 callback method 度.
而 getMapAsync 需要一個 implement 左 OnMapReadyCallback 既 class, 咁最簡單就係將原本個 activity class (即係 FindLocationActivity) 再 implement 埋佢.

public class FindLocationActivity extends FragmentActivity
implements ConnectionCallbacks,
OnConnectionFailedListener,
LocationListener,
OnMyLocationButtonClickListener,
OnMapReadyCallback { .....
之後, 當然係加番有關既 method 喇, 而 OnMapReadyCallback 只係需要一個 OnMapReady 既 method, 而佢就會收到一個 GoogleMap 既 parameter, 順理成章, 就係將原本做完 getMap() 既 code, 放入去 呢個 method 就得了.

@Override
public void onMapReady(GoogleMap map) {
    mMap = map;
    if (mMap != null) {
        mMap.setMyLocationEnabled(true);
        mMap.setOnMyLocationButtonClickListener(this);
        mMap.getUiSettings().setZoomControlsEnabled(false);
    }
}

改完呢度, 基本上可以行得了.


一點手尾.....

不過, 其實 Build APK 果陣, 出左句野:
Note: E:\SourceTree\WhereAreYou\app\src\main\java\org\super169\findlocation\FindLocationActivity.java uses or overrides a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
呢個就同 getMap 一樣, 今次仲可以用, 遲下就會無.
之後會拆解埋佢, 咁就可以玩得耐 D.



又有野就黎唔用得, 同 getMap 之前一樣, 今次仲可以用, 遲下就會無.
懶既可以唔理佢, 反正今水仲用得, 有時間就睇下發生乜事.

由於 default 係比你過既, 所以唔知邊度死, 跟佢講 Recompile with -Xlint:deprecation for details.
打開 build.gradle, 加呢段野落最尾就得:

tasks.withType(JavaCompile) {
    options.compilerArgs << "-Xlint:deprecation"}

之後再  build APK, 就會出唔到了, 講埋邊度唔得, 原來係 SmsMessage.createFromPdu 出事:

E:\SourceTree\WhereAreYou\app\src\main\java\org\super169\findlocation\FindLocationActivity.java:189: warning: [deprecation] createFromPdu(byte[]) in SmsMessage has been deprecated
                    SmsMessage message = SmsMessage.createFromPdu((byte[]) pdus[i]);
又要上網搵笨法解決了.

本來, 最簡單既方法, 咪跟佢既 syntax 比埋個  format 佢就得:
String format = extras.getString("format");
SmsMessage message = SmsMessage.createFromPdu((byte[]) pdus[i], format);
世事總係無咁好既, 呢個 syntax 係 API Level 23 開始至用得, 即係要改  minSdkVersion 去到 23 或以上, 即係 Android 6.0 Marshmallow 之後既機至用到, 太過份了.

另一個方法, 就係用  Telephony, 先攞哂 d msg 再慢慢睇.

SmsMessage[] msgs = msgs = android.provider.Telephony.Sms.Intents.getMessagesFromIntent(intent);
for (int i = 0; i < msgs.length; i++) {
    SmsMessage message = msgs[i];


今次好 D, API Level 19 就有了 (即係 4.4 KitKat 開始).

所以, 針對 SmsMessage.createFromPdu 可以有以下幾個方案:


  1. 唔鬼理佢, 反正家陣仲用得, 可以 keep 住 midSdkVersion 18
  2. 轉用 Telephony 去讀 message, 而 midSdkVersion 只係升上 19, 影響唔算大
  3. 用 SmsMessage.createFromPdu 既新 Syntax, 但 midSdkVersion 就要上 23 至得
最後, 我暫時用第 2 個方案, 費事下次就要改.  



No comments:

Post a Comment