1. 程式人生 > >適配Android6.0到8.0詳細過程——小白教程

適配Android6.0到8.0詳細過程——小白教程

前言:

由於GooglePlay在2018年11月1日開始上架專案要求targetSdkVersion在26以上,因此只能版本適配了。我的專案版本是22,也就是Android5.1,之前也沒有做過版本適配,只能一邊查資料一邊摸索著搞,如果有不對的地方,或者有更好的解決方案,歡迎聯絡指出!

準備工作:

要適配Android8.0首先要先把AndroidStudio升級到AndroidStudio3.0以上版本。

開啟project.properties,設定

target=android-26

開啟配置檔案build.gradle,修改targetSdkVersion,compileSdkVersion為26以上,更新gradle版本為最新版本,我這裡更新的是gradle:3.2.1

具體如下:

compileSdkVersion 26
targetSdkVersion 26

dependencies {
    classpath
'com.android.tools.build:gradle:3.2.1'
}

具體截圖:

buildToolsVersion 會在更新gradle時自動更新成28.0.3 或更新版本。

=========分割線==============

如果有用到程式碼混淆的話,可能回遇到下面這個異常:

更新前程式碼:

    buildTypes {

release {

            // 是否進行混淆

            minifyEnabled false

            zipAlignEnabled true

            shrinkResources true

            // 混淆檔案的位置

proguardFiles getDefaultProguardFile('proguard-project.txt'), 'proguard-project.txt'

            buildConfigField "boolean", "LOG_DEBUG", "false"

        }    debug {

            buildConfigField "boolean", "LOG_DEBUG", "true"

        }

}

更新後報出異常:

User supplied default proguard base extension name is unsupported

解決:

proguardFile ('TIS-SmarthomeV5.0.3/.../proguard-project.txt')

異常:Removing unused resources requires unused code shrinking to be turned on.

解決:

minifyEnabled true  //這裡原本是false改成true

如果不使用程式碼混淆:

// 是否進行混淆

minifyEnabled false
zipAlignEnabled false

shrinkResources false

=======分割線========

編譯,根據錯誤提示,如果之前是用compile的,把compile改成implementation,testCompile改成testImplementation, instrumentTest改成androidTest。

另外如果專案有使用到multidex 突破64k限制解決方案的有可能回報下面這種異常:

解決:

implementation 'com.android.support:multidex:1.0.3'

把依賴改成最新版,我這裡是改成1.0.3,然後就能解決Failed to resolve: multidex這個異常了。

接著下面那個異常是這樣解決的:

修改專案根目錄的那個build.gradle檔案中repositories, 保持google()在第一位置:
allprojects {
    repositories {
        google()//
保持這個放在頂部
        mavenCentral()
        maven {
            url "https://jitpack.io"
        }
        maven{
            url 'https://maven.google.com'
        }
        jcenter()//
保持這個放在底部
    }

具體截圖:

接著編譯,

如果出現編譯異常:

Please correct the above warnings first.

看Messages 檢視提示,可以在你的混淆檔案proguard-rules.pro裡面新增下面這句程式碼遮蔽警告:

-ignorewarnings

繼續編譯,有可能會出現v4jar包keyeventcompat不存在的異常:

Error:(30, 31) 錯誤: 找不到符號
符號:    KeyEventCompat

位置: 程式包 android.support.v4.view

解決:

KeyEventCompat類被取消了 hasNoModifiers方法已經被KeyEvent實現了

報錯:

if (KeyEventCompat.hasNoModifiers(event)) {

    handled = arrowScroll(FOCUS_FORWARD);

} else if (KeyEventCompat.hasModifiers(event, KeyEvent.META_SHIFT_ON)) {

    handled = arrowScroll(FOCUS_BACKWARD);

}

改成:

if (event.hasNoModifiers()) {

    handled = arrowScroll(FOCUS_FORWARD);

} else if (event.hasModifiers(KeyEvent.META_SHIFT_ON)) {

    handled = arrowScroll(FOCUS_BACKWARD);

}

=======================分割線======================

完成以上操作可以成功編譯執行之後,開始先適配6.0的動態許可權:

Android6.0開始,官方對許可權的要求越來越嚴格,所以一些危險許可權需要在程式中動態獲取,讓使用者點選允許許可權才能獲取,普通許可權和以前沒區別,可以直接在清單檔案裡面配置獲取。而危險許可權在清單檔案裡面配置了,如果使用者沒有點選允許一樣是獲取不到的。具體哪些是危險許可權,哪些是普通許可權可以自己在網上查一下,這裡就不詳細說了。

首先在build.gradle中的dependencies裡面新增第三方許可權工具,這裡使用閆振杰封裝的第三方依賴:

dependencies {implementation 'com.yanzhenjie:permission:2.0.0-rc4'}

因為已經在配置檔案中添加了第三方依賴,所以我們可以直接使用別人封裝好的動態獲取許可權的API。一般來說,在開啟程式的主activity那裡我們就要向用戶申請許可權了,在MainActivity的onCreate()方法裡面申請,程式碼如下:

@Override
    public void onCreate(Bundle savedInstanceState) {
        getWindow().requestFeature(Window.FEATURE_NO_TITLE);//設定無標題
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_smartbus);

  	//寫你自己的初始化佈局…
    
   
        //獲取外部儲存許可權和地理位置許可權
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { //版本在23及以上
            AndPermission.with(this).permission(Permission.READ_EXTERNAL_STORAGE, Permission.WRITE_EXTERNAL_STORAGE,
                    Permission.ACCESS_FINE_LOCATION, Permission.ACCESS_COARSE_LOCATION).onGranted(new Action() {
                @Override
                public void onAction(List<String> permissions) {
                    //TODO
			//成功獲取許可權後要做的操作
                         }
            }).onDenied(new Action() {
                @Override
                public void onAction(List<String> permissions) {
//使用者拒絕許可權,toast提示使用者如果不允許許可權有部分功能將無法使用
                    Toast.makeText(HomepageActivity.this,
                            "Rejection may result in some functionality being unavailable.",
                            Toast.LENGTH_SHORT).show();
                }
            }).start();

        }else{//低於6.0版本的
          //TODO
        }
    }

如果還需要其他危險許可權可以直接在這裡後面新增: AndPermission.with(this).permission(Permission.READ_EXTERNAL_STORAGE, Permission.WRITE_EXTERNAL_STORAGE,
                   
Permission.ACCESS_FINE_LOCATION, Permission.ACCESS_COARSE_LOCATION,

…..

)

而其他危險許可權,例如相機許可權,傳送簡訊許可權,可以在需要用到的地方再申請,因為一開始向用戶申請太多許可權的話,使用者體驗不是那麼好。

例如,可以在開啟相機的回撥那裡動態申請相機許可權:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){//如果當前Android版本是6.0以上的
                    AndPermission.with(SettingActivity.this).permission(Permission.CAMERA).onGranted(new Action() {
                        @Override
                        public void onAction(List<String> permissions) {
                    //使用者允許許可權,啟用相機
                            
                    intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                    intent.putExtra(MediaStore.EXTRA_OUTPUT,
                        Uri.fromFile(new File(getExternalFilesDir("TIS-Smarthome/"), "photo_BgImage.png")));
                    startActivityForResult(intent, GET_BACKGROUND_PHOTOZOOM);
                        }
                    }).onDenied(new Action() {
                        @Override
                        public void onAction(List<String> permissions) {
                    //使用者拒絕許可權,toast提示拒絕許可權將使某些功能無法使用
                            Toast.makeText(SettingActivity.this,
                                    "Rejection may result in some functionality being unavailable.",
                                    Toast.LENGTH_SHORT).show();
                        }
                    }).start();
                }else {
                    //6.0以下的,直接啟動相機
                    intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                    intent.putExtra(MediaStore.EXTRA_OUTPUT,
                        Uri.fromFile(new File(getExternalFilesDir("TIS-Smarthome/"), "photo_BgImage.png")));
                    startActivityForResult(intent, GET_BACKGROUND_PHOTOZOOM);
                }

" TIS-Smarthome/"是專案名稱,"photo_BgImage.png"是拍照存放的圖片名稱,也就是外部儲存到你手機哪裡,儲存成什麼名字的圖片。

適配Android7.0

前面添加了兩個危險許可權之後,如果你的應用有使用相機功能,你會發現在應用中開啟相機就閃退。因為Android官方在7.0對私有目錄訪問進行了限制,這裡我們可以使用FileProvider來解決。(當然你得先申請了相機許可權,不會申請的參照上面的程式碼在啟動相機前申請。)

首先在清單檔案AndroidManifest.xml的application標籤下新增:

<application
        android:name="caro.automation.MyApplication"
        android:allowBackup="true"
        android:hardwareAccelerated="true"
        android:hasCode="true"
        android:icon="@drawable/tis"
        android:label="@string/app_name"
        android:usesCleartextTraffic="true"

        >


        <!--2018.10.16 相機打不開問題-->
        <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="你的包名.fileprovider"
            android:grantUriPermissions="true"
            android:exported="false"
            >
            <meta-data android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths" />

        </provider>

...
</application>

Provider標籤部分,file_paths是我們指定的檔案目錄,所以需要在res資料夾下的xml檔案目錄下新建file_paths.xml,然後編寫程式碼:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <paths>
        <external-path path="" name="camera_photos" />
    </paths>
</resources>

正常來說這樣已經可以在7.0系統里正常調起相機了,但是有的手機在7.0之後你的APP就算有許可權,給出一個URI之後手機也認為你沒有許可權,這個問題的解決方法是,在MyApplication的onCreate()方法中新增以下程式碼:

   /*2018.10.16 相機打不開問題*/
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)//如果當前Android版本大於7.0
        { StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
            StrictMode.setVmPolicy(builder.build());
        }

適配Android8.0

Android8.0主要是適配通知欄和圖示。我這邊只做了通知欄的適配。

由於我負責的專案是使用第三方個推的,所以適配Android8.0只需要更新個推到最新版GETUI_ANDROID_SDK_2.12.5.0就可以了。先到個推官網下載最新的個推SDKhttp://docs.getui.com/getui/version/

下載完之後根據他的接入文件重新接入一遍SDK就可以,這裡就不詳細描述了,畢竟我怎麼寫都沒有別人的接入文件詳細0.0

更新完個推SDK後,點選建立推送:

選擇目標使用者指定到你的測試機,傳送通知,如果能成功接收到通知就是適配成功了。

完成適配後,使用Androidstudio3.2進行打包,我這裡出現警告fastjson沒有找到相關的類或介面。解決:更新fastjson依賴1.2.51版本,更新完注意把舊版的jar包刪除,不然會報jar包重複,導致打包失敗。

還要注意的是,8.0移除了靜態廣播,所以廣播要改成動態註冊!