سير عمل WebView

تاريخ النشر: 28 شباط (فبراير) 2014

من المزايا الرائعة لتطوير الويب هي المجموعة الغنية من الأدوات التي يمكنك استخدامها لتحسين سير العمل.

ومن الأمثلة على هذه الأدوات Grunt، وهو أداة لتشغيل مهام JavaScript تتيح لك تحديد المهام التي تريد تنفيذها على تطبيق الويب، بدءًا من تجميع Sass و بدء خادم علني ووصولاً إلى ضغط الصور وتصغير JavaScript وتشغيل JSHint قبل إنشاء إصدار جاهز للنشر.

Yeoman هي أداة تساعد في إنشاء تطبيقات الويب، وإنشاء ملف بدء برمجي، واستيراد المكتبات من Bower وnpm، وإنشاء ملف برمجي Grunt يتضمّن مهام محدّدة مسبقًا.

في هذا الدليل التعليمي، ستستخدم Yeoman لإنشاء تطبيق ويب أساسي جديد، ثم دمج نظام إنشاء "استوديو Android" (Gradle) مع Grunt لإنشاء تطبيق الويب. ستحتاج أيضًا إلى إعداد مهام Grunt لتشغيل خادم محلي لإعادة التحميل المباشر لاختبار تطبيقك في المتصفّح، حتى لا تحتاج إلى إعادة تحميل الصفحة يدويًا في كل مرة تُجري فيها تغييرًا على ملف HTML أو CSS أو JavaScript.

المتطلبات الأساسية

قبل البدء، عليك تثبيت بعض المتطلبات الأساسية:

  1. تثبيت Yeoman: https://github.com/yeoman/yeoman/wiki/Getting-Started
  2. تثبيت "استوديو Android": https://developer.android.com/sdk/installing/studio.html

الخطوة 1: إنشاء مشروع جديد في "استوديو Android" باستخدام WebView

يمكنك الاطّلاع على تعليمات كاملة حول كيفية إجراء ذلك في دليل البدء.

الخطوة 2: أنشئ دليلاً فرعيًا لمحتوى تطبيق الويب.

بعد إنشاء مشروعك، أنشئ دليلاً جديدًا من المستوى الأعلى. في IDE Android Studio، انقر بزر الماوس الأيمن على مجلد المشروع واختَر جديد > دليل.

أدخِل اسمًا للدليل webapp.

الخطوة 3: أنشئ مشروع Yeoman في الدليل الجديد.

في وحدة تحكّم طرفية، انتقِل إلى الدليل webapp في المشروع باستخدام الأمر cd.

cd <path-to-project>/webapp/

بعد ذلك، أنشئ تطبيق ويب جديدًا باستخدام Yeoman:

yo webapp

اتّبِع التعليمات الظاهرة على الشاشة لاختيار خيارات المشروع. قد تحتاج إلى تشغيل sudo npm install، استنادًا إلى كيفية تثبيت npm على جهازك.

قبل المتابعة إلى الخطوة التالية، اختبِر التطبيق من خلال تنفيذ الأمر التالي:

grunt server

من المفترض أن تفتح علامة تبويب جديدة في المتصفّح، مع الاتصال بخادم محلي بدأه Grunt. في حال تغيير أحد ملفات HTML أو CSS أو JavaScript في المشروع، تتم إعادة تحميل الصفحة وتعديلها تلقائيًا.

في حال تشغيل grunt build، يتم إنشاء دليل جديد باسم dist ويتم ضغط تطبيق الويب وتحسينه وتحويله إلى إصدار جاهز للنشر داخل هذا المجلد.

الخطوة 4. ضبط عملية إنشاء Gradle

في الدليل webapp، أنشئ ملفًا جديدًا باسم build.gradle.

في ملف build.gradle الجديد، أضِف ما يلي:

import org.apache.tools.ant.taskdefs.condition.Os

task buildWebApp(type: Exec) {
  executable = Os.isFamily(Os.FAMILY_WINDOWS) ? "grunt.cmd" : "grunt"
  args = ["build"]
}

يؤدي ذلك إلى إنشاء مهمة جديدة باسم buildWebApp بنوع محدّد مسبقًا Exec. بعد ذلك، اضبط المتغيّر executable في Exec على الأمر grunt ذي الصلة استنادًا إلى نظام التشغيل الحالي. تم ضبط args على "build"، ما يعادل grunt build يتم تشغيله على سطر الأوامر. أخيرًا، الاستيراد في أعلى الصفحة هو للاستفادة من Os.isFamily(Os.FAMILY_WINDOWS).

قبل أن نتمكّن من استخدام هذه المهمة الجديدة، علينا إبلاغ المشروع بملف build.gradle الجديد.

افتح settings.gradle في الدليل الجذر وأضِف السطر التالي:

include ':webapp'

الخطوة الخامسة. إنشاء تطبيق الويب عند إنشاء تطبيق Android

احصل على تطبيق الويب لإنشاء التطبيق، ثم انسخ التطبيق إلى الدليل assets في تطبيق Android.

انسخ ما يلي في ملف build.gradle لتطبيقات Android:

task copyWebApplication(type: Copy) {
  from '../webapp/dist'
  into 'src/main/assets/www'
}

task deleteWebApplication(type: Delete) {
  delete 'src/main/assets/www'
}

copyWebApplication.dependsOn ':webapp:buildWebApp'
copyWebApplication.dependsOn deleteWebApplication

android.applicationVariants.all { variant ->
  tasks.getByPath(":${project.name}:assemble${variant.buildType.name.capitalize()}").dependsOn copyWebApplication
}

لنطّلِع على كل جزء من هذه العملية.

task copyWebApplication

task copyWebApplication(type: Copy) {
  from '../webapp/dist'
  into 'src/main/assets/www'
}

تنسخ مهمة Copy هذه تطبيقك من دليل webapp/dist. نريد نسخ الملفات إلى src/main/assets/www. تنشئ هذه المهمة أيضًا بنية الملفات اللازمة في حال عدم توفّر أي من الدلائل المطلوبة.

task deleteWebApplication

task deleteWebApplication(type: Delete) {
  delete 'src/main/assets/www'
}

تؤدي مهمة الحذف هذه إلى حذف جميع الملفات في دليل assets/www.

copyWebApplication.dependsOn

copyWebApplication.dependsOn ':webapp:buildWebApp'
copyWebApplication.dependsOn deleteWebApplication

يشير السطر الأول من هذا إلى أنّ copyWebApplication يعتمد على مهمة buildWebApp من ملف build.gradle في تطبيق الويب.

يشير السطر الثاني إلى أنّ هناك تبعية على مهمة deleteWebApplication.

بعبارة أخرى، قبل نسخ أي ملفات إلى الدليل assets، علينا التأكّد من إنشاء تطبيق الويب وحذف المحتوى الحالي في الدليل assets.

android.applicationVariants.all

android.applicationVariants.all { variant ->
  tasks.getByPath(":${project.name}:assemble${variant.buildType.name.capitalize()}").dependsOn copyWebApplication
}

تحدِّد هذه المهمة التبعيات لجميع إصدارات مشروعك، ولكل إصدار من تطبيقك. وتضبط هنا تبعية على مهام assemble لتشغيل copyWebApplication.

تجمع مهام assemble نتائج المشروع، لذا يجب نسخ تطبيق الويب إلى مشروع Android أولاً.

الخطوة السادسة. التأكّد من أنّ كل شيء يعمل على ما يرام

في Android Studio، يجب ألا يتوفّر لديك دليل assets في مجلّد src تطبيقات Android.

اضبط WebView لاستخدام صفحة index.html:

mWebView.loadUrl("file:///android_asset/www/index.html");

انقر على تشغيل واترك تطبيقك يتم إنشاؤه. من المفترض أن يظهر لك assets دليل يتضمّن تطبيق الويب الخاص بك في الدليل الفرعي www.

الخطوة السابعة: إنشاء خادم مباشر وإعادة تحميل مباشرة

يمكن أن يكون إعادة التحميل المباشر مفيدًا جدًا لإجراء تغييرات سريعة على تطبيقات الويب. لتفعيل هذه الميزة، يمكنك إنشاء "نُسخة منتج" اثنَين لتطبيقك: إصدار خادم علني وإصدار ثابت يتم فيه تجميع محتوى الويب في تطبيق Android.

في ملف build.gradle الخاص بتطبيق Android، أضِف الأسطر التالية في نهاية عنصر android:

android {
  ...
  defaultConfig {
    ...
  }
  productFlavors {
    staticbuild {
      packageName "com.google.chrome.myapplication"
    }

    liveserver {
      packageName "com.google.chrome.myapplication.liveserver"
    }
  }

}

يتيح لك Gradle الآن إنشاء إصدار من تطبيقك باستخدام اسم حزمة liveserver وإصدار آخر باستخدام اسم الحزمة العادي. للتحقّق مما إذا كان الإجراء قد أدّى إلى حلّ المشكلة، انقر على مزامنة المشروع مع ملفات Gradle (في الشريط العلوي بجانب الزر تشغيل).

بعد ذلك، اطّلِع على أنواع الإصدارات في أسفل يمين "استوديو Android"، والتي تعرض لك بشكل أساسي إصدارات تطبيقك التي يمكنك إنشاؤها.

لكل productFlavor، يتوفّر إصداران Debug وRelease، يقدّمهما المكوّن الإضافي لنظام Gradle المتوافق مع Android تلقائيًا. يحدِّد هذا الخيار ما إذا كان يجب أن يكون الإصدار قيد الإنشاء إصدارًا لتصحيح الأخطاء أو إصدارًا مناسبًا للنشر على "متجر Google Play".

لديك الآن نسختان، ولكنهما لا تؤديان إلى أيّ تغيير حتى الآن.

الخطوة 8: التحميل من خادم مباشر

الآن، عليك ضبط تطبيقك لتحميل عنوان URL مختلف استنادًا إلى ملف علامة ملف تعريف الارتباط الذي تُنشئه.

في تطبيق Android، تكون الملفات الشائعة لجميع أنواع المنتجات في ملف ‎ src/main. لإضافة رمز أو موارد خاصة بنكهة منتج معيّنة، أنشئ دليلاً آخر ضمن src بالاسم نفسه المستخدَم في productFlavor. عند إنشاء إصدار مخصّص لهذا الصيغة، يدمج Gradle والمكوّن الإضافي لنظام Android هذين الملفَّين الإضافيَّين بالإضافة إلى الملفات في src/main.

حدِّد عنوان URL كمصدر سلسلة، واستخدِم هذا المرجع في الرمز بدلاً من عنوان URL مضمّن في الرمز.

  1. أنشئ المجلدَين src/liveserver وsrc/staticbuild.

  2. في مجلد liveserver، أنشئ مجلدًا جديدًا باسم res يتضمّن مجلدًا فرعيًا باسم values. أنشئ ملفًا باسم config.xml داخل هذا المجلد. كرِّر هذه الخطوات لتطبيقها على المجلد staticbuild.

  3. داخل ملفات الإعداد، أضِف الأسطر التالية إلىملف src/liveserver/res/values/config.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
      <string name="init_url">https://<Your Local Machine IP Address>:9000</string>
    </resources>
    

    أضِف القسم التالي إلى src/staticbuild/res/values/config.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
      <string name="init_url">file:///android_asset/www/index.html</string>
    </resources>
    
  4. اضبط WebView لاستخدام init_url من ملفات الإعدادات هذه.

    mWebView.loadUrl(getString(R.string.init_url));
    
  5. أنشئ ملفًا جديدًا باسم AndroidManifest.xml في liveserver/AndroidManifest.xml وأضِف السطور التالية:

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="https://schemas.android.com/apk/res/android">
      <uses-permission android:name="android.permission.INTERNET" />
    </manifest>
    

    يؤدي ذلك إلى إضافة إذن الوصول إلى الإنترنت لإصدارات liveserver.

  6. في webapp/Gruntfile.js، ابحث عن:

    connect: {
      options: {
        port: 9000,
        livereload: 35729,
        // change this to '0.0.0.0' to access the server from outside
        hostname: **'localhost'**
      },
      ...
    }
    

    استبدِل localhost بـ 0.0.0.0 حتى تتمكّن من الوصول إلى الخادم المحلي من الشبكة المحلية:

    connect: {
      options: {
        port: 9000,
        livereload: 35729,
        // change this to '0.0.0.0' to access the server from outside
        hostname: '**0.0.0.0'**
      },
      ...
    }
    

لاختبار التغييرات، اتّبِع الخطوات التالية:

  1. ابدأ الخادم المباشر:

    grunt server
    
  2. في "استوديو Android"، اختَر LiveserverDebug من خيارات نوع الإصدار. بعد ذلك، انقر على تشغيل.

    من المفترض أن تتمكّن من تعديل محتوى HTML وCSS وJavaScript وأن ترى التغييرات على الفور في المتصفّح.

لديك الآن إصداران من تطبيقك: إصدار تطويري يتضمّن إعادة تحميل مباشرةً من خادم Grunt وإصدار ثابت تم حزمه محليًا في تطبيق Android.