安卓LMNOP新特性及適配

前言

HI萍悴,歡迎來到《每周一博》。今天是十月第三周寓免,我給大家分享一下安卓各系統(tǒng)版本的新特性和開發(fā)過程中的適配.

安卓每次升級(jí)都會(huì)帶來一些重大的改變癣诱,在性能,安全上都會(huì)有所提升袜香,每個(gè)版本也都有其各自的特點(diǎn)撕予,比如L引入的MaterialDesign設(shè)計(jì),M增加對(duì)權(quán)限和耗電的控制蜈首,N支持的多窗口和VR实抡,O對(duì)后臺(tái)進(jìn)程的限制欠母,P對(duì)流海屏的支持等。

當(dāng)然吆寨,每個(gè)版本都需要開發(fā)者去適配赏淌,開發(fā)者明顯可以感到系統(tǒng)對(duì)權(quán)限的收緊和安全上的重視,過去很多粗放的代碼都要變更啄清,典型的比如M的權(quán)限適配六水,N的FileProvider,O的后臺(tái)限制盒延,P的安全上的配配等缩擂,這里我將針對(duì)LMNOP這5個(gè)版本中重大的適配做一個(gè)簡(jiǎn)單總結(jié)鼠冕。

安卓各版本新特性

安卓L

  1. 引入Material Design設(shè)計(jì)添寺,增加UI控件和動(dòng)畫效果, V7支持庫(kù)中增加新控件以便向下兼容懈费;
  2. 系統(tǒng)由以往的Dalvik模式改為采用ART(Android Runtime)模式计露,實(shí)現(xiàn)ahead-of-time (AOT)靜態(tài)編譯與just-in-time (JIT)動(dòng)態(tài)編譯交互進(jìn)行;
  3. 支持64位系統(tǒng)憎乙;

安卓M

  1. 新增運(yùn)行時(shí)權(quán)限概念:系統(tǒng)默認(rèn)給app授權(quán)部分基礎(chǔ)權(quán)限票罐,其他敏感權(quán)限,需要運(yùn)行時(shí)手動(dòng)請(qǐng)求系統(tǒng)授予權(quán)限泞边;
  2. 新增Doze模式:可以自動(dòng)識(shí)別手機(jī)使用狀態(tài)该押,并在閑時(shí)主動(dòng)關(guān)閉部分后臺(tái)進(jìn)程以節(jié)省能耗;
  3. 新增待機(jī)模式: 針對(duì)很少使用的應(yīng)用阵谚,將不再消耗電量
  4. 新增指紋解鎖API蚕礼;

安卓N:

  1. 通知中心變的便捷且更強(qiáng)大,下拉通知欄中最上方加入了快捷按鍵控制開關(guān)梢什,同時(shí)通知中心能顯示更多的信息奠蹬,用戶可以在通知中心內(nèi)快速回復(fù);
  2. 支持多窗口功能嗡午;
  3. 支持VR囤躁,以使開發(fā)者能為用戶打造高質(zhì)量移動(dòng) VR 體驗(yàn);
  4. 引入全新的JIT編譯器荔睹,使得App安裝速度快了75%狸演,編譯代碼的規(guī)模減少了50%;
  5. App快捷菜單僻他,長(zhǎng)按APP圖標(biāo)可以快速進(jìn)入某些功能界面宵距;

安卓O:

  1. 支持畫中畫模式;
  2. 自動(dòng)填充中姜,對(duì)于用戶設(shè)備上最常用的應(yīng)用消玄,Android O將會(huì)幫助用戶進(jìn)行快速登錄跟伏,而不用每次都填寫賬戶名和密碼;
  3. 自適應(yīng)圖標(biāo)翩瓜,為開發(fā)者提供了適應(yīng)其顯示設(shè)備的每個(gè)圖標(biāo)的多個(gè)形狀模板受扳,來解決Android中APP圖標(biāo)形狀不一致的問題;
  4. 通知提醒兔跌,當(dāng)通知欄有未讀信息時(shí)勘高,會(huì)出現(xiàn)一個(gè)小點(diǎn),這時(shí)候長(zhǎng)按應(yīng)用程序圖標(biāo)坟桅,就會(huì)以類似氣泡的形式快速預(yù)覽华望。
  5. 后臺(tái)進(jìn)程限制,當(dāng)應(yīng)用被置入后臺(tái)后仅乓,將自動(dòng)智能限制后臺(tái)應(yīng)用活動(dòng)赖舟,主要會(huì)限制應(yīng)用的廣播,后臺(tái)運(yùn)行和位置夸楣,但應(yīng)用的整體進(jìn)程并沒有被殺掉宾抓。
  6. 運(yùn)行時(shí)權(quán)限策略變化,系統(tǒng)只會(huì)授予應(yīng)用明確請(qǐng)求的權(quán)限豫喧,而一旦用戶為應(yīng)用授予某個(gè)權(quán)限石洗,則所有后續(xù)對(duì)該權(quán)限組中權(quán)限的請(qǐng)求都將被自動(dòng)批準(zhǔn)。

安卓P:

  1. 支持流海屏紧显,系統(tǒng)會(huì)管理狀態(tài)欄的高度從而將內(nèi)容與裁切區(qū)域分開讲衫,如果擁有重要的沉浸式內(nèi)容,則還可以使用新的API查看裁切形狀并創(chuàng)建全屏布局孵班;
  2. 多攝像頭API涉兽,可以通過兩個(gè)或更多實(shí)體攝像頭同時(shí)訪問視頻流;
  3. 新增了ImageDecoder類重父,為解碼圖像提供了一種更優(yōu)的方法花椭;
  4. 增加神經(jīng)網(wǎng)絡(luò)API-1.1版本;

安卓各版本開發(fā)適配

安卓L-5.0

  1. Service服務(wù)必須采用顯示方式啟動(dòng)
    解決辦法有兩種房午,一種是設(shè)置Action和packageName矿辽,這也是推薦的方案,另一種是通過PackageManager遍歷所有符合的ComponentName郭厌;
Intent intent = new Intent();
// service定義的action
intent.setAction("XXX.XXX.XXX");
// service所在的包名
intent.setPackage(getPackageName());
context.startService(mIntent);
  1. 通知欄適配
    5.0以上需要通過NotificationCompat.Builder來創(chuàng)建通知袋倔,而不是直接new Notification或new Notification.Builder,另外在8.0之上還需要適配折柠,后面再說宾娜;
   Notification notification = new NotificationCompat.Builder(mContext)
     .setContentTitle(name)
     .setContentText(contentText)
     .setSmallIcon(R.drawable.stat)
     .setContentIntent(pi)
     .build();
  1. 關(guān)閉通知權(quán)限不彈Toast
    其實(shí)看過Toast源碼就知道它是通知欄服務(wù)NotificationManagerService維護(hù)的一個(gè)隊(duì)列,通過調(diào)用 WindowManager來添加view扇售,所以關(guān)閉通知權(quán)限后無法顯示Toast前塔。
 public void show() {
        if (mNextView == null) {
            throw new RuntimeException("setView must have been called");
        }
        INotificationManager service = getService();
        String pkg = mContext.getOpPackageName();
        TN tn = mTN;
        tn.mNextView = mNextView;
        try {
            service.enqueueToast(pkg, tn, mDuration);
        } catch (RemoteException e) {
        }
    }

    static private INotificationManager getService() {
        if (sService != null) {
            return sService;
        }
        sService = INotificationManager.Stub.asInterface(ServiceManager.getService("notification"));
        return sService;
    }

解決辦法可以自己去實(shí)現(xiàn)一個(gè)Toast嚣艇,使用隊(duì)列來維護(hù),用WindowManager來addView华弓,或者直接使用第三方庫(kù)食零。

  1. View的高度與陰影
    View新增加了z軸屬性,來體現(xiàn)MaterialDesign中的層次寂屏,影響的因素有translationZ和elevation贰谣。
    計(jì)算View高度= elevation + translationZ
    (1) transtionZ屬性表示view在Z方向移動(dòng)的距離,一般用于屬性動(dòng)畫中迁霎;
    (2) elevation表示view的陰影吱抚,可以在xml中直接使用屬性, 也可以在代碼中使用view.setEvelvation()考廉;elevation也能起到權(quán)重的作用秘豹,因?yàn)橛嘘幱暗谋厝皇窃谄胀▽蛹?jí)的上面,具體的關(guān)于elevation和transtionZ的說明可以參考這篇文章芝此。

高度會(huì)影響View的繪制順序憋肖,以前是按View添加順序繪制因痛,現(xiàn)在高度小的先繪制婚苹,因?yàn)閷蛹?jí)低,在下面鸵膏, 高度相同的膊升,按添加順序繪制,需要注意的是如果View的背景色為透明谭企,則不會(huì)顯示出陰影效果廓译,另外只有子View的大小比父View小時(shí),陰影才能顯示出來债查;

安卓M-6.0

  1. 動(dòng)態(tài)權(quán)限申請(qǐng)
    當(dāng)targetSdkVersion>=23的時(shí)候, 需要用checkSelfPermission()用來檢測(cè)App是否被授予了權(quán)限非区,比如定位的時(shí)候需要先去檢查是否擁有相關(guān)權(quán)限,如果沒有盹廷,可以使用requestPermissions()用來請(qǐng)求權(quán)限 征绸,這是Activity的方法,同時(shí)在回調(diào)方法onRequestPermissionsResult里面判斷結(jié)果俄占。

  2. 棄用HttpClient
    Android6.0版本移除了對(duì)Httpclient的支持管怠,建議我們使用HttpUrlConnection,如果仍要堅(jiān)持使用缸榄,需要在build.gradle中添加如下代碼:

android {  
    useLibrary 'org.apache.http.legacy'  
} 
  1. Doze模式對(duì)定時(shí)器的影響
    在Doze模式下渤弛,標(biāo)準(zhǔn) AlarmManager鬧鈴,包括 setExact() 和 setWindow()將推遲到下一維護(hù)時(shí)段甚带,如果需要設(shè)置在低電耗模式下觸發(fā)的鬧鈴她肯,可以使用setAndAllowWhileIdle() 或setExactAndAllowWhileIdle()方法佳头,這2個(gè)方法只能在15分鐘喚醒一次,如果你的廣播需要1分鐘廣播很多次晴氨,也只能15分鐘一次畜晰。setAlarmClock()將不會(huì)受Doze模式影響,但是它會(huì)耗電瑞筐, 所以必須在節(jié)約電量和業(yè)務(wù)之間做個(gè)取舍凄鼻。

  2. 獲取硬件標(biāo)識(shí)符需要權(quán)限
    WifiInfo.getMacAddress()和BluetoothAdapter.getAddress()將始終返回02:00:00:00:00:00,為了在M上可以掃描WiFi或藍(lán)牙聚假,需具有ACCESS_FINE_LOCATION和 ACCESS_COARSE_LOCATION權(quán)限

安卓N-7.0

  1. 私有文件權(quán)限收緊
    私有文件的文件權(quán)限不再放權(quán)給全部的應(yīng)用块蚌,使用 MODE_WORLD_READABLE 或 MODE_WORLD_WRITEABLE 進(jìn)行的操作將觸發(fā) SecurityException。

  2. 文件共享使用FileProvider
    在N上Android 框架強(qiáng)制運(yùn)行了StrictMode膘格,禁止對(duì)外公開file:// URI峭范,也就是說不能發(fā)起包含文件file:// URI類型的Intent ,這樣會(huì)出現(xiàn)FileUriExposedException異常瘪贱,比如調(diào)用系統(tǒng)相機(jī)拍照或相冊(cè)纱控。

(1) 先在清單文件里面配置FileProvider

<provider
    android:name="android.support.v4.content.FileProvider"
    android:authorities="${applicationId}.fileprovider"
    android:grantUriPermissions="true"
    android:exported="false">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/file_paths" />
</provider>

其中exported必須為false,true會(huì)報(bào)安全異常菜秦,grantUriPermissions為true表示授予URI訪問權(quán)限甜害。

(2) 指定共享的文件夾
在res文件夾下創(chuàng)建一個(gè)xml文件夾,然后創(chuàng)建一個(gè)名為“file_paths”(和注冊(cè)的Provider所引用的resource保持一致就可以)的資源文件球昨,內(nèi)容如下;

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

代碼中path="."尔店,表示根文件夾,也就是說你能夠向其它的應(yīng)用共享根文件夾及其子文件夾下的任何文件主慰,假設(shè)你把path設(shè)為path="pictures"嚣州, 那么它表示根文件夾下的pictures文件夾,如/storage/emulated/0/pictures共螺,那么向其它應(yīng)用分享pictures文件夾之外的文件是不行的该肴。

path下必須包含一到多個(gè)子元素,這些子元素用于指定共享文件的目錄路徑藐不,必須是這些元素之一:

  1. <files-path>:內(nèi)部存儲(chǔ)空間應(yīng)用私有目錄下的 files/ 目錄匀哄,等同于 Context.getFilesDir() 所獲取的目錄路徑;
  2. <cache-path>:內(nèi)部存儲(chǔ)空間應(yīng)用私有目錄下的 cache/ 目錄佳吞,等同于 Context.getCacheDir() 所獲取的目錄路徑拱雏;
  3. <external-path>:外部存儲(chǔ)空間根目錄,等同于 Environment.getExternalStorageDirectory() 所獲取的目錄路徑底扳;
  4. <external-files-path>:外部存儲(chǔ)空間應(yīng)用私有目錄下的 files/ 目錄铸抑,等同于 Context.getExternalFilesDir(null) 所獲取的目錄路徑;
  5. <external-cache-path>:外部存儲(chǔ)空間應(yīng)用私有目錄下的 cache/ 目錄衷模,等同于 Context.getExternalCacheDir()鹊汛;

可以看出蒲赂,這五種子元素基本涵蓋內(nèi)外存儲(chǔ)空間所有目錄路徑,包含應(yīng)用私有目錄刁憋。每個(gè)子元素都擁有 name 和 path 兩個(gè)屬性滥嘴,path 屬性用于指定當(dāng)前子元素所代表目錄下需要共享的子目錄名稱。注意path屬性值不能使用具體的獨(dú)立文件名至耻,只能是目錄名若皱,而name屬性用于給 path 屬性所指定的子目錄名稱取一個(gè)別名。后續(xù)生成content:// URI 時(shí)尘颓,會(huì)使用這個(gè)別名代替真實(shí)目錄名走触。這樣做的目的,很顯然是為了提高安全性疤苹。

如果我們需要分享的文件位于同級(jí)別目錄下不同的子目錄中互广,就需要添加多個(gè)子元素逐一指定要分享的文件目錄,或者共享他們通用的父目錄也行卧土。

(3) 使用FileProvider惫皱,比如調(diào)用相機(jī)

String filePath = Environment.getExternalStorageDirectory() + 
"/images/"+System.currentTimeMillis()+".jpg";
File outputFile = new File(filePath);
if (!outputFile.getParentFile().exists()) {
    outputFile.getParentFile().mkdir();
}
// 這里的uri要和manifest里面的對(duì)應(yīng)上
Uri contentUri = FileProvider.getUriForFile(this,BuildConfig.APPLICATION_ID + ".myprovider", outputFile);
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, contentUri);
startActivityForResult(intent, REQUEST_TAKE_PICTURE);

安卓O-8.0

  1. 通知欄增加渠道
    安卓O增加了渠道,使得用戶可以選擇接受哪些渠道的通知尤莺,上一張圖比較直觀旅敷。


這里我上一份最終的通知欄適配代碼,經(jīng)歷各版本的缝裁;

    public void showNotification(){
        final int NOTIFICATION_ID = 12234;
        NotificationManager notificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
        Intent intent = new Intent();
        String action = "com.tamic.myapp.action";
        intent.setAction(action);
 
        Notification notification = null;
        String contentText;
        PendingIntent pi = PendingIntent.getActivity(mContext, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT);
 
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
            notification = new Notification();
            notification.icon = android.R.drawable.stat_sys_download_done;
            notification.flags |= Notification.FLAG_AUTO_CANCEL;
            notification.setLatestEventInfo(mContext, aInfo.mFilename, contentText, pi);
            // 5.0適配
        } else if (Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.O && Build.VERSION.SDK_INT >= LOLLIPOP_MR1) {
            notification = new NotificationCompat.Builder(mContext)
                    .setContentTitle("Title")
                    .setContentText(contentText)
                    .setSmallIcon(android.R.drawable.stat_sys_download_done)
                    .setContentIntent(pi).build();
            // 4.4適配
        } else if ( Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN && Build.VERSION.SDK_INT <= LOLLIPOP_MR1) {
            notification = new Notification.Builder(mContext)
                    .setAutoCancel(false)
                    .setContentIntent(pi)
                    .setSmallIcon(android.R.drawable.stat_sys_download_done)
                    .setWhen(System.currentTimeMillis())
                    .build();
            // 8.0適配
        } else if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
            String CHANNEL_ID = "my_channel_01";
            CharSequence name = "my_channel";
            String Description = "This is my channel";
            int importance = NotificationManager.IMPORTANCE_HIGH;
            NotificationChannel mChannel = new NotificationChannel(CHANNEL_ID, name, importance);
            mChannel.setDescription(Description);
            mChannel.enableLights(true);
            mChannel.setLightColor(Color.RED);
            mChannel.enableVibration(true);
            mChannel.setVibrationPattern(new long[]{100, 200, 300, 400, 500, 400, 300, 200, 400});
            mChannel.setShowBadge(false);
            // 這里配置了渠道
            notificationManager.createNotificationChannel(mChannel);
            notification = new NotificationCompat.Builder(ctx, CHANNEL_ID)
                    .setSmallIcon(android.R.drawable.stat_sys_download_done)
                    .setContentTitle("Title").build();
        }
        notificationManager.notify(NOTIFICATION_ID, notification);
    }
  1. 安裝APK
    Android)去除了“允許未知來源”選項(xiàng)扫皱,所以如果我們的App有安裝App的功能,比如檢查更新之類的捷绑,那么會(huì)無法正常安裝。

首先在AndroidManifest文件中添加安裝未知來源應(yīng)用的權(quán)限:

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

這樣系統(tǒng)會(huì)自動(dòng)詢問用戶完成授權(quán)氢妈,當(dāng)然也可以先使用 canRequestPackageInstalls()查詢是否有此權(quán)限粹污,如果沒有的話使用Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES這個(gè)action將用戶引導(dǎo)至安裝未知應(yīng)用權(quán)限界面去授權(quán)。

    private void installAPK(){
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            boolean hasInstallPermission = getPackageManager().canRequestPackageInstalls();
            if (hasInstallPermission) {
                //安裝應(yīng)用
            } else {
                //跳轉(zhuǎn)至“安裝未知應(yīng)用”權(quán)限界面首量,引導(dǎo)用戶開啟權(quán)限
                Uri selfPackageUri = Uri.parse("package:" + this.getPackageName());
                Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES, selfPackageUri);
                startActivityForResult(intent, REQUEST_CODE_UNKNOWN_APP);
            }
        }else {
            //安裝應(yīng)用
        }
    }

    //接收“安裝未知應(yīng)用”權(quán)限的開啟結(jié)果
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == REQUEST_CODE_UNKNOWN_APP) {
            installAPK();
        }
    }
  1. 懸浮窗適配
    使用 SYSTEM_ALERT_WINDOW 權(quán)限的應(yīng)用必須使用名為TYPE_APPLICATION_OVERLAY 的新窗口類型壮吩,以下窗口類型將無法顯示:
    TYPE_PHONE
    TYPE_PRIORITY_PHONE
    TYPE_SYSTEM_ALERT
    TYPE_SYSTEM_OVERLAY
    TYPE_SYSTEM_ERROR

需要在之前的基礎(chǔ)上判斷一下:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    mWindowParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
}else {
    mWindowParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT
}

另外需要有權(quán)限

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

安卓P-9.0

  1. 前臺(tái)Service權(quán)限
    在 Android P中,如果 targeSdkVersion 升級(jí)到 28加缘,使用前臺(tái) Service 必須要申請(qǐng)F(tuán)OREGROUND_SERVICE權(quán)限鸭叙,如果沒有申請(qǐng)?jiān)摍?quán)限,系統(tǒng)會(huì)拋出SecurityException拣宏,該權(quán)限為普通權(quán)限沈贝,申請(qǐng)自動(dòng)授予應(yīng)用。

  2. 序列號(hào)棄用
    在 Android P中勋乾,Build.SERIAL 始終設(shè)置為 "UNKNOWN" 宋下,來保護(hù)用戶的隱私嗡善。如果需要訪問設(shè)備的硬件序列號(hào),需要請(qǐng)求 READ_PHONE_STATE 權(quán)限学歧,然后調(diào)用 getSerial()罩引;

  3. 默認(rèn)啟用網(wǎng)絡(luò)傳輸層安全協(xié)議 (TLS)
    在 Android P 中,默認(rèn)情況下 isCleartextTrafficPermitted() 函數(shù)返回 false枝笨。 如果應(yīng)用需要為特定域名啟用明文袁铐,必須在應(yīng)用的網(wǎng)絡(luò)安全性配置中針對(duì)這些域名將 cleartextTrafficPermitted 顯式設(shè)置為 true。所以無法及時(shí)把服務(wù)器變更為 https 的應(yīng)用横浑,應(yīng)該通過配置文件針對(duì)特定域名允許使用明文傳輸昭躺,也就是http服務(wù)。

先定義配置文件 res/xml/network_security_config.xml:

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <domain-config cleartextTrafficPermitted="true">
        <domain includeSubdomains="true">secure.example.com</domain>
    </domain-config>
</network-security-config>

然后在manifest.xml中使用

<application android:networkSecurityConfig="@xml/network_security_config">
  1. WiFi相關(guān)權(quán)限變更

(1)在Android 8.0和Android 8.1上:三選一
調(diào)用 WifiManager.getScanResults() 需要以下任何一項(xiàng)權(quán)限伪嫁,如果調(diào)用應(yīng)用程序沒有任何這些權(quán)限领炫,則調(diào)用將失敗并顯示 SecurityException。
ACCESS_FINE_LOCATION
ACCESS_COARSE_LOCATION
CHANGE_WIFI_STATE

(2)Android 9及更高版本:全部滿足
調(diào)用 WifiManager.startScan() 需要滿足以下所有條件:
具有 ACCESS_FINE_LOCATION 或 ACCESS_COARSE_LOCATION 權(quán)限张咳;
具有 CHANGE_WIFI_STATE 權(quán)限帝洪;

調(diào)用 WifiManager.getScanResults() 需要滿足以下所有條件:
具有 ACCESS_FINE_LOCATION 或 ACCESS_COARSE_LOCATION 權(quán)限;
具有 ACCESS_WIFI_STATE 權(quán)限脚猾;
設(shè)備上啟用了位置服務(wù)葱峡;

這個(gè)限制條件也適用于getConnectionInfo() 函數(shù),該函數(shù)返回描述當(dāng)前WiFi連接的WifiInfo 對(duì)象龙助。 如果調(diào)用應(yīng)用具有以下權(quán)限砰奕,則只能使用該對(duì)象的函數(shù)來檢索 SSID 和 BSSID 值:
具有 ACCESS_FINE_LOCATION 或 ACCESS_COARSE_LOCATION 權(quán)限;
具有 ACCESS_WIFI_STATE 權(quán)限提鸟;
檢索 SSID 或 BSSID 還需要在設(shè)備上啟用位置服務(wù)军援;

結(jié)尾:

本周給大家簡(jiǎn)單介紹了各系統(tǒng)版本的新特性和開發(fā)適配,具體更多的內(nèi)容可以參考其他文章称勋。感謝大家的閱讀胸哥,我們下周再見。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末赡鲜,一起剝皮案震驚了整個(gè)濱河市空厌,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌银酬,老刑警劉巖嘲更,帶你破解...
    沈念sama閱讀 210,978評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異揩瞪,居然都是意外死亡赋朦,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來北发,“玉大人纹因,你說我怎么就攤上這事×詹Γ” “怎么了瞭恰?”我有些...
    開封第一講書人閱讀 156,623評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)狱庇。 經(jīng)常有香客問我惊畏,道長(zhǎng),這世上最難降的妖魔是什么密任? 我笑而不...
    開封第一講書人閱讀 56,324評(píng)論 1 282
  • 正文 為了忘掉前任颜启,我火速辦了婚禮,結(jié)果婚禮上浪讳,老公的妹妹穿的比我還像新娘缰盏。我一直安慰自己,他們只是感情好淹遵,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,390評(píng)論 5 384
  • 文/花漫 我一把揭開白布口猜。 她就那樣靜靜地躺著,像睡著了一般透揣。 火紅的嫁衣襯著肌膚如雪济炎。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,741評(píng)論 1 289
  • 那天辐真,我揣著相機(jī)與錄音须尚,去河邊找鬼。 笑死侍咱,一個(gè)胖子當(dāng)著我的面吹牛耐床,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播放坏,決...
    沈念sama閱讀 38,892評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼咙咽,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了淤年?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,655評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤蜡豹,失蹤者是張志新(化名)和其女友劉穎麸粮,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體镜廉,經(jīng)...
    沈念sama閱讀 44,104評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡弄诲,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片齐遵。...
    茶點(diǎn)故事閱讀 38,569評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡寂玲,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出梗摇,到底是詐尸還是另有隱情拓哟,我是刑警寧澤,帶...
    沈念sama閱讀 34,254評(píng)論 4 328
  • 正文 年R本政府宣布伶授,位于F島的核電站断序,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏糜烹。R本人自食惡果不足惜违诗,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,834評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望疮蹦。 院中可真熱鬧诸迟,春花似錦、人聲如沸愕乎。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽妆毕。三九已至慎玖,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間笛粘,已是汗流浹背趁怔。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評(píng)論 1 264
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留薪前,地道東北人润努。 一個(gè)月前我還...
    沈念sama閱讀 46,260評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像示括,于是被迫代替她去往敵國(guó)和親铺浇。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,446評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容