微信小程序沒有彈出相冊權限申請窗口


在微信小程序開發中,將圖片或者視頻保存到用戶手機是常見的業務需求之一。通過調用小程序的下載文件以及保存文件到相冊的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)

function saveMediaToPhotosAlbum(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 封裝

function authorize(scope) {
  scope = 'scope.writePhotosAlbum'
  return new Promise((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)
    })
  })
}

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

 

 

 

 

 

 

 

 

 

 

 

 



























免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM