微信小程式沒有彈出相簿許可權申請視窗
在微信小程式開發中,將圖片或者視訊儲存到使用者手機是常見的業務需求之一。通過呼叫小程式的下載檔案以及儲存檔案到相簿的API才能完成,後者會向用戶申請許可權,一旦使用者不小心拒絕,那麼下次儲存檔案的時候將不再彈出許可權申請視窗,顯然這對使用者會造成困擾。
提示:如果使用者在首次許可權申請中拒絕,則必須在小程式的設定模組開啟該許可權,不再彈窗操作。
因此,作為開發者如何通過程式碼去引導使用者正確操作呢?
首先我們可以通過API(wx.getSetting)獲取當前小程式的設定資訊,檢視當前的許可權狀態。
wx.getSetting({ success: res => { console.log(res.authSetting) } })
提示:authSetting 是一個物件,儲存當權使用者的所有許可權設定,物件的 Key 為具體許可權別名,Value 為授權狀態,即 true 已經授權;false 為拒絕該許可權,如果沒有申請過授權,則不儲存在該物件中。
許可權別名請參考:https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/authorize.html
如果沒有授權,可以呼叫授權API(wx.authorize)向用戶發起授權,同樣只有第一次授許可權才會彈窗,如果被拒絕過,返回失敗。
wx.getSetting({ success: res=> { // 儲存到相簿的授權別名 res.scope = 'scope.writePhotosAlbum' if (!res.authSetting[res.scope]) { // 申請授權 wx.authorize({ scope: res.scope, success: res => { // 同意或已經授權 }, fail() { // 使用者拒絕授權 } }) } } })
因此,當用戶拒絕過授權後,只能引導使用者開啟設定介面,開啟相關許可權。開啟設定的API(wx.openSetting)返回當前新的設定資訊。
需要注意的是,wx.openSetting 無法直接呼叫,但可以在彈窗 wx.showModal 回撥中開啟。
wx.showModal({ content:'請允許小程式使用相簿許可權', success:()=>{ wx.openSetting({ success:result=>{ //如果使用者還是不肯授權,提示沒有許可權 if(!result.authSetting[res.scope]){ wx.showToast({ title:'未允許該許可權' }) } }, }) } })梳理一下,先獲取設定資訊,判斷是否授權,如果沒有或者拒絕過,然後引導使用者開啟設定介面開啟相關許可權。當然,即使如此,使用者可能仍然選擇不開啟許可權,那隻能提示使用者沒用許可權,無法儲存圖片或視訊,否則我們進行下一步操作。
整個過程完全是一個非同步的操作,所以在封裝的程式碼的時候,可以用 Promise 去完成。
分解一下操作,先下載視訊,然後判斷是否有許可權儲存圖片視訊檔案(包括引導使用者開啟相關許可權),最後才是去儲存,這一步難點在獲取非同步的操作,你得先知道使用者最後有沒有開啟許可權。
重點來了,業務程式碼封裝。
下載圖片視訊,呼叫下載檔案的API(wx.downloadFile)
function downloadFile(url, listener) { listener = listener || {} return new Promise((resolve, reject) => { listener.onStart && listener.onStart() const downloadTask = wx.downloadFile({ url, success: res => { // 下載狀態正常 if (res.statusCode == 200) { resolve(res) } else { reject(res) } } }) if (listener.onProgress) { downloadTask.onProgressUpdate(listener.onProgress) } }) }
上面封裝的 downloadFile 函式接受兩個引數,url 下載地址,listener 下載監聽回撥,物件型別,listener.onStart 開始下載回撥,listener.onProgress 下載進度回撥
儲存到相簿,繼續封裝,API(wx.saveVideoToPhotosAlbum)
functionsaveMediaToPhotosAlbum(url,listener){ downloadFile(url,listener).then(res=>{ wx.saveVideoToPhotosAlbum({ filePath:res.tempFilePath, success:listener.onComplete, fail:listener.onComplete }) }) }呼叫很簡單,如下
const url = 'http://example.com/xxx.mp4' saveMediaToPhotosAlbum(url, { onStart() { wx.showToast({ title: '開始下載', }) }, onComplete(res) { wx.showToast({ title: '下載完成', }) }, onProgress(res) { // 下載進度回撥 wx.showLoading({ title: res.progress + "%", }) } })
測試一下,你會發現,開始下載=》下載中=》進度在走,下載完成會彈出儲存到相簿許可權彈窗,當你點選允許後提示已經儲存到xxx(安卓)。好像挺完美,按照預想的過程走完,但別忘了,上面提到的授權問題,一旦拒絕,再呼叫就無法成功儲存。
所以,在下載完成後還要進行授權操作,如果授權成功再儲存到相簿,否則提示沒有許可權無法儲存。
同樣用 Promise 封裝
functionauthorize(scope){ scope='scope.writePhotosAlbum' returnnewPromise((resolve,reject)=>{ wx.getSetting({ success:res=>{ if(!res.authSetting[scope]){ wx.authorize({ scope, success:resolve, fail:()=>wx.showModal({ content:R.string.prompt_authorize_photos, //請允許小程式使用相簿許可權 success:()=>wx.openSetting({ success:res=>{ if(res.authSetting[scope]){ resolve(res.authSetting) }else{ wx.showModal({ content:R.string.prompt_authorize_cancel }) //未允許使用該許可權 reject(res.authSetting) } } }) }) }) }else{ resolve(res.authSetting) } } }) }) }因為是要在檔案下載完成後先判斷授權狀態,所以呼叫授權的程式碼應該放在 downloadFile 函式中,繼續改造
function downloadFile(url, listener) { listener = listener || {} return new Promise((resolve, reject) => { listener.onStart && listener.onStart() const downloadTask = wx.downloadFile({ url, success: res => { // 下載狀態正常 if (res.statusCode == 200) { resolve(res) } else { reject(res) } } }) if (listener.onProgress) { downloadTask.onProgressUpdate(listener.onProgress) } }).then(res => { return authorize().then(() => res).catch(() => { listener.onComplete() return Promise.reject(null) }) }) }
到處就大功告成,趕緊去試試。