تا
قسمت سوم توانستیم Xamarin را نصب و پروژهی اولیه آن را بیلد کنیم. سپس کد مشترک بین سه پلتفرم را بر روی Windows اجرا و Edit & continue آن را هم تست کردیم که هم برای UI ای که با Xaml نوشته میشود و هم برای منطقی که با CSharp نوشته میشود، کار میکند.
همانطور که گفتیم، کد UI و Logic برای هر سه پلتفرم مشترک است؛ منتهی به علت امکانات دیباگ فوق العاده و سرعت بیشتر ویندوز، ابتدا آن را بر روی ویندوز تست کردیم و بعد برای تکمیل UI، آن را بر روی Android اجرا میکنیم. این بار میتوانید دو پروژه UWP و iOS را Unload کنید و سپس پروژه Android ای را در صورت Unload بودن Load کنید. (با راست کلیک نمودن روی پروژه). این کار باعث میشود Visual Studio بیهوده کند نشود؛ مخصوصا اگر سیستم شما ضعیف است.
ابتدا با موبایل یا تبلت اندرویدی شروع میکنیم. اگر چه Xamarin از نسخهی 4.0.3 اندروید به بالا را پشتیبانی میکند، ولی توصیه میکنم وقتتان را بر روی گوشیهای اندرویدی کمتر از 4.4 تلف نکنید. دستگاه را میتوانید، هم به صورت USB و هم به صورت Wifi استفاده کنید. ابتدا باید دستگاه اندرویدی خود را آمادهی برای دیباگ کنید. برای این منظور مقالههای فارسی و انگلیسی زیادی وجود دارند که میتوانید از آنها استفاده کنید. من عبارت "اندروید debug" را جستجو کردم و به
این مقاله رسیدم. همچنین Android SDK شما باید USB debugging اش نصب شده باشد که البته حجم زیادی ندارد. برای بررسی این مورد ابتدا از وجود فولدر extras\google\usb\_driver درAndroid SDK خود مطمئن شوید. حال سؤال این است که ویژوال استودیو، Android SDK را کجا نصب کردهاست که خیلی ساده در
این لینک توضیح داده شدهاست.
اگر فولدر extras\google\usb\_driver وجود نداشت، باید آن را نصب کنید که خیلی ساده توسط Android SDK Manager امکان پذیر است؛ ولی نه! امکان پذیر نیست!
دلیل: در Xamarin شما همیشه بر روی آخرین SDKها حرکت میکنید. این شامل Windows SDK 17134 و Android SDK 27 و iOS SDK 11 است. وقتی از نسخهی فعلی ویژوال استودیو، یعنی 15.8 به نسخهی بعدی ویژوال استودیو که الان Preview است بروید، یعنی 15.9، عملا به این معنا است که به Windows SDK 17763 و Android SDK 28 و iOS SDK 12 میروید. این بزرگترین مزیت Xamarin است و این یعنی شما همیشه به صد در صد امکانات هر پلتفرم در زبان CSharp دسترسی دارید و همیشه آخرین SDK هر سیستم عامل در اختیار شماست و اگر دوستی از طریق Swift توانست مثالی از ARKit 2.0 را در iOS 12 پیاده سازی کند،
قطعا شما هم میتوانید. همچنین تیم Xamarin نه تنها این امکانات را بلکه Documentation لازم را نیز در اختیار شما قرار میدهد. چون در همین مثال، مستندات Apple به زبان Swift / Objective-C بوده و مستندات Xamarin به زبان CSharp.
حال اگر سری به فولدر Android SDK نصب شدهی توسط Visual Studio بزنید، مشاهده میکنید که خبری از Android SDK Manager نیست! به صورت رسمی، مدتی است که گوگل در نسخههای اخیر Android SDK، دیگر Android SDK Manager را ارائه نمیکند و همانطور که گفتم شما الان بر روی آخرین نسخهی Android SDK هستید. هر چند ترفندهایی وجود دارد که این Manager را باز میگردانند، ولی لزومی به انجام این کار در Xamarin نیست و شما میتوانید از Android SDK Manager ای که تیم Xamarin ارائه دادهاست، استفاده کنید. همین مسئله در مورد Android Virtual Device Manager که برای مدیریت Emulatorها بود نیز صدق میکند.
برای استفاده از این دو، ضمن استفاده از ابزارهای دور زدن تحریم، در ویژوال استودیو، در منوی Tools، به قسمت Android رفته و Android SDK Manager را باز کنید. Android Emulator Manager نیز جایگزین Android Virtual Device Manager ای است که قبلا توسط گوگل ارائه میشد. حال بعد از باز کردن Android SDK Manager ارائه شده توسط Xamarin، به برگهی Tools آن بروید و از قسمت extras مطمئن شوید که Google USB driver تیک خورده باشد.
حال پس از وصل کردن گوشی یا تبلت اندرویدی به سیستم توسط کابل USB و Set as startup project نمودن پروژهی XamApp.Android که در قسمت قبل آن را Clone کرده بودید، میتوانید پروژه را بر روی گوشی خود اجرا کنید. اگر نام گوشی خود را در کنار دکمهی سبز اجرای پروژه (F5) نمیبینید، بستن و باز کردن Visual Studio را امتحان کنید.
پروژه را که اجرا کنید، اولین بیلد کمی طول میکشد (اولین بار دو برنامه بر روی گوشی شما نصب میشوند که برای کار دیباگ در Xamarin لازم هستند) و اساسا بیلد یک پروژهی اندرویدی کند است. خوشبختانه به واسطه وجود Xaml edit and continue احتیاجی به Stop - Start کردن پروژه و بیلد کردن برای اعمال تغییرات UI نیست و به محض تغییر Xaml، میتوانید تاثیر آن را در گوشی خود ببینید. ولی برای هر تغییر CSharp باید Stop - Start و Build کنید که زمان بر است و به همین علت تست بر روی پروژه ویندوزی را برای پیاده سازی منطق برنامه پیشنهاد میکنیم. البته در نسخهی 15.9 ویژوال استودیو، سرعت بیلد تا 40% بهبود یافته است.
ممکن است شما گوشی اندرویدی یا تبلت نداشته باشید که بخواهید بر روی آن تست کنید و یا مثلا گوشی شما Android 7 هست و میخواهید بر روی Android 8 تست بگیرید. در این جا شما احتیاج به استفاده از Emulator را خواهید داشت.
توجه داشته باشید که Emulator شما ترجیحا نباید ARM باشد و بهتر است یا X86 یا X64 باشد، وگرنه ممکن است خیلی کند شود. همچنین بهتر است Google Play Services داشته باشد. همچنین ترجیحا دنبال گزینهی اجرا کردن Emulator نروید؛ اگر خود ویندوز شما درون یک Virtual Machine در حال اجراست.
ابتدا ضمن جستجو کردن "فعال سازی intel virtualization"، اقدام به فعال سازی این امکان در سیستم خود کنید.
این آموزش را مناسب دیدم.
گزینههای مطرح: [Google Android Emulator] - [Genymotion] - [Microsoft Hyper-V Android Emulator] که فقط یکی از آنها را لازم دارید.
Google Android Emulator توسط خود Google ارائه میشود و دارای Google Play Services نیز هست. بر اساس
این آموزش به صفحه Workloads در Visual Studio Installer بروید و از قسمت Xamarin دو مورد
"Google Android Emulator API Level 27" و "Intel Hardware Accelerated Execution Manager (HAXM) global install" را نصب کنید. توجه داشته باشید که بدین منظور احتیاج به ابزارهای دور زدن تحریم دارید؛ زیرا نیاز به دسترسی به سرورهای گوگل هست. این Emulator آماده برای دیباگ هست و نیازی به اقدام خاصی نیست.
Genymotion حجم کمتری دارد و برای دانلود احتیاج به ابزارهای دور زدن تحریم را ندارد و اساسا نسبت به بقیه بر روی سیستمهای ضعیفتر، بهتر کار میکند. فقط Emulator ای که با آن میسازید، به صورت پیش فرض Google Play Services را ندارد که در آخرین نسخههای آن گزینه Open GApps به toolbar اضافه شده که Google Play Services را اضافه میکند. (از انجام هر گونه عملیات پیچیده بر اساس آموزشهایی که برای نسخههای قدیمیتر Genymotion هستند، پرهیز کنید). مطابق با ابتدای همین آموزش برای دستگاههای اندرویدی، Emulator خود را آماده برای دیباگ کنید.
Microsoft Hyper-V android emulators. مایکروسافت قبلا اقدام به ارائه یک Android Emulator کرده بود که برای نسخه 4 و 5 اندروید بودند و بزرگترین ضعف آنها عدم پشتیبانی از Google Play Services بود که ادامه داده نشدند. ولی سری جدید ارائه شده توسط مایکروسافت چنین مشکلی را ندارد. اگر CPU شما AMD بوده و روشهای قبلی برای شما کند هستند یا اساسا کار نمیکنند، یا در حال حاضر در حال استفاده از Docker for Windows هستید که از Hyper-V استفاده میکنید و قصد استفاده مجدد از منابع موجود را دارید، این نیز گزینه خوبی است که جزئیات آن را میتوانید در اینجا دنبال کنید. این Emulator آماده برای دیباگ هست و نیازی به اقدام خاصی نیست.
پس از اینکه Emulator خود را ساختید، آن را اجرا کنید. سپس برنامه را از درون ویژوال استدیو اجرا کنید. مطابق نسخه ویندوزی، دوباره یک دکمه دارید و یک Label، عدد بر روی Label، با هر بار کلیک کردن بر روی دکمه، افزایش مییابد.
سرعت اجرای این برنامه در Emulator یا گوشی شما برای دیباگ است و در حالت Release، سرعت چندین برابر بهتر خواهد شد و به هیچ وجه تستهای Performance را بر روی Debug mode انجام ندهید.
حال نوبت به پابلیش پروژه میرسد. در این قسمت باید توجه کنید که حجم Apk شما برای پروژهی XamApp مثال ما به 7 مگ میرسد که برای یک فرم ساده خیلی زیاد به نظر میرسد. ولی اگر شما بجای یک فرم ساده، صد فرم پیچیده نیز داشته باشید، باز هم این حجم به 8 مگ نخواهد رسید. حجم Apk خیلی متاثر از کدهای شما نیست، بلکه شامل موارد زیر است:
1- NET. که خود شامل CLR & BCL است. (BCL (Base Class Library مثل کلاسهای string - Stream - List - File و (CLR (Common language runtime که شامل موارد لازم برای اجرای کدها است. این پیاده سازی بر اساس NET Standard 2.0. بوده که عملا اجازه استفاده از تعداد خیلی زیادی از کتابخانههای موجود را میدهد، حتی Entity framework core! البته هر کتابخانه حجم DLLهای خودش را اضافه میکند.
2- Android Support libraries که به شما اجازه میدهد از تعداد زیادی (و البته نه همه) امکانات نسخههای جدید اندروید در پروژهتان استفاده کنید که بر روی نسخ قدیمیتر Android نیز کار کنند. همچنین با یکپارچگی با Google Play Services عملا خیلی از کارها سادهتر و با Performance بهتری انجام میشود، مانند گرفتن موقعیت کاربر جاری.
3- Xamarin essentials . اگر چه در CSharp شما به صد در صد امکانات هر سیستم عامل دسترسی دارید و میتوانید مثلا مقدار درصد شارژ باطری را بخوانید، ولی اینکار مستلزم نوشتن سه کد CSharp ای برای Android - iOS - Windows است که طبیعتا کار را سخت میکند. اما Xamarin Essentials به شما اجازه میدهد با یک کد CSharp واحد برای هر سه پلتفرم، با باطری، کلیپبورد، قطب نما و خیلی موارد دیگر کار کنید. 4- Xamarin.Forms. اگر Button و Label ای که در مثال برنامه داشتیم، با یکبار نوشتن بر روی هر سه پلتفرم دارند کار میکنند، در حالی که هر پلتفرم، Button مخصوص به خود را دارد؛ این را Xamarin Forms مدیریت میکند. علاوه بر این، Binding نیز به عهدهی Xamarin Forms است.
5-
Prism -
Autofac -
Bit Framework: درک آنها نیاز به دنبال کردن آموزشهای این دوره را دارد؛ ولی به صورت کلی معماری پروژه شما بسیار کارآمد و حرفهای خواهد شد و به کدی با قابلیت نگهداری بالا خواهید رسید.
حجم 7 مگ برای این تعداد کتابخانه و امکان، خیلی زیاد نیست و شما عملا تعداد زیادی از پروژههای خود را میتوانید با همین حجم ببندید و اگر مثلا به پروژهی
Humanizer خیلی علاقه داشته باشید (که در این صورت حق هم دارید!) میتوانید با اضافه شدن چند کیلوبایت (!) به پروژه آن را داشته باشید. اکثر کتابخانههای NET. ای سبک هستند. همچنین موقع قرار گرفتن در پروژه، فشرده سازی نیز میشوند و قسمتهای استفاده نشدهی آنها نیز توسط Linker حذف میشوند.
علاوه بر این، اجرای برنامه بر روی گوشیهای ضعیف و قدیمی کمی طول میکشد. این مربوط به اجرای برنامه است؛ نه باز شدن فرم مثال ما که دارای Button و Label بود و اگر مثال ما دو فرم داشته باشد (که در آموزشهای بعدی به آن میرسیم) میبینید که چرخش بین فرمها بسیار سریع است.
مواردی مهم در زمینهی بهبود عملکرد پروژههای Xamarin در Android
در ابتدا باید بدانید Apk شما شامل دو قسمت است؛ یکی کدهای CSharp ای شما که DotNet ای بوده و در کنار کدهای کتابخانههایی چون Json.NET بر روی DotNet اجرا میشوند. دیگری کتابخانهای است که مثلا با Java نوشته شده و بعد برای استفاده در CSharp بر روی آن یک Wrapper یا پوشاننده توسعه داده شدهاست. عموما توسعه دهندگان چنین پروژههایی، ابتدا پروژه را به Java مینویسند و بعد برای JavaScript - CSharp و ... Wrapper ارائه میدهند.
برای بهبود اینها ابزارهایی چون AOT-NDK-LLVM-ProGurad-Linker و ... وجود دارند که سعی میکنم به صورت ساده آنها را توضیح دهم.
وظیفه ProGurad این است که از قسمتی از پروژهی شما که بخاطر کتابخانههای Java ای، عملا DotNet ای نیست، کدهای اضافه و استفاده نشده را حذف کند.
ممکن است استفاده از ProGurad باعث شود کلاسی که داینامیک استفاده شده است، به اشتباه حذف شود. پروژه XamApp دارای یک
ProGuard configuration file است که جلوی چنین اشتباهاتی را حتی الامکان میگیرد.
همچنین ProGurad که در داخل Android SDK قرار دارد، به Space در طول مسیر حساس است (!) و با توجه به اینکه مسیر پیش فرض Android SDK نصب شدهی توسط ویژوال استودیو دارای Space است (C:\Program Files (x86)\Android\android-sdk) شما در همان ابتدا دچار مشکل میشوید! برای حل این مشکل ابدا فولدر Android SDK را جا به جا نکنید؛ بلکه از امکانی در ویندوز به نام Junction folder یا فولدر جانشین استفاده کنید. بدین منظور دستور زیر را وارد کنید:
mklink /j C:\android-sdk "C:\Program Files (x86)\Android\android-sdk"
این مورد باعث میشود که مسیر C:\android-sdk نیز به همان مسیر پیش فرض اشاره کند و این دو مسیر در واقع یکی هستند. امیدوارم این امکان را با قابلیت Shortcut سازی در ویندوز اشتباه نگیرید! حال از منوی Tools > Options > Xamarin > Android Settings مسیر Android SDK را به C:\android-sdk تغییر دهید که فاقد Space است و ویژوال استودیو را ببندید و باز کنید.
NDK که در ادامه SDK برای Android قرار میگیرد، Native Development Kit است و باعث میشود هم DLLهای DotNet ای و هم Jarهای Java ای به فایلهای so تبدیل شوند. so همان DLL ویندوز است، البته برای Linux و همانطور که احتمالا میدانید، پایه Android بر روی Linux است. طبیعتا کامپایل شدن کدها به so، بر روی بهبود سرعت برنامه تاثیر گذار است.
Linker نیز مشابه با ProGuard کمک میکند، ولی اینبار حجم DLLهای DotNet ای مانند Json.NET را کم میکند. بالاخره شما از صد در صد کلاسهای یک DLL استفاده نمیکنید و موارد اضافی نیز باید حذف شوند. البته این وسط، امکان حذف اشتباه کلاسهایی که به صورت داینامیک فراخوانی شده باشند وجود دارد که LinkerConfig موجود در پروژه XamApp حتی الامکان جلوی این مشکل را میگیرد.
جزئیات این موارد در مستندات Xamarin وجود دارد و در پایان این دوره یک Project Builder سورس باز نیز به شما ارائه میشود که ساختار اولیه پروژهها را بر اساس نیازهای شما و با بهترین تنظیمات ممکن میسازد.
در پروژه XamApp علاوه بر موارد فوق، دو مورد دیگر نیز آماده به استفاده هستند، ولی غیر فعال شده اند؛ AOT و LLVM. اگر به تازگی برنامه نویس شدهاید، موارد زیر ممکن است خیلی برایتان پیچیده باشند، از آنها عبور کنید و به عنوان "نحوه انجام دادن پابلیش" بروید.
کدهایهای DotNet ای به سه شکل میتوانند اجرا شوند:
JIT - AOT - Interpreter
یک برنامه DotNet ای برای اجرا میتواند از ترکیب اینها استفاده کند. حالت Interpreter که خیلی جدید معرفی شده و الآن موضوع بحث نیست؛ میماند JIT و AOT
کد CSharp در هنگام کامپایل به IL تبدیل و سپس در زمان اجرا توسط Just in time compiler به زبان ماشین تبدیل میشود. اگر قبلا پروژهی ASP.NET یا ASP.NET Core نوشته باشید، چنین رفتاری را در پشت صحنه خواهد داشت. خود JIT که در هر بار اجرای برنامه انجام میشود، عملا زمان بر هست. ولی کد زبان ماشین حاصل از آن خیلی Optimize شده برای دقیقا همان ماشین هست؛ با در نظر گرفتن خیلی فاکتورها. در پروژههای سمت سرور مثل ASP.NET که پروژه وقتی یک بار اجرا میشود، مثلا روی IIS، ممکن است صدها هزار دستور را اجرا کند، در طول چندین روز یا ماه، این عمل JIT خیلی مفید هست. البته همان سربار اولیهی JIT هم توسط چیزی به عنوان Tiered JIT میتواند کمتر شود.
اما در پروژهی موبایل که برنامه ممکن است بعد از باز شدن، مثلا ده دقیقه باز باشد و بعد بسته شود، انجام شدن JIT با هر بار باز شدن برنامه خیلی مفید به فایده نیست. بنا به برخی مسائل که واقعا سطح این آموزش را خیلی پیچیده میکند، نتیجه کار JIT قابلیت Cache شدن آن چنانی ندارد و عملا باید هر بار اجرا شود.
در پروژههای موبایل، گزینه دیگری بر روی میز هست به نام Ahead of time یا AOT که کار تبدیل IL به زبان ماشین را در زمان کامپایل و پابلیش پروژه انجام دهد. طبیعتا این باعث میشود سرعت برنامه موبایل در عمل خیلی بالاتر رود، چون سربار JIT در هر بار اجرای برنامه حذف میشود. همچنین روال AOT میتواند از LLVM یا Low level virtual machine استفاده کند که منجر به تبدیل شدن کد زبان ماشینی میشود که بر روی LLVM کار میکند. LLVM خودش یک Runtime با سرعت خیلی بالاست که بر روی تمامی سیستم عاملها کار میکند.
بر روی Android - iOS - Windows میشود از AOT استفاده کرد. در iOS و ویندوز، استفادهی از AOT منجر به افزایش سایز برنامه نمیشود، چون قبلا برنامه یک سری کد IL بوده که زمان اجرا توسط JIT به کد ماشین تبدیل میشده و الان بجای آن IL، یک سری کد زبان ماشین مبتنی بر LLVM هست. اما بر روی Android، پیاده سازی AOT ناقص هست و البته که با فعال کردناش، سرعت برنامه بسیار بیشتر میشود، ولی کماکان نیاز به JIT و IL هم برای برخی از سناریوها هست. این مورد یعنی اینکه فعال سازی AOT+LLVM بر روی اندروید تا مادامی که AOT در Android به صورت آزمایشی هست، باعث افزایش حجم Apk ما از 7 به 13 مگ میشود. البته این مورد در نسخههای بعدی رفع خواهد شد و رفتار Android مشابه با iOS-Windows خواهد بود؛ یعنی حجم نسبتا کم و سرعت خیلی بالا.
برای فعال سازی AOT+LLVM در
csproj پروژه اندرویدی، دو مقدار AotAssemblies و EnableLLVM را از false به true تغییر دهید:
<AotAssemblies>true</AotAssemblies>
<EnableLLVM>true</EnableLLVM>
با این تنظیمات، بیلد شما طولانیتر و در عوض سرعت اجرای برنامه بیشتر خواهد شد.
نحوه انجام دادن پابلیش
برای انجام دادن پابلیش، بر روی پروژه XamApp.Android در هنگامیکه بر روی Release mode هستید، راست کلیک کنید و Archive را بزنید. سپس فایل Archive شده را انتخاب و Distribute را بزنید که به شما Apk مناسب برای انتشار توسط خودتان یا Google Play میدهد.
نکات مهم:
1- فایل Apk حاصل از Archive را بدون Distribute کردن، در اختیار کسی قرار ندهید. فقط پیام Corrupt و خراب بودن فایل، حاصل کارتان خواهد بود!
2- اولین باری که Distribute میکنید، Wizard مربوطه کمک میکند تا یک فایل Certificate را برای Apk اتان بسازید. آن فایل را گم نکنید! در پابلیشهای بعدی دیگر نباید Certificate جدیدی بسازید؛ بلکه فایل قبلی را باید به آن معرفی کنید و فقط رمز آن Certificate را دوباره بزنید.
3- به برنامه آیکون بدهید. برای آن Splash Screen خوبی بگذارید. در هر بار پابلیش، ورژن برنامه را افزایش دهید. اینها همگی توضیحات اش بر روی بستر وب موجود است. سؤالی بود، همینجا هم میتوانید بپرسید.
فایلهای Apk این مثال را میتوانید از
اینجا دانلود کنید.
در قسمت بعدی آموزش، دیباگ و پابلیش گرفتن پروژه بر روی iOS را خواهیم داشت که البته مقداری از مطالب اش با مطالب این آموزش مشترک هست. بعد دست به کد شده و آموزش CSharp و Xaml را خواهیم داشت تا پروژهای با کیفیت، کارآمد و عالی از هر جهت بنویسید.
همچنین تعدادی از نکات مربوط به Performance که مربوط به ظاهر برنامه و نحوه چیدمان صفحات و کنترلها هستند و بر روی Performance هر سه پلتفرم تاثیر گذار هستند (و نه فقط Android) نیز در ادامه بحث خواهند شد.