1. 程式人生 > 實用技巧 >微信小程式沒有彈出相簿許可權申請視窗

微信小程式沒有彈出相簿許可權申請視窗

在微信小程式開發中,將圖片或者視訊儲存到使用者手機是常見的業務需求之一。通過呼叫小程式的下載檔案以及儲存檔案到相簿的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)
    })
  })
}

到處就大功告成,趕緊去試試。