کانال بله, جهت پشتیبانی و اطلاع رسانی کانال بله, جهت پشتیبانی و اطلاع رسانی
عضویت

طراحی widget در android

کلیه حقوق مادی و معنوی این مقاله متعلق به آموزشگاه تحلیل داده می باشد و هر گونه استفاده غیر قانونی از آن پیگرد قانونی دارد .

طراحی widget در android , طراحی ابزارک در android

در این مبحث به شما نحوه ی ایجاد ابزارک (widget) های اندروید را آموزش می دهیم .

فهرست محتوا

1. ابزارک های اندروید

·         مقدمه ای بر ابزارک های اندروید

·         مراحل ایجاد ابزارک های اندروید

·         توضیحاتی درباره ی اندازه ی ابزارک ها

2. ایجاد Broadcast receiver ویژه ی ابزارک مورد نظر

·         فرایند ایجاد و پیکربندی ابزارک

·         View ها و layout های موجود

·         کلاس AppWidgetProvider

·         Receiver و پردازش ناهمگام

3. بروز رسانی ابزارک ها

4. تمرین : بروز رسانی ابزارک ها در فواصل معین

·         آنچه در این تمرین انجام خواهید داد

·         ایجاد پروژه و پیاده سازی ابزارک

·         راه اندازی و تست برنامه

5. Collection view widgets

6. فعال سازی یک ابزارک برای Lock Screen

7. تمرین : بروز رسانی ابزارک از طریق service

1. ابزارک های اندروید

مقدمه ای بر ابزارک های اندروید

Widgets در واقع برنامه های کوچکی هستند که روی یک میزبان ابزارک از جمله home screen یا lock screen دستگاه اندروید جای گذاری می شوند.

یک ابزارک به عنوان جزئی از فرایند میزبانش اجرا می شود . این امر ملزم این است که ابزارک مربوطه مجوزهای اپلیکیشن خود را داشته باشد .

ابزارک از RemoteViews جهت ایجاد رابط کاربری استفاده می کنند . RemoteViews می تواند با همان مجوز برنامه ی اصلی توسط پروسه ی دیگری اجرا شود, بدین نحو ابزارک ها قادر خواهند بود با مجوزهای defining app نیز اجرا شوند.

رابط کاربری (برای) Widget توسط broadcast receiver تعریف می شود .  Receiverمذکور طرح بندی (layout) خود را در شئی از نوع RemoteViews بارگذاری (inflate) می کند. این شئ در اختیار سیستم اندروید قرار گرفته و به دنبال آن سیستم اندروید شئ را به برنامه ی صفحه نمایش خانگی (home screen) تحویل می دهد .        

مراحل ایجاد ابزارک های اندروید

به منظور ایجاد یک ابزارک باید مراحل زیر را دنبال کنید :

·         یک فایل طرح بندی (layout) ایجاد کنید

·         یک فایل XML (AppWidgetProviderInfo) ایجاد کنید, این فایل خصوصیات ابزارک را مشخص می کنند برای مثال می توان به اندازه, فواصل ثابت بروز رسانی اشاره کرد

·         یک BroadcastReceiver ایجاد کنید که ویژه ی ساخت و طراحی رابط کاربری مورد استفاده قرار می گیرد

·         پیکربندی Widget را در فایل AndroidManifest.xml تعریف کنید

·         می توانید در صورت تمایل یک configuration activity تعریف کنید که زمانی فراخوانده می شود که یک نمونه از Widget به میزبان (دربردارنده) ابزارک افزوده شود            

 

توضیحاتی درباره ی اندازه ی ابزارک ها

پیش از نسخه ی 3.1 اندروید, ابزارک همیشه تعداد ثابتی سلول را در صفحه ی نمایش خانگی اشغال می کرد . سلول معمولاً برای نمایش آیکون یک اپلیکیشن بکار گرفته می شود . جهت تعریف اندازه و مقیاس بندی ابزارک باید از فرمول ذیل کمک بگیرید : ((Number of columns / rows) * 74) - 2 . این ها در حقیقت پیکسل های مستقل از دستگاه هستند و عدد - 2 نیز به منظور جلوگیری از خطاهایی که در فرایند گرد کردن رخ می دهد در نظر گرفته شده است .

از ویرایش 3.1 به بعد اندروید, این قابلیت برای کاربر بوجود آمده که ابزارک دلخواه را بر اساس نیاز کوچک تر یا بزرگ تر کنند . برای فعال سازی این قابلیت, کافی است برنامه نویس خصیصه ی android:resizeMode="horizontal|vertical" را در فایل پیکربندی XML ویژه ی ابزارک دلخواه بکار ببرد .

2. ایجاد Broadcast receiver ویژه ی ابزارک مورد نظر

فرایند ایجاد و پیکربندی ابزارک

به منظور ثبت (register) یک ابزارک, کافی است یک broadcast receiver بهمراه یک intent-filter ویژه ی عملیات android.appwidget.action.APPWIDGET_UPDATE ایجاد کنید .

<receiver
android:icon=
"@drawable/icon"
       
android:label=
"Example Widget"
       
android:name="MyWidgetProvider"
>
<intent-filter >
<action android:name=
"android.appwidget.action.APPWIDGET_UPDATE"
/>
</intent-filter>

<meta-data
        android:name=
"android.appwidget.provider"
       
android:resource="@xml/widget_info"
/>
</receiver>

می توان به receiver مذکور برچسب و آیکون تخصیص داد . برچسب و آیکون نام برده در فهرست ابزارک های موجود در Android launcher مورد استفاده قرار می گیرند .

همچنین با استفاده از خصیصه ی android:name="android.appwidget.provider, می توانید metadata ی ابزارک را تعریف کنید . فایل پیکربندیی که metadata ی مزبور به آن ارجاع می دهد دربردارنده ی تنظیمات پیکربندی (config settings) ویژه ی آن ابزارک می باشد . از میان این تنظیمات می توان رابط بروز رسانی, اندازه و طرح بندی اولیه ی ابزارک را نام برد .

<?xml version="1.0" encoding="utf-8" ?>

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"

                    android:initiallayout="@layout/widget_layout"

                    android:minheight="72dp"

                    android:minwidth="146dp"

                    android:updateperiodmillis="1800000">

 

</appwidget-provider>

View ها و layout های موجود

یک ابزارک در کلاس های View ای که می تواند بکارببرد, محدود می شود . می توانید به عنوان layout از کلاس های FrameLayout , LinearLayout و RelativeLayout بهره گرفته و به مثابه ی views از AnalogClock, Button , Chromometer, ImageButton, ImageView, ProgressBar و TextView استفاده کنید .

از اندروید 3.0 به بعد تعداد view هایی که در اختیار شما قرار می گیرد افزایش یافته است : GridView , ListView , StackView , ViewFlipper و AdapterViewFlipper از جمله ی آن view ها هستند . توجه داشته باشید که adapter view های نام برده مستلزم ایجاد یک collection view widget می باشند که بعداً به آن خواهیم پرداخت .

تعامل با view های یک ابزارک تنها از طریق رخداد OnClickListener  صورت می گیرد . می توان OnClickListener را روی یک ابزارک رجیستر کرد که بعد توسط کاربر فعال سازی می شود .  

کلاس AppWidgetProvider

پیاده سازی BroadcastReceiver عموماً کلاس AppWidgetProvider را بسط می دهد (به ارث می برد) .

کلاس AppWidgetProvider متد onReceive() را پیاده سازی می کند, اطلاعات لازمه را استخراج کرده و متدهای (برای) چرخه ی حیات (life-cycle method) که در جدول ذیل فهرست شده را صدا می زند .

شما می توانید چندین نمونه از یک ابزارک را به صفحه نمایش خانگی (home screen) ضمیمه کنید . لازم است بیاد داشته باشید که ویژه ی نمونه ی اولی که به صفحه ی خانگی الصاق می شود یا از آن حذف می گردد متد چرخه ی حیات معینی را باید فراخوانی کنید . البته متدهای چرخه ی حیات دیگری هم هستند که برای هر نمونه از ابزارک صدا زده می شوند .  

جدول 1. متدهای چرخه ی حیات

متد

توضیح

onEnabled()

  هنگامی صدا زده می شود که نمونه ی ابزارک برای اولین بار به صفحه نمایش خانگی افزوده می شود .

onDisabled()

 زمانی فراخوانده می شود که اخرین نمونه ی ابزارک از home screen حذف گردد .

onUpdate()

 برای هر مرحله بروز رسانی ابزارک فراخوانده می شود . دربردارنده ی شناسه هایappWidgetIds  است که نیاز به بروز رسانی دارند . توجه داشته باشید که این می تواند تمامی نمونه های     AppWidget  برای این provider  باشد یا زیرمجموعه ای از آن ها . برای مثال, در صورتی که چندین (بیش از یک) ابزارک به صفحه ی خانگی اضافه شود, تنها آخرین ابزارک (تا زمان نصب مجدد) تغییر می یابد .  

onDeleted()

نمونه ی ابزارک از صفحه ی خانگی حذف می گردد .

 

Receiver و پردازش ناهمگام

ابزارک از تمامی محدودیت هایی که یک broadcast receiver معمولی در زمینه ی runtime دارد رنج می برد, به عنوان مثال می توان به این حقیقت اشاره کرد که ابزارک تنها 5 ثانیه زمان برای به اتمام رساندن پردازش خود دارد . بنابراین یک receiver باید عملیات زمان بری را در service پیاده کرده, سپس بروز رسانی ابزارک را از service مربوطه صورت دهد .  

3. بروز رسانی ابزارک ها

ابزارک اطلاعات و داده های خود را طبق جدول زمانی متناوب و طی فواصل معین آپدیت می کند . جمعاً دو روش برای بروز رسانی یک ابزارک وجود دارد که یکی بر اساس فایل پیکربندی XML صورت می گیرد و دیگری بر پایه ی سرویس AlarmManager انجام می شود .

می توانید در فایل پیکربندی ابزارک فاصله ی زمانی بروز رسانی را مدت ثابت و معینی تعیین کنید . سیستم پس از سپری شدن این فاصله ی زمانی تعیین شده بیدار شده و broadcast receiver را برای بروز رسانی ابزارک صدا می زند . کم ترین فاصله ی زمانی بروز رسانی چیزی حدود 1800000 هزارم ثانیه است (حدوداً 30 دقیقه) .

AlarmManager به شما اجازه می دهد از منابع موجود به صورت موثرتر و کارامدتر استفاده کنید, همچنین تعداد دفعات بروز رسانی را بالا ببرید. جهت استفاده از این روش یک سرویس تعریف کرده, سپس سرویس مزبور را از طریق AlarmManager گونه ای برنامه ریزی کنید که به طور منظم آپدیت شود .

توجه داشته باشید که افزایش تعداد دفعات بروز رسانی باعث می شود گوشی از حالت ذخیره ی انرژی خارج گشته و بدنبال آن ابزارک مورد نظر انرژی بیشتری مصرف کند .     

4. تمرین : بروز رسانی ابزارک ها در فواصل معین

آنچه در این تمرین انجام خواهید داد

در تمرین پیش رو به ایجاد یک ابزارک که وظیفه آن نمایش عدد تصادفی است می پردازیم . 

نمایی از Widget نهایی در این آموزش

پروژه ی جدیدی به نام de.vogella.android.widget.example ایجاد کنید . حال activity مورد نیاز را در پکیج de.vogella.android.widget.example خلق کنید .

فایل جدید myshape.xml را در پوشه ی /res/drawable ایجاد کنید . این فایل drawable ای را که به عنوان تصویر پس زمینه در ابزارک بکار گرفته می شود, تعریف می کند .   

<?xml version="1.0" encoding="UTF-8" ?>

<shape xmlns:android="http://schemas.android.com/apk/res/android"

       android:shape="rectangle">

 

    <stroke android:width="2dp"

            android:color="#FFFFFFFF" />

 

    <gradient android:angle="225"

              android:endcolor="#DD2ECCFA"

              android:startcolor="#DD000000" />

 

    <corners android:bottomleftradius="7dp"

             android:bottomrightradius="7dp"

             android:topleftradius="7dp"

             android:toprightradius="7dp" />

 

</shape>

فایل widget_layout.xml زیر را در پوشه ی res/layout تعریف کنید .

<?xml version="1.0" encoding="utf-8" ?>

<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"

              android:id="@+id/layout"

              android:layout_width="match_parent"

              android:layout_height="match_parent"

              android:layout_margin="8dip"

              android:background="@drawable/myshape">

 

    <textview android:id="@+id/update"

              style="@android:style/TextAppearance.Medium"

              android:layout_width="match_parent"

              android:layout_height="match_parent"

              android:layout_gravity="center"

              android:gravity="center_horizontal|center_vertical"

              android:layout_margin="4dip"

              android:text="Static Text">

    </textview>

 

</linearlayout>

 

فراداده ی AppWidgetProvider فایل widget_info.xml را طبق دستور العمل زیر ایجاد کنید :

File New Android Android XML File

ایجاد یک Widget

ایجاد یک Widget

<?xml version="1.0" encoding="utf-8" ?>

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"

                    android:initiallayout="@layout/widget_layout"

                    android:minheight="72dp"

                    android:minwidth="300dp"

                    android:updateperiodmillis="300000">

 

</appwidget-provider>

کلاس receiver class را ایجاد کنید . کلاس مذکور حین بروز رسانی ها فراخوانی می شود .

package de.vogella.android.widget.example;

import
java.util.Random;

import
android.app.PendingIntent;
import
android.appwidget.AppWidgetManager;
import
android.appwidget.AppWidgetProvider;
import
android.content.ComponentName;
import
android.content.Context;
import
android.content.Intent;
import
android.util.Log;
import
android.widget.RemoteViews;

public class MyWidgetProvider extends
AppWidgetProvider {

 
private static final String ACTION_CLICK = "ACTION_CLICK"
;

  @Override
 
public void
onUpdate(Context context, AppWidgetManager appWidgetManager,
                      
int
[] appWidgetIds) {

   
// Get all ids
   
ComponentName thisWidget = new
ComponentName(context,
            MyWidgetProvider.
class
);
   
int
[] allWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget);
   
for (int
widgetId : allWidgetIds) {
     
// create some random data
     
int number = (new Random().nextInt(100
));

      RemoteViews remoteViews =
new
RemoteViews(context.getPackageName(),
              R.layout.widget_layout);
      Log.w(
"WidgetExample"
, String.valueOf(number));
     
// Set the text
     
remoteViews.setTextViewText(R.id.update, String.valueOf(number));

     
// Register an onClickListener
     
Intent intent = new Intent(context, MyWidgetProvider.class
);

      intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
      intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds);

      PendingIntent pendingIntent = PendingIntent.getBroadcast(context,
             
0
, intent, PendingIntent.FLAG_UPDATE_CURRENT);
      remoteViews.setOnClickPendingIntent(R.id.update, pendingIntent);
      appWidgetManager.updateAppWidget(widgetId, remoteViews);
    }
  }
}

AndroidManifest.xml را باز کرده و ابزارک خود را مشابه کد لیست (listing) زیر ثبت کنید .

<?xml version="1.0" encoding="utf-8" ?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android"

          package="de.vogella.android.widget.example"

          android:versioncode="1"

          android:versionname="1.0">

 

    <application android:icon="@drawable/icon"

                 android:label="@string/app_name">

        <receiver android:name="MyWidgetProvider">

            <intent-filter>

                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />

            </intent-filter>

 

            <meta-data android:name="android.appwidget.provider"

                       android:resource="@xml/widget_info" />

        </receiver>

    </application>

 

    <uses-sdk android:minsdkversion="8" />

 

</manifest>

این خصیصه به AppWidgetProvider دستور می دهد که ACTION_APPWIDGET_UPDATE broadcast را بپذیرد . این خصیصه همچنین metadata ی ابزارک مورد نظر را مشخص می کند .

راه اندازی و تست برنامه

اکنون برنامه ی خود را در دستگاه اندروید اجرا کنید . پس از اجرای برنامه با استفاده از Android launcher ابزارک جدید را در صفحه نمایش خانگی پیاده کنید .

نصب Widget بخش اول

 

 

 

 

نصب Widget بخش دوم

5. Collection view widgets

Collection view widgets قابلیت پشتیبانی و استفاده از کلاس های ListView, StackView و GridView را در ابزارک ها فراهم می کند.

برای Collection view widgets به دو فایل طرح بندی (layout file) نیاز دارید, یکی ویژه ی خود ابزارک و دیگری مختص هر یک از آیتم های موجود در مجموعه ابزارک (widget collection) .

آیتم های ابزارک با نمونه ای از کلاس RemoteViewsFactory پر می شوند .

این کلاس (factory class) توسط یکی از سرویس های اندروید ارائه می شود که کلاس RemoteViewsService را به ارث می برد . سرویس مزبور به مجوز android.permission.BIND_REMOTEVIEWS نیاز دارد .

جهت متصل کردن view ها با سرویس مذکور, متد onUpdate() را در پیاده سازی ابزارک بکار ببرید .

 ابتدا یک intent تعریف کنید که به سرویس مربوطه ارجاع می دهد, سپس متد setRemoteAdapter را در کلاس RemoteViews بکار ببرید .   

Intent intent = new Intent(context, YourRemoteViewsService.class);
        intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
        views.setRemoteAdapter(apppWidgetId,
        R.id.widget_your_id_to_collectionview,
        intent)

6. فعال سازی یک ابزارک برای Lock Screen

از ویرایش 4.2 به بعد اندروید, این امکان فراهم شده ابزارک های برنامه ها را که مختص صفحه نمایش خانگی هستند (home screen application widgets) به lock screen دستگاه اندروید اضافه کنید . برای این منظور کافی است یک ابزارک جهت پشتیبانی از رده ی "keyguard"" در خصیصه ی android:widgetCategory داخل فایل اِکس اِم اِل  AppWidgetProviderInfo معرفی کنید .

کد زیر نمونه ای از آن را در زیر برای شما به نمایش می گذارد .

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
       
android:widgetCategory=
"keyguard|home_screen"
       
...
        >
        ...
</appwidget-provider>

در مثال فوق ابزارکی تعریف کردیم که که از هر دو پشتیبانی می کند – قفل صفحه (lock screen) و صفحه ی خانگی (home screen) . چنانچه برنامه ی خود را هم اکنون مجدداً کامپایل کرده و راه اندازی کنید, می توانید ابزارک را به lock screen اضافه کنید .

همچنین می توانید یک widget category را در زمان اجرا شناسایی (detect) کنید . برای این منظور در متد AppWidgetProvider.onUpdate(), می توانید با استفاده از کد زیر category option یک ابزارک را بررسی کنید .

Bundle options = appWidgetManager.getAppWidgetOptions(widgetId);

       
int category = options.getInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY, -1
);
       
boolean
isLockScreen = category == AppWidgetProviderInfo.WIDGET_CATEGORY_KEYGUARD;

به کمک این روش می توانید مدیریت کنید ابزارک هایی که برنامه ی کاربردی ارائه می دهد هنگامی که در صفحه ی قفل جای گذاری می شود ظاهر متفاوتی داشته باشند .

 

همان طور که خصیصه ی android:initialLayout را برای تعریف طرح کلی (layout) اولیه ویژه ی ابزارک های صفحه ی خانگی بکار بردید, همان گونه نیز می توانید یک صفت مشخصه ((attribute برای قفل صفحه در فایل XML AppWidgetProviderInfo بکار ببرید . طرح کلی مذکور بلافاصله پس اضافه شدن ابزارک ظاهر شده و توسط طرح کلی اصلی یا حقیقی پس از مقداردهی اولیه ابزارک (initializing) جایگزین می شود . 

7. تمرین : بروز رسانی ابزارک از طریق service

مثال زیر کاربرد سرویس در بروز رسانی ابزارک را نمایش می دهد .

کلاس  UpdateWidgetServiceرا در پروژه ی خود ایجاد کنید .

package de.vogella.android.widget.example;

import
java.util.Random;

import
android.app.PendingIntent;
import
android.app.Service;
import
android.appwidget.AppWidgetManager;
import
android.content.ComponentName;
import
android.content.Intent;
import
android.os.IBinder;
import
android.util.Log;
import
android.widget.RemoteViews;

public class UpdateWidgetService extends
Service {
 
private static final String LOG = "de.vogella.android.widget.example"
;

  @Override
 
public void onStart(Intent intent, int
startId) {
    Log.i(LOG,
"Called"
);
   
// create some random data

   
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(
this
           
.getApplicationContext());

   
int
[] allWidgetIds = intent
            .getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS);

    ComponentName thisWidget =
new
ComponentName(getApplicationContext(),
            MyWidgetProvider.
class
);
   
int
[] allWidgetIds2 = appWidgetManager.getAppWidgetIds(thisWidget);
    Log.w(LOG,
"From Intent"
+ String.valueOf(allWidgetIds.length));
    Log.w(LOG,
"Direct"
+ String.valueOf(allWidgetIds2.length));

   
for (int
widgetId : allWidgetIds) {
     
// create some random data
     
int number = (new Random().nextInt(100
));

      RemoteViews remoteViews =
new RemoteViews(
this
             
.getApplicationContext().getPackageName(),
              R.layout.widget_layout);
      Log.w(
"WidgetExample"
, String.valueOf(number));
     
// Set the text
     
remoteViews.setTextViewText(R.id.update,
             
"Random: "
+ String.valueOf(number));

     
// Register an onClickListener
     
Intent clickIntent = new Intent(this
.getApplicationContext(),
              MyWidgetProvider.
class
);

      clickIntent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
      clickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS,
              allWidgetIds);

      PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(),
0
, clickIntent,
              PendingIntent.FLAG_UPDATE_CURRENT);
      remoteViews.setOnClickPendingIntent(R.id.update, pendingIntent);
      appWidgetManager.updateAppWidget(widgetId, remoteViews);
    }
    stopSelf();

   
super
.onStart(intent, startId);
  }

  @Override
 
public
IBinder onBind(Intent intent) {
   
return null
;
  }
}

کلاس نام برده را به عنوان یک Service به فایل AndroidManifest.xml اضافه کنید .

<service android:name=".UpdateWidgetService"></service>

MyWidgetProvider را به ذیل تغییر دهید, اکنون سرویس ساخته شده و راه اندازی می شود.

package de.vogella.android.widget.example;

import
android.appwidget.AppWidgetManager;
import
android.appwidget.AppWidgetProvider;
import
android.content.ComponentName;
import
android.content.Context;
import
android.content.Intent;
import
android.util.Log;

public class MyWidgetProvider extends
AppWidgetProvider {

 
private static final String LOG = "de.vogella.android.widget.example"
;

  @Override
 
public void
onUpdate(Context context, AppWidgetManager appWidgetManager,
                      
int
[] appWidgetIds) {

    Log.w(LOG,
"onUpdate method called"
);
   
// Get all ids
   
ComponentName thisWidget = new
ComponentName(context,
            MyWidgetProvider.
class
);
   
int
[] allWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget);

   
// Build the intent to call the service
   
Intent intent = new
Intent(context.getApplicationContext(),
            UpdateWidgetService.
class
);
    intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, allWidgetIds);

   
// Update the widgets via the service
   
context.startService(intent);
  }
}

به مجرد فراخوانی, سرویس ذکر شده تمامی ابزارک ها را بروز رسانی می کند . کافی است روی تنها یک ابزارک کلیک کرده تا کلیه ی ابزارک ها بروز رسانی شوند .

 

 

1394/07/27 4102 2859
رمز عبور : tahlildadeh.com یا www.tahlildadeh.com
نظرات شما

نظرات خود را ثبت کنید...