Добавить PWA на главный экран не работает на chrome мобильных - PullRequest
1 голос
/ 30 мая 2020

Недавно я занялся разработкой внешнего интерфейса, чтобы создать интерфейс для сервера nodejs, размещенного на Raspberry Pi. Я слышал о прогрессивном веб-приложении и хотел, чтобы пользователь мог установить его на свой телефон. Итак, вот манифест и скрипт сервис-воркера. Манифест:

{
  "name": "Philips D6330",
  "short_name": "Philips D6330",
  "description": "A control app for the Philips D6330",
  "icons": [
    {
      "src": "https://192.168.1.26/cdn/favicon.png",
      "sizes": "512x512",
      "type": "image/png"
    }
  ],
  "start_url": "https://192.168.1.26",
  "display": "fullscreen",
  "orientation": "portrait",
  "theme_color": "#333333",
  "background_color": "#333333",
  "scope": "/"
}

Service Worker:

const CACHE_NAME = 'cache';
const CACHE = [
  '/',
  '/cdn/offline.html',
  '/cdn/style.css',
  '/cdn/favicon.png',
  '/cdn/linetoB.ttf',
  '/cdn/linetoL.ttf',
  '/cdn/neon.ttf',
  '/cdn/not.png',
  '/cdn/next.png',
  '/cdn/pause.png',
  '/cdn/play.png',
  '/cdn/previous.png',
  '/cdn/dots.png',
  '/cdn/rfid.png'
];

self.addEventListener('install', function(event) {
  event.waitUntil(
    caches.open(CACHE_NAME)
      .then(function(cache) {
        return cache.addAll(CACHE)
      })
      .then(self.skipWaiting())
  )
})

self.addEventListener('fetch', function(event) {
  if (event.request.mode === 'navigate') {
    event.respondWith(
      fetch(event.request)
      .catch(() => {
          return caches.open(CACHE_NAME)
          .then((cache) => {
              return cache.match('/cdn/offline.html');
          })
      })
    );
  }
  else {
    event.respondWith(
      fetch(event.request)
      .catch(() => {
        return caches.open(CACHE_NAME)
        .then((cache) => {
            return cache.match(event.request)
        })
      })
    );
  }
})

self.addEventListener('activate', function(event) {
  event.waitUntil(
    caches.keys()
      .then((keyList) => {
        return Promise.all(keyList.map((key) => {
          if (key !== CACHE_NAME) {
            console.log('[ServiceWorker] Removing old cache', key)
            return caches.delete(key)
          }
        }))
      })
      .then(() => self.clients.claim())
  )
})

Я думаю, также уместно сказать вам, что все это происходит в моей локальной сети, поэтому мой сервер узла использует https с самоподписанным сертификат, созданный с помощью этого руководства: https://medium.com/@tbusser / create-a-browser-trusted-self-signed-ssl-certificate-2709ce43fd15 Но даже несмотря на то, что это самозаверяющий сертификат, сервисный работник, похоже, хорошо регистрируется на firefox и chrome, поскольку он хранит файлы и отображает автономную страницу в автономном режиме.

Вот моя проблема: когда я хочу установить его из настольной версии chrome Я могу, но не могу chrome мобильный (или samsung inte rnet) ... вот фрагмент кода, который я использую для его установки:

<script  defer>
    window.addEventListener('beforeinstallprompt', (event) => {
      console.log('?', 'beforeinstallprompt', event);
      // Stash the event so it can be triggered later.
      window.deferredPrompt = event;
    });

    butInstall.addEventListener('click', () => {
      console.log('?', 'butInstall-clicked');
      const promptEvent = window.deferredPrompt;
      if (!promptEvent) {
        // The deferred prompt isn't available.
        return;
      }
      // Show the install prompt.
      promptEvent.prompt();
      // Log the result
      promptEvent.userChoice.then((result) => {
        console.log('?', 'userChoice', result);
        // Reset the deferred prompt variable, since
        // prompt() can only be called once.
        window.deferredPrompt = null;
      });
    });

    window.addEventListener('appinstalled', (event) => {
      console.log('?', 'appinstalled', event);
    });

  </script>

Отсюда https://web.dev/codelab-make-installable/

Вот скриншот события перед установкой с отчетом о маяке, если это может помочь (кстати, знак плюса в URL-адресе показывает, что он работает): console информация журнала

Но на мобильном телефоне плюс знак не отображается и ничего не происходит, когда я нажимаю кнопку ... И поскольку у меня нет доступа к консоли, я не вижу никаких ошибок ...

------ Изменить ------

После использования предупреждения для записи в журнал того, что говорит консоль, я думаю, что проблема исходит из-за того, что сервисный работник хорошо регистрируется, потому что я получаю следующее: «Ошибка регистрации ServiceWorker: SecurityError: Failed to register ServiceWorker для области ('https://192.168.1.26/') со сценарием ('https://192.168.1.26/sw.js'): при получении сценария произошла ошибка сертификата SSL. ".

Есть ли способ заставить браузер доверять моему самостоятельно подписанному сертификату?

Любая помощь, предложение или комментарий приветствуются ^^

1 Ответ

0 голосов
/ 19 июня 2020

Это .webmanifest, и вы не соответствуете критериям. Вам нужен значок 512x512 И 192x192.

В качестве start_url я бы просто использовал /?source=pwa

  "icons": [
    {
      "src": "icon.png",
      "type": "image/png",
      "sizes": "192x192"
    },
    {
      "src": "big_icon.png",
      "type": "image/png",
      "sizes": "512x512"
    }
  ],
  "start_url": "/?source=pwa",

После этого вам нужно связать свой веб-манифест с <link>

<link rel="manifest" href="/manifest.webmanifest">

Проверить, все ли пути верны.

Вот моя собственная маленькая «библиотека» для абстрактных вещей: https://github.com/ilijanovic/serviceHelper (пока что в разработке)

Если вы соответствуете всем критериям, вы можете сделать свое приложение устанавливаемым

Вот как оно работает с моей библиотекой. Вы создаете экземпляр класса и передаете путь работнику службы.

var sh = new ServiceHelper("./sw.js");

sh.init().then(response => {
   console.log("Initialized");
})

sh.on("notinstalled", (e) => {

   console.log("App is not installed");

   //do some stuff. For example enable some button
   //button.classList.remove("disabled");

})
butInstall.addEventListener('click', () => {
   sh.installApp().then(e => {
      // e = user choice event
      console.log(e);
   }).catch(err => {
      // error if the app is already installed
      console.log(err);
   })
...