Android O 遷移(適配Android 8.0)

Android O Migrating

小夥伴們現在裝載android 8.0 的手機已經在市面銷售那麼作爲程序員的我們是否已經完成面向Android O的遷移了呢?


現在我們介紹下 Android O新的改動:

通知

在 Android 8.0 中,我們已重新設計通知,以便爲管理通知行爲和設置提供更輕鬆和更統一的方式。這些變更包括:

  • Android 8.0 中的通知長按菜單。
    通知渠道:Android 8.0 引入了通知渠道,其允許您爲要顯示的每種通知類型創建用戶可自定義的渠道。用戶界面將通知渠道稱之爲通知類別。要了解如何實現通知渠道的信息,請參閱通知渠道指南。

    • 通知標誌:Android 8.0 引入了對在應用啓動器圖標上顯示通知標誌的支持。通知標誌可反映某個應用是否存在與其關聯、並且用戶尚未予以清除也未對其採取行動的通知。通知標誌也稱爲通知點。要了解如何調整通知標誌,請參閱通知標誌指南。

    • 休眠:用戶可以將通知置於休眠狀態,以便稍後重新顯示它。重新顯示時通知的重要程度與首次顯示時相同。應用可以移除或更新已休眠的通知,但更新休眠的通知並不會使其重新顯示。

    • 通知超時:現在,使用 setTimeoutAfter() 創建通知時您可以設置超時。您可以使用此函數指定一個持續時間,超過該持續時間後,通知應取消。如果需要,您可以在指定的超時持續時間之前取消通知。

    • 通知設置:當您使用 Notification.INTENT_CATEGORY_NOTIFICATION_PREFERENCESIntent 從通知創建指向應用通知設置的鏈接時,您可以調用 setSettingsText() 來設置要顯示的文本。此係統可以提供以下 Extra 數據和 Intent,用於過濾應用必須向用戶顯示的設置:EXTRA_CHANNEL_ID、NOTIFICATION_TAG 和 NOTIFICATION_ID。
    • 通知清除:系統現在可區分通知是由用戶清除,還是由應用移除。要查看清除通知的方式,您應實現 NotificationListenerService 類的新 onNotificationRemoved() 函數。
    • 背景顏色:您現在可以設置和啓用通知的背景顏色。只能在用戶必須一眼就能看到的持續任務的通知中使用此功能。例如,您可以爲與駕車路線或正在進行的通話有關的通知設置背景顏色。您還可以使用 Notification.Builder.setColor() 設置所需的背景顏色。這樣做將允許您使用 Notification.Builder.setColorized() 啓用通知的背景顏色設置。
    • 消息樣式:現在,使用 MessagingStyle 類的通知可在其摺疊形式中顯示更多內容。對於與消息有關的通知,您應使用 MessagingStyle 類。您還可以使用新的 addHistoricMessage() 函數,通過向與消息相關的通知添加歷史消息爲會話提供上下文。

自動填充框架

Android 8.0 允許以畫中畫 (PIP) 模式啓動操作組件。PIP 是一種特殊的多窗口模式,最常用於視頻播放。目前,PIP 模式可用於 Android TV,而 Android 8.0 則讓該功能可進一步用於其他 Android 設備。

當某個 Activity 處於 PIP 模式時,它會處於暫停狀態,但仍應繼續顯示內容。因此,您應確保您的應用在 onPause() 處理程序中進行處理時不會暫停播放。相反,您應在 onStop() 中暫停播放視頻,並在 onStart() 中繼續播放。如需瞭解詳細信息,請參閱多窗口生命週期。

要指定您的 Activity 可以使用 PIP 模式,請在清單中將 android:supportsPictureInPicture 設置爲 true。(從 Android 8.0 開始,如果您打算在 Android TV 或其他 Android 設備上支持 PIP 模式,則無需將 android:resizeableActivity 設置爲 true;只有在您的 Activity 支持其他多窗口模式時,才需要設置 android:resizeableActivity。)

API 變更

Android 8.0 引入一種新的對象 PictureInPictureParams,您可以將該對象傳遞給 PIP 函數來指定某個 Activity 在其處於 PIP 模式時的行爲。此對象還指定了各種屬性,例如操作組件的首選縱橫比。

現在,在添加畫中畫中介紹的現有 PIP 函數可用於所有 Android 設備,而不僅限於 Android TV。此外,Android 8.0 還提供以下函數來支持 PIP 模式:

  • Activity.enterPictureInPictureMode(PictureInPictureParams args):將操作組件置於畫中畫模式。操作組件的縱橫比和其他配置設置均由 args 指定。如果 args 中的任何字段爲空,系統將使用您上次調用 Activity.setPictureInPictureParams() 時所設置的值。
    指定的操作組件被置於屏幕的一角,屏幕剩餘部分則被屏幕顯示的上一個操作組件填滿。進入 PIP 模式的 Activity 將進入暫停狀態,但仍保持已啓動狀態。如果用戶點按此 PIP 操作組件,系統將顯示一個菜單供用戶操作,而在操作組件處於 PIP 狀態期間,不會理會任何觸摸事件。

  • Activity.setPictureInPictureParams():更新操作組件的 PIP 配置設置。如果操作組件目前處於 PIP 模式,則會更新此設置;如果操作組件的縱橫比發生變化,這非常有用。如果操作組件不處於 PIP 模式,則會使用這些配置設置,而不會考慮您調用的 enterPictureInPictureMode() 函數。

自動調整 TextView 的大小

Android 8.0 允許您根據 TextView 的大小自動設置文本展開或收縮的大小。這意味着,在不同屏幕上優化文本大小或者優化包含動態內容的文本大小比以往簡單多了。如需瞭解有關如何在 Android 8.0 中自動調整 TextView 的大小的詳細信息,請參閱自動調整 TextView 的大小

自適應圖標

Android 8.0 引入自適應啓動器圖標。自適應圖標支持視覺效果,可在不同設備型號上顯示爲各種不同的形狀。要了解如何創建自適應圖標,請參閱自適應圖標預覽功能指南。

更多請參閱Android 8.0 功能和 API


通知功能適配

1:Create a new class and name it NotificationUtils, extending ContextWrapper.
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Context;
import android.content.ContextWrapper;
import android.graphics.Color;


public class NotificationUtils extends ContextWrapper {


    private NotificationManager mManager;
    public static final String ANDROID_CHANNEL_ID = "com.chikeandroid.tutsplustalerts.ANDROID";
    public static final String IOS_CHANNEL_ID = "com.chikeandroid.tutsplustalerts.IOS";
    public static final String ANDROID_CHANNEL_NAME = "ANDROID CHANNEL";
    public static final String IOS_CHANNEL_NAME = "IOS CHANNEL";


    public NotificationUtils(Context base) {
        super(base);
        createChannels();
    }


    public void createChannels() {


        // create android channel
        NotificationChannel androidChannel = new NotificationChannel(ANDROID_CHANNEL_ID,
                ANDROID_CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT);
        // Sets whether notifications posted to this channel should display notification lights
        androidChannel.enableLights(true);
        // Sets whether notification posted to this channel should vibrate.
        androidChannel.enableVibration(true);
        // Sets the notification light color for notifications posted to this channel
        androidChannel.setLightColor(Color.GREEN);
        // Sets whether notifications posted to this channel appear on the lockscreen or not
        androidChannel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);


        getManager().createNotificationChannel(androidChannel);


        // create ios channel
        NotificationChannel iosChannel = new NotificationChannel(IOS_CHANNEL_ID,
                IOS_CHANNEL_NAME, NotificationManager.IMPORTANCE_HIGH);
        iosChannel.enableLights(true);
        iosChannel.enableVibration(true);
        iosChannel.setLightColor(Color.GRAY);
        iosChannel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
        getManager().createNotificationChannel(iosChannel);
    }


    private NotificationManager getManager() {
        if (mManager == null) {
            mManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        }
        return mManager;
    }
}

在上面的代碼中,我們創建了兩個NotificationChannel實例,傳遞一個id(在你的包裏必須是唯一的),一個通道名,還有一個重要性級別的構造函數。 對於每個通知頻道,我們都會應用聲音,燈光,振動和通知等特徵來顯示在鎖定屏幕上。 最後,我們從系統中獲得了NotificationManager,然後通過調用createNotificationChannel()方法來註冊頻道,傳遞我們創建的頻道。

我們可以使用createNotificationChannels()一次創建多個通知通道,並傳遞Java列表的NotificationChannel實例。 您可以使用getNotificationChannels()獲取應用程序的所有通知頻道,並使用getNotificationChannel()獲取特定頻道,只傳遞頻道ID作爲參數。

Importance Levels

從Android O開始,各個通知不推薦使用優先級。 而是在創建通知渠道時設置重要性級別,範圍從NotificationManager.IMPORTANCE_NONE到NotificationManager.IMPORTANCE_HIGH。 我們將Android頻道設置爲IMPORTANCE_DEFAULT,而iOS頻道的頻道爲IMPORTANCE_HIGH。

可用的重要選項的完整列表是:

  • IMPORTANCE_MAX:未使用
  • IMPORTANCE_HIGH:到處顯示,造成噪音和偷看
  • IMPORTANCE_DEFAULT:處處顯示,產生噪音,但不會在視覺上侵入
  • IMPORTANCE_LOW:處處顯示,但不侵入
  • IMPORTANCE_MIN:僅在摺疊下的陰影中顯示
  • IMPORTANCE_NONE:通知無關緊要; 不在陰涼處顯示
    所有通道的通知將被賦予相同的重要性級別。
Create Notifications and Post to Channels

指定應該將哪個通知發送到Notification.Builder(Android API 25)構造函數中的通道,我們將通道ID作爲第二個參數傳遞給它。

// ...
public Notification.Builder getAndroidChannelNotification(String title, String body) {
    return new Notification.Builder(getApplicationContext(), ANDROID_CHANNEL_ID)
            .setContentTitle(title)
            .setContentText(body)
            .setSmallIcon(android.R.drawable.stat_notify_more)
            .setAutoCancel(true);
}


public Notification.Builder getIosChannelNotification(String title, String body) {
    return new Notification.Builder(getApplicationContext(), IOS_CHANNEL_ID)
            .setContentTitle(title)
            .setContentText(body)
            .setSmallIcon(android.R.drawable.stat_notify_more)
            .setAutoCancel(true);
}
//...

請注意,Notification.Builder()也有一個名爲setChannel(String channelId)的通知通道id setter方法,因此您可以選擇在構造函數中使用通知通道id或使用setter方法。

Create the XML Layout

現在我們已經創建併發布到通知渠道,我們創建XML佈局接口,將消息發佈到我們的activity_main.xml中。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/activity_main"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:layout_margin="16dp"
        tools:context="com.chikeandroid.tutsplusalerts.MainActivity">


    <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">


        <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Tuts+ Android Channel"
                android:layout_gravity="center_horizontal"
                android:textAppearance="@style/TextAppearance.AppCompat.Title"/>


        <EditText
                android:id="@+id/et_android_title"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="Title"/>


        <EditText
                android:id="@+id/et_android_author"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="Author"/>


        <Button
                android:id="@+id/btn_send_android"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="Send"/>
    </LinearLayout>


    <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:layout_marginTop="20dp">


        <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Tuts+ IOS Channel"
                android:layout_gravity="center_horizontal"
                android:textAppearance="@style/TextAppearance.AppCompat.Title"/>


        <EditText
                android:id="@+id/et_ios_title"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="Title"
                />


        <EditText
                android:id="@+id/et_ios_author"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="Author"/>
        <Button
                android:id="@+id/btn_send_ios"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="Send"/>
    </LinearLayout>


</LinearLayout>
Post Notifications to Channels

發佈到Android頻道
在本節中,我們將編輯我們的MainActivity,以便我們可以從EditText組件獲取標題和作者,然後將其發送到Android頻道。 我們爲我們在NotificationUtils中創建的Android頻道獲取Notification.Builder,然後通知NotificationManager。

import android.app.Notification;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;


public class MainActivity extends AppCompatActivity {


    private NotificationUtils mNotificationUtils;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        mNotificationUtils = new NotificationUtils(this);


        final EditText editTextTitleAndroid = (EditText) findViewById(R.id.et_android_title);
        final EditText editTextAuthorAndroid = (EditText) findViewById(R.id.et_android_author);
        Button buttonAndroid = (Button) findViewById(R.id.btn_send_android);


        buttonAndroid.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                String title = editTextTitleAndroid.getText().toString();
                String author = editTextAuthorAndroid.getText().toString();


                if(!TextUtils.isEmpty(title) && !TextUtils.isEmpty(author)) {
                    Notification.Builder nb = mNotificationUtils.
                            getAndroidChannelNotification(title, "By " + author);


                    mNotificationUtils.getManager().notify(101, nb.build());
                }
            }
        });
    }
}

此時,運行應用程序並輸入標題和作者,然後單擊發送按鈕以立即接收通知。
在這裏,我們將發佈到iOS頻道。 我們爲我們在NotificationUtils中創建的iOS通道獲取Notification.Builder,然後在NotificationManager中調用notify()方法。

@Override
protected void onCreate(Bundle savedInstanceState) {


    // ...


    final EditText editTextTitleIos = (EditText) findViewById(R.id.et_ios_title);
    final EditText editTextAuthorIos = (EditText) findViewById(R.id.et_ios_author);
    Button buttonIos = (Button) findViewById(R.id.btn_send_ios);
    buttonIos.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            String title = editTextTitleIos.getText().toString();
            String author = editTextAuthorIos.getText().toString();


            if(!TextUtils.isEmpty(title) && !TextUtils.isEmpty(author)) {
                Notification.Builder nb = mNotificationUtils
                        .getIosChannelNotification(title, "By " + author);


                mNotificationUtils.getManager().notify(102, nb.build());
            }
        }
    });
}

再次運行應用程序並輸入標題和作者,然後單擊發送按鈕立即接收通知。

Notification Channel Settings

再次運行應用程序並輸入標題和作者,然後單擊發送按鈕立即接收通知。在撰寫本文時,不能以編程方式更改特定通知通道設置的配置。 相反,唯一可用的選項是讓用戶在設備設置中轉到應用程序的通知設置屏幕。 從那裏,用戶可以訪問應用程序通知設置來修改設置,如振動,聲音等。用戶可以通過以下任一方式導航到應用程序通知設置:

  • 長按通知抽屜上的通知。
  • 設置>應用程序和通知>通知>然後選擇應用程序

您也可以將用戶從您的應用程序發送到頻道通知設置。 我們來看看我們如何爲Android頻道做到這一點。 建議您在應用設置中執行此操作,以方便用戶訪問這些通知選項。
編輯XML佈局
加入另一個按鈕,將用戶發送到頻道通知設置

<!--...-->
<Button
    android:id="@+id/btn_android_notif_settings"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="Notification Settings"/>
<!--...-->

在這裏,我們創建一個意圖,並將其傳遞給設置操作ACTION_CHANNEL_NOTIFICATION_SETTINGS(API 25),然後添加一些額外的值:應用程序包名稱和頻道ID。 最後,我們開始設置活動的意圖。

// ...
@Override
protected void onCreate(Bundle savedInstanceState) {
    //...
    Button buttonAndroidNotifSettings = (Button) findViewById(R.id.btn_android_notif_settings);
    buttonAndroidNotifSettings.setOnClickListener(new View.OnClickListener() {


        @Override
        public void onClick(View view) {
            Intent i = new Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS);
            i.putExtra(Settings.EXTRA_APP_PACKAGE, getPackageName());
            i.putExtra(Settings.EXTRA_CHANNEL_ID, NotificationUtils.ANDROID_CHANNEL_ID);
            startActivity(i);
        }
    });
}
//...

運行應用程序,然後單擊Android通道的通知設置。
或顯示頻道的徽章(如果支持)。

如果您想讓用戶訪問您的應用的一般通知設置,也可以使用Intent來完成:

Intent i = new Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS);
i.putExtra(Settings.EXTRA_APP_PACKAGE, getPackageName());
startActivity(i);

廣播

對於程序中的廣播 在Android O中將會取消靜態廣播,如果你的代碼中含有靜態廣播 更改爲動態廣播即可(想一想早就應該改成這樣)

解決8.0無法使用PackageManager 安裝apk

只需要在AndroidManifest中添加權限

<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />

至於各種新API 大家移步Android Develop

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章