位置权限弹出窗口

Posted

技术标签:

【中文标题】位置权限弹出窗口【英文标题】:location permission popup 【发布时间】:2019-03-01 12:06:09 【问题描述】:

我正在用 PyQt5 和 Python 制作一个网络浏览器。如何使位置权限弹出如下:

这是我的代码:

from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtWebEngineWidgets import *
from PyQt5 import QtCore, QtGui, QtWidgets, QtWebEngineWidgets,QtWebEngine
from PyQt5.QtPrintSupport import *
import os
import sys
from time import sleep
from threading import Timer
import re
import urllib.request


class SearchPanel(QtWidgets.QWidget):
    searched = QtCore.pyqtSignal(str, QtWebEngineWidgets.QWebEnginePage.FindFlag)
    closed = QtCore.pyqtSignal()

    def __init__(self, parent=None):
        super(SearchPanel, self).__init__(parent)
        lay = QtWidgets.QHBoxLayout(self)
        self.case_button = QtWidgets.QPushButton('Match &Case', checkable=True)
        next_button = QtWidgets.QPushButton('&Next')
        prev_button = QtWidgets.QPushButton('&Previous')
        self.search_le = QtWidgets.QLineEdit()
        self.setFocusProxy(self.search_le)

        next_button.clicked.connect(self.update_searching)
        prev_button.clicked.connect(self.on_preview_find)
        self.case_button.clicked.connect(self.update_searching)
        for btn in (self.case_button, self.search_le, next_button, prev_button, ):
            lay.addWidget(btn)
            if isinstance(btn, QtWidgets.QPushButton): btn.clicked.connect(self.setFocus)
        self.search_le.textChanged.connect(self.update_searching)
        self.search_le.returnPressed.connect(self.update_searching)
        self.closed.connect(self.search_le.clear)

        QtWidgets.QShortcut(QtGui.QKeySequence.FindNext, self, activated=next_button.animateClick)
        QtWidgets.QShortcut(QtGui.QKeySequence.FindPrevious, self, activated=prev_button.animateClick)
        QtWidgets.QShortcut(QtGui.QKeySequence(QtCore.Qt.Key_Escape), self.search_le, activated=self.closed)

    @QtCore.pyqtSlot()
    def on_preview_find(self):
        self.update_searching(QtWebEngineWidgets.QWebEnginePage.FindBackward)

    @QtCore.pyqtSlot()
    def update_searching(self, direction=QtWebEngineWidgets.QWebEnginePage.FindFlag()):
        flag = direction
        if self.case_button.isChecked():
            flag |= QtWebEngineWidgets.QWebEnginePage.FindCaseSensitively
        self.searched.emit(self.search_le.text(), flag)

    def showEvent(self, event):
        super(SearchPanel, self).showEvent(event)
        self.setFocus(True)

class AboutDialog(QDialog):
    def __init__(self, *args, **kwargs):
        super(AboutDialog, self).__init__(*args, **kwargs)

        QBtn = QDialogButtonBox.Ok  # No cancel
        self.buttonBox = QDialogButtonBox(QBtn)
        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)

        layout = QVBoxLayout()
        title = QLabel("Pyxis Browser")
        font = title.font()
        font.setPointSize(20)
        title.setFont(font)

        layout.addWidget(title)

        logo = QLabel()
        logo.setPixmap(QPixmap(os.path.join('', 'ma-icon-128.png')))
        layout.addWidget(logo)

        layout.addWidget(QLabel("Version 1.0.0"))
        layout.addWidget(QLabel("Copyright."))

        for i in range(0, layout.count()):
            layout.itemAt(i).setAlignment(Qt.AlignHCenter)

        layout.addWidget(self.buttonBox)

        self.setLayout(layout)

class MyPage(QWebEnginePage):
    def __init__(self, *args, **kwargs):
        super(MyPage, self).__init__(*args, **kwargs)
    def triggerAction(self, action, checked=False):
        if action == QWebEnginePage.OpenLinkInNewWindow:
            self.createWindow(QWebEnginePage.WebBrowserWindow)

        return super(MyPage, self).triggerAction(action, checked)

class MainWindow(QMainWindow):

    def __init__(self, *args, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)

        self.browser = QWebEngineView()
        self.browser.setUrl(QUrl("https://androidd.pw/Login/"))
        QWebEnginePage.javascriptCanOpenWindows:True

        self.browser.urlChanged.connect(self.update_urlbar)
        self.browser.urlChanged.connect(self.page_loading)
        self.browser.loadFinished.connect(self.update_title)
        self.setCentralWidget(self.browser)
        self.status = QStatusBar()
        self.setStatusBar(self.status)

        self.setCentralWidget(self.browser)
        #self.browser.page().settings().setAttribute(QWebEngineSettings.AllowGeolocationOnInsecureOrigins, True)

        navtb = QToolBar("Navigation")
        navtb.setIconSize(QSize(16, 16))
        self.addToolBar(navtb)

        guide = QToolBar("Navigation")
        guide.setIconSize(QSize(16, 16))
        self.addToolBar(guide)

        self.guidestate = QLabel()  # Yes, really!
        self.guidestate.setText('Welcome to Pyxis Ad')

        font = self.guidestate.font()
        font.setPointSize(14)
        self.guidestate.setFont(font)
        guide.addWidget(self.guidestate)

        self.done_btn = QAction(QIcon(os.path.join('', 'done.png')), "Done", self)
        self.done_btn.setVisible(False)
        self.done_btn.triggered.connect(self.start_earning)
        guide.addAction(self.done_btn)

        self.child_domain = QAction(QIcon(os.path.join('', 'new_ad.png')), "Load New Pyxis Domain", self)
        self.child_domain.setVisible(False)
        self.child_domain.triggered.connect(self.load_child_domain)
        guide.addAction(self.child_domain)

        self.advertise = QAction(QIcon(os.path.join('', 'new_ad.png')), "Load New Avertisements Site", self)
        self.advertise.setVisible(False)
        self.advertise.triggered.connect(self.load_advertise)
        guide.addAction(self.advertise)

        self.load_new_url = QAction(QIcon(os.path.join('', 'new_ad.png')), "Reload New Site", self)
        self.load_new_url.setVisible(False)
        self.load_new_url.triggered.connect(self.new_ad_site)
        guide.addAction(self.load_new_url)

        back_btn = QAction(QIcon(os.path.join('', 'arrow-180.png')), "Back", self)
        back_btn.setStatusTip("Back to previous page")
        back_btn.triggered.connect(self.browser.back)
        navtb.addAction(back_btn)

        next_btn = QAction(QIcon(os.path.join('', 'arrow-000.png')), "Forward", self)
        next_btn.setStatusTip("Forward to next page")
        next_btn.triggered.connect(self.browser.forward)
        navtb.addAction(next_btn)

        reload_btn = QAction(QIcon(os.path.join('', 'arrow-circle-315.png')), "Reload", self)
        reload_btn.setStatusTip("Reload page")
        reload_btn.triggered.connect(self.browser.reload)
        navtb.addAction(reload_btn)

        home_btn = QAction(QIcon(os.path.join('', 'home.png')), "Home", self)
        home_btn.setStatusTip("Go home")
        home_btn.triggered.connect(self.navigate_home)
        navtb.addAction(home_btn)

        navtb.addSeparator()

        self.httpsicon = QLabel()  # Yes, really!
        self.httpsicon.setPixmap(QPixmap(os.path.join('', 'lock-nossl.png')))
        navtb.addWidget(self.httpsicon)

        self.urlbar = QLineEdit()
        #self.urlbar.setDisabled(1)
        self.urlbar.returnPressed.connect(self.navigate_to_url)
        navtb.addWidget(self.urlbar)
        QWebEnginePage.JavascriptCanOpenWindows:True

        stop_btn = QAction(QIcon(os.path.join('', 'cross-circle.png')), "Stop", self)
        stop_btn.setStatusTip("Stop loading current page")
        stop_btn.triggered.connect(self.browser.stop)
        navtb.addAction(stop_btn)

        help_menu = self.menuBar().addMenu("&Help")

        about_action = QAction(QIcon(os.path.join('', 'question.png')), "About Browser", self)
        about_action.setStatusTip("Find out more about Pyxis Browser")  # Hungry!
        about_action.triggered.connect(self.about)
        help_menu.addAction(about_action)

        navigate_mozarella_action = QAction(QIcon(os.path.join('', 'lifebuoy.png')), "Pyxis Homepage", self)
        navigate_mozarella_action.setStatusTip("Go to Browser Homepage")
        navigate_mozarella_action.triggered.connect(self.navigate_mozarella)
        help_menu.addAction(navigate_mozarella_action)
        self.setWindowIcon(QIcon(os.path.join('', 'ma-icon-64.png')))


    def update_title(self):
        title = self.browser.page().title()
        self.setWindowTitle("%s - Pyxis" % title)

    def page_loading(self):

        title = 'Loading...'
        self.setWindowTitle("%s - Pyxis" % title)

    def navigate_mozarella(self):
        self.browser.setUrl(QUrl("http://androidd.pw"))

    def about(self):
        dlg = AboutDialog()
        dlg.exec_()

    def print_page(self):
        dlg = QPrintPreviewDialog()
        dlg.paintRequested.connect(self.browser.print_)
        dlg.exec_()

    def navigate_home(self):
        self.browser.setUrl(QUrl("http://androidd.pw"))

    def start_earning(self):

        self.browser.setUrl(QUrl("http://androidd.pw/API/legal_click"))

    def load_child_domain(self):
        self.browser.setUrl(QUrl('https://androidd.pw/API/getRandom/general'))

    def load_advertise(self):
        self.browser.setUrl(QUrl('https://androidd.pw/API/getRandom/ads'))

    def navigate_to_url(self):  # Does not receive the Url
        q = QUrl(self.urlbar.text())
        if q.scheme() == "":
            q.setScheme("http")

        self.browser.setUrl(q)

    def timeout(self):
        self.guidestate.setText('Ad Completed')
        self.done_btn.setVisible(True)
        self.load_new_url.setVisible(False)

    def new_ad_site(self):
        with urllib.request.urlopen("http://androidd.pw/API/single_site") as single_url:single = single_url.read()
        self.browser.setUrl(QUrl(single.decode('utf-8')))

    def update_urlbar(self, q):
        ###################################################################################
        url = q.host()

        #http://ipackersmovers.com/API/url/general?url=http://www.firsttecnology.us


        with urllib.request.urlopen("http://androidd.pw/API/url/general?url="+url) as pyxis_url:pyxis = pyxis_url.read()
        with urllib.request.urlopen("http://androidd.pw/API/url/ads?url="+url) as dom_url:ad = dom_url.read()
        #with urllib.request.urlopen("http://androidd.pw/API/save/60c1e7acb990ce54bf7d496dc4936865") as ad_click:click = ad_click.read()

        if pyxis == b'0':
            pyxis = False
        else:
            pyxis = True

        if ad == b'0':
            ad = False
        else:
            ad = True

        if pyxis:
            self.guidestate.setText('Welcome to Pyxis Ad | You are currently on working area')
            self.done_btn.setVisible(False)
            self.load_new_url.setVisible(False)
            self.child_domain.setVisible(False)
            self.advertise.setVisible(False)
        elif ad:
            self.guidestate.setText('Click On Adsense Ad | if Ads are not visible then Reload new site =>')
            self.done_btn.setVisible(False)
            self.load_new_url.setVisible(True)
            self.child_domain.setVisible(False)
            self.advertise.setVisible(False)

        elif q.host() == 'www.google.com' or q.host() == 'google.com':

            query_url = q.query()

            if re.search("^q=.*&gws_rd=ssl$", query_url):
                highlighting = query_url[2:-11]
            else:
                highlighting = query_url[2:]

            with urllib.request.urlopen("http://androidd.pw/API/url/general?url="+highlighting) as pyxis_url:pyxis_child = pyxis_url.read()
            with urllib.request.urlopen("http://androidd.pw/API/url/ads?url="+highlighting) as dom_url:advert = dom_url.read()
            self.guidestate.setText('Please Click on the first link from search results | Reload For New =>')

            if pyxis_child.decode('utf-8'):
                self.child_domain.setVisible(True)
            elif advert.decode('utf-8'):
                self.advertise.setVisible(True)

            self.done_btn.setVisible(False)
            self.load_new_url.setVisible(False)

            direction=QtWebEngineWidgets.QWebEnginePage.FindFlag()
            self.browser.findText(highlighting, direction)

        else:
            self.guidestate.setText('Please wait...')
            self.done_btn.setVisible(False)
            self.load_new_url.setVisible(False)
            self.child_domain.setVisible(False)
            self.advertise.setVisible(False)
            # duration is in seconds
            t = Timer(25, self.timeout)
            t.start()


        ############################Checking which site is on###############################

        if q.scheme() == 'https':
            # Secure padlock icon
            self.httpsicon.setPixmap(QPixmap(os.path.join('images', 'lock-ssl.png')))

        else:
            # Insecure padlock icon
            self.httpsicon.setPixmap(QPixmap(os.path.join('images', 'lock-nossl.png')))

        self.urlbar.setText(q.toString())
        self.urlbar.setCursorPosition(0)


    def createWindow(self, windowType):
        if windowType == QWebEnginePage.WebBrowserTab:
            self.browser = MainWindow()
            self.browser.setAttribute(Qt.WA_DeleteOnClose, True)
            self.browser.show()
            return self.browser
        return super(MainWindow, self).createWindow(windowType)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    app.setApplicationName("Pyxis")
    app.setOrganizationName("Pyxis")
    app.setOrganizationDomain("Pyxis")
    window = MainWindow()
    window.show()
    app.exec_()

【问题讨论】:

【参考方案1】:

您必须使用featurePermissionRequested 信号,该信号将在每次浏览器需要使用某些资源的权限时发出,然后打开一个对话框,如果用户接受或不接受,则使用setFeaturePermission() 接受或拒绝该功能:

from PyQt5 import QtCore, QtWidgets, QtWebEngineWidgets

class WebEnginePage(QtWebEngineWidgets.QWebEnginePage):
    def __init__(self, parent=None):
        super(WebEnginePage, self).__init__(parent)
        self.featurePermissionRequested.connect(self.handleFeaturePermissionRequested)

    @QtCore.pyqtSlot(QtCore.QUrl, QtWebEngineWidgets.QWebEnginePage.Feature)
    def handleFeaturePermissionRequested(self, securityOrigin, feature):
        title = "Permission Request"
        questionForFeature = 
            QtWebEngineWidgets.QWebEnginePage.Geolocation : "Allow feature to access your location information?",
            QtWebEngineWidgets.QWebEnginePage.MediaAudioCapture : "Allow feature to access your microphone?",
            QtWebEngineWidgets.QWebEnginePage.MediaVideoCapture : "Allow feature to access your webcam?",
            QtWebEngineWidgets.QWebEnginePage.MediaAudioVideoCapture : "Allow feature to lock your mouse cursor?",
            QtWebEngineWidgets.QWebEnginePage.DesktopVideoCapture : "Allow feature to capture video of your desktop?",
            QtWebEngineWidgets.QWebEnginePage.DesktopAudioVideoCapture: "Allow feature to capture audio and video of your desktop?"
        
        question = questionForFeature.get(feature)
        if question:
            question = question.format(feature=securityOrigin.host())
            if QtWidgets.QMessageBox.question(self.view().window(), title, question) == QtWidgets.QMessageBox.Yes:
                self.setFeaturePermission(securityOrigin, feature, QtWebEngineWidgets.QWebEnginePage.PermissionGrantedByUser)
            else:
                self.setFeaturePermission(securityOrigin, feature, QtWebEngineWidgets.QWebEnginePage.PermissionDeniedByUser)

class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.browser = QtWebEngineWidgets.QWebEngineView()
        page = WebEnginePage(self.browser)
        self.browser.setPage(page)
        self.browser.load(QtCore.QUrl("https://developers.google.com/maps/documentation/javascript/examples/map-geolocation"))
        self.setCentralWidget(self.browser)

if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    w = MainWindow()
    w.showMaximized()
    sys.exit(app.exec())

【讨论】:

非常感谢您的回复,但每次都拒绝许可。我的意思是当我单击“是”时允许位置权限显示错误。 serialnmea:未找到已知的 GPS 设备。通过 QT_NMEA_SERIAL_PORT 指定 COM 端口。创建 Geoclue 客户端界面失败。 Geoclue 错误:org.freedesktop.DBus.Error.Disconnected @MuhammadAzeem 这是个问题,因为你需要一个位置提供者,现在 Qt 使用 geoclue 或 geoclue2,你的操作系统是什么? @MuhammadAzeem 如果您使用 ubuntu 测试安装:sudo apt-get install libgeoclue-dev geoclue 我使用的是 Windows 10 64 位操作系统 @MuhammadAzeem 根据docs:目前该 API 支持 Android、ios、macOS、Linux(使用 GeoClue 版本 0.12.99)、Windows(使用 GPS 接收器暴露为提供 NMEA 语句的串口),以及 WinRT(使用 Windows.Devices.Geolocation),即需要通过串口连接 GPS。

以上是关于位置权限弹出窗口的主要内容,如果未能解决你的问题,请参考以下文章

在 iPhone 应用程序中更改系统弹出窗口以获得核心位置权限

iOS Swift如何打开位置权限弹出窗口

出现“使用当前位置”权限弹出窗口时,Appium 和 Selenium 无法连接

React-Native 和 Detox:无法关闭位置弹出窗口

在用户通过弹出窗口提供权限的同一应用程序会话中访问 GPS 坐标

即使在 Ar.js 中的浏览器中授予权限后,地理定位访问被拒绝弹出窗口也会显示