תהליך העבודה ב-WebView

תאריך פרסום: 28 בפברואר 2014

אחד מהיתרונות הגדולים של פיתוח אינטרנט הוא מגוון הכלים העצום שאפשר להשתמש בהם כדי לשפר את תהליך העבודה.

דוגמה לאחד הכלים האלה היא Grunt, מפעיל משימות של JavaScript שמאפשר להגדיר משימות לביצוע באפליקציית האינטרנט, החל מהדרמה של Sass והפעלת שרת פעיל ועד לדחיסת תמונות, למינימיזציה של JavaScript ולהרצת JSHint לפני יצירת גרסה מוכנה לייצור.

Yeoman הוא כלי שעוזר ליצור אפליקציות אינטרנט, ליצור קוד סטנדרטי, להוסיף ספריות מ-Bower ומ-npm וליצור קובץ Grunt עם משימות מוגדרות מראש.

במדריך הזה תלמדו איך להשתמש ב-Yeoman כדי ליצור אפליקציית אינטרנט בסיסית חדשה, ואז לשלב את מערכת ה-build של Android Studio‏ (Gradle) עם Grunt כדי ליצור את אפליקציית האינטרנט. בנוסף, תגדירו משימות Grunt להפעלת שרת מקומי לטעינה מחדש בזמן אמת כדי לבדוק את האפליקציה בדפדפן, כך שלא תצטרכו לרענן את הדף באופן ידני בכל פעם שתשנו קובץ HTML, ‏ CSS או JavaScript.

דרישות מוקדמות

לפני שמתחילים, צריך להתקין כמה תנאים מוקדמים:

  1. התקנת Yeoman: https://github.com/yeoman/yeoman/wiki/Getting-Started
  2. מתקינים את Android Studio: https://developer.android.com/sdk/installing/studio.html

שלב 1. יצירת פרויקט חדש ב-Android Studio עם WebView

הוראות מפורטות לביצוע הפעולה הזו מפורטות במדריך לתחילת השימוש.

שלב 2. יוצרים ספריית משנה לתוכן של אפליקציית האינטרנט

אחרי שיוצרים את הפרויקט, יוצרים ספרייה חדשה ברמה העליונה. ב-Android Studio, לוחצים לחיצה ימנית על תיקיית הפרויקט ובוחרים באפשרות New (חדש) > Directory (ספרייה).

נותנים לספרייה את השם webapp.

שלב 3. יצירת פרויקט Yeoman בספרייה החדשה

בטרמינל cd לספרייה webapp בפרויקט.

cd <path-to-project>/webapp/

לאחר מכן יוצרים אפליקציית אינטרנט חדשה באמצעות Yeoman:

yo webapp

פועלים לפי ההוראות במסך כדי לבחור את אפשרויות הפרויקט. יכול להיות שתצטרכו להריץ את הפקודה sudo npm install, בהתאם לאופן שבו npm מותקן במחשב.

לפני שממשיכים לשלב הבא, בודקים את האפליקציה על ידי הפעלת הפקודה הבאה:

grunt server

אמורה להיפתח כרטיסייה חדשה בדפדפן, שתתחבר לשרת מקומי שהופעל על ידי Grunt. אם משנים אחד מקובצי ה-HTML, ה-CSS או ה-JavaScript בפרויקט, הדף נטען מחדש ומעודכן באופן אוטומטי.

אם מריצים את grunt build, נוצרת ספרייה חדשה, dist, ובתוכה האפליקציה הופכת לדחוסה, מבוצעת אופטימיזציה לה והיא הופכת לגרסה מוכנה לייצור.

שלב 4. הגדרת ה-build ב-Gradle

יוצרים קובץ חדש בשם build.gradle בספרייה webapp.

בקובץ 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'

שלב 5. פיתוח אפליקציית האינטרנט בזמן פיתוח אפליקציית Android

מפעילים את אפליקציית האינטרנט ל-build ומעתיקים את האפליקציה לספרייה 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
}

המשימה הזו מציינת את יחסי התלות של כל גרסאות ה-build של הפרויקט, לכל גרסה של האפליקציה. כאן היא מגדירה יחסי תלות בין המשימות assemble להרצת copyWebApplication.

המשימות של assemble צוברות את הפלט של הפרויקט, לכן קודם צריך להעתיק את אפליקציית האינטרנט לפרויקט Android.

שלב 6. מוודאים שהכול עובד

ב-Android Studio, לא אמורה להיות ספריית assets בתיקייה src של האפליקציות ל-Android.

מגדירים את WebView כך שישתמש בדף index.html:

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

לוחצים על Run וממתינים שהאפליקציה תיבנה. בתיקיית המשנה www אמורה להופיע תיקיית assets עם אפליקציית האינטרנט.

שלב 7. יצירת שרת פעיל וטעינה מחדש בזמן אמת

טעינה מחדש בזמן אמת יכולה להיות שימושית מאוד לביצוע שינויים מהירים באפליקציות האינטרנט. כדי לעשות זאת, אפשר ליצור שתי גרסאות של האפליקציה: גרסה פעילה בשרת וגרסה סטטית שבה תוכן האינטרנט ארוז באפליקציה ל-Android.

בקטע build.gradle של אפליקציית Android, מוסיפים את השורות הבאות בסוף הרכיב android:

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

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

}

עכשיו אפשר ליצור ב-Gradle גרסה של האפליקציה עם שם חבילה של שרת פעיל, וגרסה עם שם החבילה הרגיל. כדי לבדוק אם זה עבד, לוחצים על Sync Project with Gradle Files (בסרגל העליון לצד הלחצן Run).

לאחר מכן, בודקים את גרסאות ה-build שנמצאות בפינה הימנית התחתונה של Android Studio. הן מציינות את הגרסאות של האפליקציה שאפשר ליצור.

לכל productFlavor יש גרסאות Debug ו-Release, שהפלאגין של Android ל-Gradle מספק כברירת מחדל. ההגדרה הזו קובעת אם ה-build יהיה build לניפוי באגים או build גרסה זמינה לפריסה ב-Play Store.

עכשיו יש לכם שתי גרסאות, אבל הן עדיין לא עושות שום דבר שונה.

שלב 8. טעינה משרת פעיל

עכשיו מגדירים את האפליקציה כך שתטען כתובת URL שונה בהתאם לסוג המוצר שאתם מפתחים.

באפליקציה ל-Android, הקבצים המשותפים לכל גרסאות המוצר נמצאים בתיקייה src/main. כדי להוסיף קוד או משאבים ספציפיים למאפיין אחד של המוצר, יוצרים ספרייה נוספת ב-src עם אותו שם כמו productFlavor. כשמפעילים build לגרסה הזו, 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>
    

    הפעולה הזו מוסיפה את הרשאת האינטרנט לגרסאות ה-build של 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 Studio, באפשרות Build Variant, בוחרים באפשרות LiveserverDebug. לוחצים על Run.

    אמורה להיות לכם אפשרות לערוך את התוכן ב-HTML, ב-CSS וב-JavaScript ולראות את השינויים בדפדפן באופן מיידי.

עכשיו יש לכם שתי גרסאות של האפליקציה: גרסה לפיתוח עם טעינת נתונים מחדש בזמן אמת משרת Grunt, וגרסה סטטית, שמארזת באופן מקומי באפליקציית Android.