Android 5.0 6.0 7.0 新特性

Android 5.0行為變更

API級(jí)別:21

Android Runtime(ART)

在 Android 5.0 中,ART 運(yùn)行時(shí)取代 Dalvik 成為平臺(tái)默認(rèn)設(shè)置。Android 4.4 中已引入處于實(shí)驗(yàn)階段的 ART 運(yùn)行時(shí)。
有關(guān) ART 的新功能概述,請(qǐng)參閱 ART 簡(jiǎn)介。部分主要的新功能包括: 預(yù)先 (AOT) 編譯,改進(jìn)的垃圾回收 (GC),改進(jìn)的調(diào)試支持。
ART與Dalvik的區(qū)別
程序運(yùn)行的過(guò)程中,Dalvik虛擬機(jī)在不斷的進(jìn)行將字節(jié)碼編譯成機(jī)器碼的工作。ART引入了AOT這種預(yù)編譯技術(shù),在應(yīng)用程序安裝的過(guò)程中,ART就已經(jīng)將所有的字節(jié)碼重新編譯成了機(jī)器碼。應(yīng)用程序運(yùn)行過(guò)程中無(wú)需進(jìn)行實(shí)時(shí)的編譯工作,只需要進(jìn)行直接調(diào)用.因此,ART極大的提高了應(yīng)用程序的運(yùn)行效率,同時(shí)也減少了手機(jī)的電量消耗,提高了移動(dòng)設(shè)備的續(xù)航能力,在垃圾回收等機(jī)制上也有了較大的提升。
相對(duì)于Dalvik虛擬機(jī)模式,ART模式下Android應(yīng)用程序的安裝需要消耗更多的時(shí)間,同時(shí)也會(huì)占用更大的儲(chǔ)存空間(指內(nèi)部?jī)?chǔ)存,用于儲(chǔ)存編譯后的代碼),但節(jié)省了很多Dalvik虛擬機(jī)用于實(shí)時(shí)編譯的時(shí)間。

ART與Dalvik的區(qū)別.jpg

大多數(shù) Android 應(yīng)用無(wú)需任何更改就可以在 ART 下工作。不過(guò),部分適合 Dalvik 的技術(shù)并不適用于 ART。如需了解有關(guān)最重要問(wèn)題的信息,請(qǐng)參閱在 Android Runtime (ART) 上驗(yàn)證應(yīng)用行為。如存在以下情況,應(yīng)特別注意:

  • 您的應(yīng)用使用 Java 原生接口 (JNI) 運(yùn)行 C/C++ 代碼。
  • 您使用生成非標(biāo)準(zhǔn)代碼的開發(fā)工具(例如,一些代碼混淆工具)。
  • 您使用與壓縮垃圾回收不兼容的技術(shù)。

Material Design 樣式

  • 概念:融合卡片式,立體式的設(shè)計(jì)風(fēng)格,強(qiáng)調(diào)層次感,動(dòng)畫,陰影等元素
  • 國(guó)內(nèi)翻譯介紹:查看 http://design.1sters.com
  • 官網(wǎng)介紹:http://developer.android.com/training/material
  • 演示Android5.0 Demo
  • Android UI樣式風(fēng)格發(fā)展:2.3版本(黃色丑陋版)->4.0(Holo)->5.0(MaterialDesign)

動(dòng)態(tài)替換Theme

修改狀態(tài)欄,ActionBar,界面背景,NavigationBar的顏色。讓Activity使用自定義的Theme。

<style name="AppTheme" parent="@android:style/Theme.Material">
    <!--狀態(tài)欄顏色-->
    <item name="android:colorPrimaryDark">#f00</item>
    <!--ActionBar顏色-->
    <item name="android:colorPrimary">#ff0</item>
    <!--界面背景顏色-->
    <item name="android:windowBackground">@color/colorWindowBackground</item>
    <!--導(dǎo)航欄顏色-->
    <item name="android:navigationBarColor">#00f</item>
</style>

動(dòng)態(tài)替換Theme的步驟:
1.定義至少2套theme
2.調(diào)用setTheme方法設(shè)置當(dāng)前的theme,但是該方法要在setContentView之前,如:

setTheme(mTheme);
setContentView(R.layout.activity_main);

設(shè)置了Theme,需要finish當(dāng)前Activity,然后重啟當(dāng)前Activity,讓Theme生效

Intent intent = getActivity().getIntent();
getActivity().finish();//結(jié)束當(dāng)前的Activity
getActivity().overridePendingTransition(0,0);//不要?jiǎng)赢?startActivity(intent);

Palette的使用

使用Palette可以讓我們從一張圖片中拾取顏色,將拾取到的顏色賦予ActionBar,StatusBar以及背景色可以讓界面色調(diào)實(shí)現(xiàn)統(tǒng)一,使用Palette需要添加以下依賴:

compile 'com.android.support:palette-v7:23.0.0+'

Palette提供的API
傳入Bitmap即可獲取Palette對(duì)象,以下是同步和異步使用方式:

//同步獲取,需要在子線程中使用
Palette palette = Palette.from(drawable.getBitmap()).generate();
//異步獲取,可以在主線程中使用
Palette.from(drawable.getBitmap()).generate(new Palette.PaletteAsyncListener() {
    @Override
    public void onGenerated(Palette palette) {
        //...
    }
});

得到Palette對(duì)象后,獲取其中的顏色,顏色對(duì)應(yīng)如下:


顏色對(duì)應(yīng).jpg

使用palette獲取指定顏色:

palette.getLightMutedColor(defaultColor);

也可以先獲取采樣對(duì)象Swatch,從Swatch中獲取我們需要的顏色:

//獲取有活力顏色的采樣對(duì)象
Palette.Swatch vibrantSwatch = palette.getVibrantSwatch();
采樣對(duì)象Swatch提供了以下方法來(lái)獲取顏色:
//swatch.getPopulation(): the amount of pixels which this swatch represents.
//swatch.getRgb(): the RGB value of this color.
//swatch.getHsl(): the HSL value of this color,即色相,飽和度,明度.
//swatch.getBodyTextColor(): the RGB value of a text color which can be displayed on top of this color.
//swatch.getTitleTextColor(): the RGB value of a text color which can be displayed on top of this color
//一般會(huì)將getRgb設(shè)置給控件背景色,getBodyTextColor()設(shè)置給文字顏色
textView.setBackgroundColor(vibrantSwatch.getRgb());
textView.setTextColor(vibrantSwatch.getBodyTextColor());

CardView的使用

CardLayout擁有高度和陰影,以及輪廓裁剪,圓角等功能。
各屬性說(shuō)明:

  • 設(shè)置圓角:card_view:cardCornerRadius="10dp"
  • 設(shè)置高度:card_view:cardElevation="10dp"
  • 設(shè)置內(nèi)邊距:card_view:contentPadding="10dp"
  • 設(shè)置背景色:card_view:cardBackgroundColor="?android:attr/colorPrimary"

RecyclerView的使用

  • https://developer.android.com/intl/zh-tw/training/material/lists-cards.html
  • 先添加依賴 compile 'com.android.support:recyclerview-v7:23.1.1'
  • 設(shè)置LayoutManager:控制RecyclerView如何顯示布局,系統(tǒng)提供3個(gè)布局管理器:
    • LinearLayoutManager:線性布局,有橫向和豎直方向顯示
    • GridLayoutManager:網(wǎng)格布局,有橫向和豎直方向顯示
    • StaggeredGridLayoutManager: 瀑布流布局,有橫向和豎直方向顯示
  • 然后給RecyclerView設(shè)置Adapter<RecyclerView.ViewHolder>
  • 設(shè)置點(diǎn)擊事件,由于RecyclerView沒有setOnItemClickListener,只能在Adapter中給View設(shè)置Click事件。

ToolBar的使用

它用來(lái)代替ActionBar,但是比ActionBar更加靈活,相當(dāng)于可以寫在布局文件中的ActionBar;與DrawerLayout的使用的時(shí)候,DrawerLayout可以覆蓋在ToolBar上,并且ToolBar和ActionBar不能同時(shí)使用
使用ToolBar的步驟:
先隱藏ActionBar,可以繼承一個(gè)不帶ActionBar的Theme,如:

style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar"

然后在Activity中設(shè)置ToolBar替代ActionBar:

setSupportActionBar(toolBar);

最后設(shè)置ToolBar的顯示內(nèi)容:

toolBar.setTitle("ToolBar");//設(shè)置標(biāo)題
toolBar.setNavigationIcon(iconRes);//設(shè)置圖標(biāo)
toolBar.setOnMenuItemClickListener();//設(shè)置Menu Item點(diǎn)擊

Android 6.0行為變更

API級(jí)別:23

運(yùn)行時(shí)權(quán)限

對(duì)于以 Android 6.0(API 級(jí)別 23)或更高版本為目標(biāo)平臺(tái)的應(yīng)用,請(qǐng)務(wù)必在運(yùn)行時(shí)檢查和請(qǐng)求權(quán)限。其中:

  • 新的方法checkSelfPermission()可以用來(lái)判斷你的應(yīng)用是否被授予了權(quán)限。
  • 而requestPermissions()可請(qǐng)求權(quán)限。
//判斷是否授予某個(gè)權(quán)限
public static boolean hasPermission(@NonNull Context context, @NonNull String... permissions) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            return true;
        }

        for (String permission : permissions) {
            boolean hasPermission = (ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED);
            if (!hasPermission) {
                return false;
            }
        }
        return true;
    }
//動(dòng)態(tài)請(qǐng)求權(quán)限
 public static void requestPermissions(Object o, int requestCode, String... permissions) {
        if (o instanceof Activity) {
            ActivityCompat.requestPermissions(((Activity) o), permissions, requestCode);
        } else if (o instanceof android.support.v4.app.Fragment) {
            ((android.support.v4.app.Fragment) o).requestPermissions(permissions, requestCode);
        }
    }

取消支持Apache HTTP客戶端

Android 6.0 版移除了對(duì) Apache HTTP 客戶端的支持。如果您的應(yīng)用使用該客戶端,并以 Android 2.3(API 級(jí)別 9)或更高版本為目標(biāo)平臺(tái),請(qǐng)改用 HttpURLConnection 類。此 API 效率更高,因?yàn)樗梢酝ㄟ^(guò)透明壓縮和響應(yīng)緩存減少網(wǎng)絡(luò)使用,并可最大限度降低耗電量。要繼續(xù)使用 Apache HTTP API,您必須先在 build.gradle 文件中聲明以下編譯時(shí)依賴項(xiàng):

android {
    useLibrary 'org.apache.http.legacy'
}

6.0新控件

使用需要依賴design類庫(kù):

compile 'com.android.support:design:23.0.0+'
TextInputLayout的使用

先在TextInputLayout中包裹一個(gè)EditText,如:

 <android.support.design.widget.TextInputLayout
            android:textColorHint="#fff"
            android:id="@+id/username"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
            <EditText
                android:textColor="#fff"
                android:id="@+id/edt_user"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="user" />
        </android.support.design.widget.TextInputLayout>

然后給EditText添加文本變化監(jiān)聽器:

editText.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                String name = username.getEditText().getText().toString();
                //例如用戶名必須包含 字母a
                if (!name.contains("a")) {
                    username.setError("Not a valid user name!");
                }else {
                    username.setErrorEnabled(false);
                }
            }

            @Override
            public void afterTextChanged(Editable s) {

            }
        });

實(shí)現(xiàn)效果:


TextInputLayout輸入框效果圖.gif
CoordinatorLayout的使用

CoordinatorLayout作為“super-powered FrameLayout”基本實(shí)現(xiàn)兩個(gè)功能:

  • 作為頂層布局
  • 調(diào)度協(xié)調(diào)子布局

與FloatingActionButton結(jié)合使用
定義布局:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="end|bottom"
        android:layout_margin="16dp"
        android:src="@drawable/ic_done" />
</android.support.design.widget.CoordinatorLayout>

activity:

 findViewById(R.id.fab).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view,"FAB",Snackbar.LENGTH_LONG)
                        .setAction("cancel", new View.OnClickListener() {
                            @Override
                            public void onClick(View v) {
                                //這里的單擊事件代表點(diǎn)擊消除Action后的響應(yīng)事件
                            }
                        })
                        .show();
            }
        });

實(shí)現(xiàn)效果:

fab效果.gif

與AppBarLayout結(jié)合使用
定義布局:

<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/main_content"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
            app:layout_scrollFlags="scroll|enterAlways" />

        <android.support.design.widget.TabLayout
            android:id="@+id/tabs"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

    </android.support.design.widget.AppBarLayout>

    <android.support.v4.view.ViewPager
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" />

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="end|bottom"
        android:layout_margin="@dimen/fab_margin"
        android:src="@drawable/ic_done" />

</android.support.design.widget.CoordinatorLayout>

效果:

tab效果.gif

具體還有很多用法,這里不一一介紹,參考: CoordinatorLayout的使用

Android 7.0行為變更

API級(jí)別:24

新的Notification

Android N 添加了很多新的notifications API,進(jìn)行了又一次的設(shè)計(jì),引入了新的風(fēng)格。

  • 模板更新: 開發(fā)人員將能夠充分利用新模板,僅僅需進(jìn)行少量的代碼調(diào)整。
  • 消息樣式自己定義: 新增自己定義樣式、消息回復(fù)、消息分組等更加靈活。
  • 捆綁通知: 系統(tǒng)能夠?qū)⑾⒔M合在一起(比如,按消息主題)并顯示組。用戶能夠適當(dāng)?shù)剡M(jìn)行 Dismiss 或 Archive 等操作。
  • 直接回復(fù): 對(duì)于實(shí)時(shí)通信應(yīng)用。Android 系統(tǒng)支持內(nèi)聯(lián)回復(fù),以便用戶能夠直接在通知界面中高速回復(fù)短信。
  • 自己定義視圖: 兩個(gè)新的 API ,在通知中使用自己定義視圖時(shí)能夠充分利用系統(tǒng)裝飾元素,如通知標(biāo)題和操作。

Project Svelte:后臺(tái)優(yōu)化

Project Svelte在持續(xù)改善,以最大程度降低生態(tài)系統(tǒng)中一系列 Android 設(shè)備中系統(tǒng)和應(yīng)用使用的 RAM。在 Android N 中,Project Svelte 注重優(yōu)化在后臺(tái)中運(yùn)行應(yīng)用的方式。
Android N 刪除了三項(xiàng)隱式廣播(CONNECTIVITY_ACTION、ACTION_NEW_PICTURE 和ACTION_NEW_VIDEO) 。以幫助優(yōu)化內(nèi)存使用和電量消耗。

權(quán)限更改

隨著Android版本號(hào)越來(lái)越高,Android對(duì)隱私的保護(hù)力度也越來(lái)越大。
從Android6.0引入的動(dòng)態(tài)權(quán)限控制(Runtime Permissions)到Android7.0的“私有文件夾被限制訪問(wèn)”,“StrictMode API 政策”。這些更改在為用戶帶來(lái)更加安全的操作系統(tǒng)的同一時(shí)候也為開發(fā)人員帶來(lái)了一些新的任務(wù)。怎樣讓你的APP能夠適應(yīng)這些改變而不是cash,是擺在每一位Android開發(fā)人員身上的責(zé)任。

文件夾被限制訪問(wèn),應(yīng)用間共享文件

在Android7.0系統(tǒng)上。Android 框架強(qiáng)制運(yùn)行了 StrictMode API 政策禁止向你的應(yīng)用外公開 file:// URI。
假設(shè)一項(xiàng)包含文件 file:// URI類型 的 Intent 離開你的應(yīng)用,應(yīng)用失敗,并出現(xiàn) FileUriExposedException 異常,如調(diào)用系統(tǒng)相機(jī)拍照,或裁切照片。
解決方法:
第一步:在manifest清單文件里注冊(cè)provider

        <!-- exported:要求必須為false,為true則會(huì)報(bào)安全異常。 -->
        <!-- grantUriPermissions:true,表示授予 URI 臨時(shí)訪問(wèn)權(quán)限。 -->
        <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="com.huayun.onenotice.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/filepaths" />
        </provider>

第二步:指定共享的文件夾
為了指定共享的文件夾我們須要在資源(res)文件夾下創(chuàng)建一個(gè)xml文件夾,然后創(chuàng)建一個(gè)名為“filepaths”(名字能夠隨便起,僅僅要和在manifest注冊(cè)的provider所引用的resource保持一致就可以)的資源文件。內(nèi)容例如以下:

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <!-- root-path 手機(jī)存儲(chǔ)根目錄 -->
    <!-- external-path:sd ;path:你的應(yīng)用保存文件的根目錄;name隨便定義-->
    <external-path path="" name="camera_photos" />
</paths>

第三步:使用FileProvider
上述準(zhǔn)備工作做完之后,如今我們就能夠使用FileProvider了。
以調(diào)用系統(tǒng)相機(jī)拍照為例,我們須要將上述拍照代碼改動(dòng)為例如以下:

File file=new File(Environment.getExternalStorageDirectory(), "/temp/"+System.currentTimeMillis() + ".jpg");
if (!file.getParentFile().exists())file.getParentFile().mkdirs();
      Uri imageUri = FileProvider.getUriForFile(context, "com.jph.takephoto.fileprovider", file);//通過(guò)FileProvider創(chuàng)建一個(gè)content類型的Uri
Intent intent = new Intent();
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); //加入這一句表示對(duì)目標(biāo)應(yīng)用暫時(shí)授權(quán)該Uri所代表的文件
intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);//設(shè)置Action為拍照
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);//將拍取的照片保存到指定URI
startActivityForResult(intent,1000);
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容