برنامههایی که درحالحاضر از کتابخانه مستقل com.google.android.exoplayer2
و androidx.media استفاده میکنند باید به androidx.media3 انتقال داده شوند. از دستورگان انتقال برای انتقال فایلهای ساخت gradle، فایلهای منبع جاوا و Kotlin، و فایلهای چیدمان XML از ExoPlayer 2.19.1 به AndroidX Media3 1.1.1 استفاده کنید.
نمای کلی
قبلاز انتقال، بخشهای زیر را مرور کنید تا درباره مزایای میاناهای برنامهسازی کاربردی جدید، میاناهای برنامهسازی کاربردی برای انتقال، و پیشنیازهایی که پروژه برنامهتان باید داشته باشد بیشتر بدانید.
چرا به Jetpack Media3 انتقال دهیم
- این خانه جدید ExoPlayer است، درحالیکه
com.google.android.exoplayer2متوقف شده است. - با
MediaBrowser/MediaControllerبه میانای برنامهسازی کاربردی پخشکننده در سراسر عناصر/فرایندها دسترسی پیدا کنید. - از قابلیتهای گسترده
MediaSessionوMediaControllerAPI استفاده کنید. - قابلیتهای بازپخش را با کنترل دسترسی دقیق تبلیغ کنید.
- با برداشتن
MediaSessionConnectorوPlayerNotificationManager، برنامهتان را ساده کنید. - با میاناهای برنامهسازی کاربردی کارخواه سازگار با رسانه سازگار با نسخههای قبلی است
(
MediaBrowserCompat/MediaControllerCompat/MediaMetadataCompat)
میاناهای برنامهسازی کاربردی رسانه برای انتقال به AndroidX Media3
- ExoPlayer و افزونههای آن
این شامل همه واحدهای پروژه قدیمی ExoPlayer بهجز واحد mediasession است که متوقف شده است. برنامهها یا واحدهایی که به بستههای موجود درcom.google.android.exoplayer2وابسته هستند را میتوان با اسکریپت انتقال انتقال داد. - MediaSessionConnector (بسته به
androidx.media.*بستههایandroidx.media:media:1.4.3+)
MediaSessionConnectorرا بردارید و بهجای آن ازandroidx.media3.session.MediaSessionاستفاده کنید. - MediaBrowserServiceCompat (بسته به
androidx.media.*بستههایandroidx.media:media:1.4.3+)
زیرکلاسهایandroidx.media.MediaBrowserServiceCompatرا بهandroidx.media3.session.MediaLibraryServiceانتقال دهید و بااستفاده ازMediaBrowserCompat.MediaItemبهandroidx.media3.common.MediaItemکدنویسی کنید. - MediaBrowserCompat (بسته به
android.support.v4.media.*بستههایandroidx.media:media:1.4.3+)
کد مشتری را بااستفاده ازMediaBrowserCompatیاMediaControllerCompatبهandroidx.media3.session.MediaBrowserباandroidx.media3.common.MediaItemمنتقل کنید.
پیشنیازها
مطمئن شوید پروژه شما تحت کنترل منبع است
مطمئن شوید که میتوانید بهراحتی تغییرات اعمالشده توسط ابزارهای انتقال داده بااستفاده از دستورگان را برگردانید. اگر هنوز پروژه خود را تحت کنترل منبع ندارید، اکنون زمان خوبی برای شروع آن است. اگر به هر دلیلی نمیخواهید این کار را انجام دهید، قبلاز شروع انتقال، یک نسخه پشتیبان از پروژه خود تهیه کنید.
بهروزرسانی برنامه
توصیه میکنیم پروژه خود را بهروز کنید تا از جدیدترین نسخه کتابخانه ExoPlayer استفاده کنید و هرگونه فراخوانی روشهای منسوخشده را حذف کنید. اگر قصد دارید از دستورگان برای انتقال استفاده کنید، باید نسخهای را که بهروز میکنید با نسخهای که دستورگان مدیریت میکند مطابقت دهید.
compileSdkVersion برنامه خود را حداقل به ۳۲ افزایش دهید.
Gradle و افزایه Android Studio Gradle را به نسخه جدیدی که با وابستگیهای بهروزشده در بالا کار میکند ارتقا دهید. برای مثال:
- نسخه افزایه Android Gradle: 7.1.0
- نسخه Gradle: 7.4
همه گزارههای وارد کردن با حروف عام را که از ستاره (*) استفاده میکنند جایگزین کنید و از گزارههای وارد کردن کاملاً واجدشرایط استفاده کنید: گزارههای وارد کردن با حروف عام را حذف کنید و از Android Studio برای وارد کردن گزارههای کاملاً واجدشرایط استفاده کنید (F2 - Alt/Enter، F2 - Alt/Enter، …).
انتقال از
com.google.android.exoplayer2.PlayerViewبهcom.google.android.exoplayer2.StyledPlayerView. این کار لازم است زیرا در AndroidX Media3 معادلcom.google.android.exoplayer2.PlayerViewوجود ندارد.
انتقال ExoPlayer با پشتیبانی از دستورگان
این دستورگان انتقال از com.google.android.exoplayer2 به ساختار جدید بسته و واحد تحت androidx.media3 را تسهیل میکند. این دستورگان برخیاز بررسیهای اعتبارسنجی را روی پروژه شما اعمال میکند و درصورت ناموفق بودن اعتبارسنجی، هشدارهایی را چاپ میکند.
درغیراینصورت، نگاشتهای کلاسها و بستههای تغییرنامدادهشده را در
منابع پروژه Android gradle که به زبان Java یا Kotlin نوشته شده است اعمال میکند.
usage: ./media3-migration.sh [-p|-c|-d|-v]|[-m|-l [-x <path>] [-f] PROJECT_ROOT]
PROJECT_ROOT: path to your project root (location of 'gradlew')
-p: list package mappings and then exit
-c: list class mappings (precedence over package mappings) and then exit
-d: list dependency mappings and then exit
-l: list files that will be considered for rewrite and then exit
-x: exclude the path from the list of file to be changed: 'app/src/test'
-m: migrate packages, classes and dependencies to AndroidX Media3
-f: force the action even when validation fails
-v: print the exoplayer2/media3 version strings of this script
-h, --help: show this help text
استفاده از دستورگان انتقال
برنامه انتقال را از برچسب پروژه ExoPlayer در GitHub متناسب با نسخهای که برنامه خود را به آن بهروز کردهاید بارگیری کنید:
curl -o media3-migration.sh \ "https://raw.githubusercontent.com/google/ExoPlayer/r2.19.1/media3-migration.sh"اجرایی کردن متن:
chmod 744 media3-migration.shبرای آشنایی با گزینهها، این پلات را با
--helpاجرا کنید.برای فهرست کردن مجموعه فایلهایی که برای انتقال انتخاب شدهاند، این دستور را با
-lاجرا کنید (برای اجبار کردن فهرست بدون هشدار، از-fاستفاده کنید):./media3-migration.sh -l -f /path/to/gradle/project/rootبرای نگاشت بستهها، کلاسها، و واحدها به Media3، این دستورگان را با
-mاجرا کنید. اجرای دستورگان با گزینه-mتغییرات را روی فایلهای انتخابی اعمال میکند.- بدون اعمال تغییرات، در خطای اعتبارسنجی متوقف شود
./media3-migration.sh -m /path/to/gradle/project/root- اجرای اجباری
اگر این نوشتار نقض پیشنیازها را پیدا کند، میتوان با پرچم
-fانتقال را اجباری کرد:./media3-migration.sh -m -f /path/to/gradle/project/root
# list files selected for migration when excluding paths
./media3-migration.sh -l -x "app/src/test/" -x "service/" /path/to/project/root
# migrate the selected files
./media3-migration.sh -m -x "app/src/test/" -x "service/" /path/to/project/root
پساز اجرای اسکریپت با گزینه -m، این مراحل دستی را تکمیل کنید:
- بررسی کنید که چگونه دستورگان کد شما را تغییر داده است: از ابزار تفاوت استفاده کنید و مشکلات احتمالی را برطرف کنید (اگر فکر میکنید دستورگان مشکل کلی دارد که بدون گذراندن گزینه
-fمعرفی شده است، گزارش اشکال ثبت کنید). - ساختن پروژه: یا از
./gradlew clean buildاستفاده کنید یا در Android Studio، File > Sync Project with Gradle Files (فایل > همگامسازی پروژه با فایلهای Gradle) را انتخاب کنید، سپس Build > Clean project (ساختن > پاک کردن پروژه)، و سپس Build > Rebuild project (ساختن > بازسازی پروژه) را انتخاب کنید (ساختن را در برگه Build - Build Output (ساختن - برونداد ساختن) در Android Studio پایش کنید).
مراحل پیگیری توصیهشده:
- برای خطاهای مربوط به استفاده از میاناهای برنامهسازی کاربردی ناپایدار، موافقت خود را اعلام کنید.
- جایگزین کردن فراخوانیهای منسوخشده میانای برنامهسازی کاربردی: از میانای برنامهسازی کاربردی جایگزین پیشنهادی استفاده کنید. نشانگر را روی هشدار در «استودیو Android» نگه دارید و برای اینکه بدانید بهجای فراخوانی دادهشده از چه چیزی استفاده کنید، به JavaDoc نماد منسوخشده مراجعه کنید.
- مرتب کردن دستورات وارد کردن: پروژه را در «استودیو Android» باز کنید، سپس روی گره پوشه بسته در بیننده پروژه کلیک راست کنید و بهینهسازی وارد کردنها را در بستههایی که حاوی فایلهای منبع تغییریافته هستند انتخاب کنید.
جایگزین کردن MediaSessionConnector با androidx.media3.session.MediaSession
در دنیای قدیمی MediaSessionCompat، MediaSessionConnector مسئول همگامسازی وضعیت پخشکننده با وضعیت جلسه و دریافت دستورات از کنترلکنندههایی بود که نیاز به واگذاری به روشهای پخشکننده مناسب داشتند. با AndroidX Media3، این کار مستقیماً توسط MediaSession انجام میشود
بدون نیاز به اتصالدهنده.
برداشتن همه ارجاعها و استفاده از MediaSessionConnector: اگر از نوشتار خودکارسازیشده برای انتقال کلاسها و بستههای ExoPlayer استفاده کردهاید، نوشتار احتمالاً کد شما را در وضعیتی قرار داده است که در آن
MediaSessionConnectorقابلحل نیست و نمیتوان آن را کامپایل کرد. وقتی سعی میکنید برنامه را بسازید یا شروع کنید، Android Studio کد خراب را به شما نشان میدهد.در فایل
build.gradleکه وابستگیهایتان را در آن نگهداری میکنید، وابستگی پیادهسازی به واحد جلسه AndroidX Media3 اضافه کنید و وابستگی قدیمی را بردارید:implementation "androidx.media3:media3-session:1.11.1"
MediaSessionCompatرا باandroidx.media3.session.MediaSessionجایگزین کنید.در سایت کد که
MediaSessionCompatقدیمی را ایجاد کردهاید، ازandroidx.media3.session.MediaSession.Builderبرای ساختنMediaSessionاستفاده کنید. برای ساختن سازنده جلسه، بازیکن را رد کنید.را ببینید.کاتلین
val player = ExoPlayer.Builder(context).build() mediaSession = MediaSession.Builder(context, player).setCallback(MySessionCallback()).build()
جاوا
ExoPlayer player = new ExoPlayer.Builder(context).build(); mediaSession = new MediaSession.Builder(context, player).setCallback(new MySessionCallback()).build();
MySessionCallbackرا همانطور که برنامهتان لازم دارد پیادهسازی کنید. این کار اختیاری است. اگر میخواهید کنترلکنندهها بتوانند موارد رسانهای را به پخشکننده اضافه کنند،MediaSession.Callback.onAddMediaItems()را پیادهسازی کنید. این میانای برنامهسازی کاربردی روشهای مختلف API فعلی و قدیمی را ارائه میدهد که موارد رسانهای را به پخشکننده برای بازپخش به روشی سازگار با نسخههای قبلی اضافه میکند. این شاملMediaController.set/addMediaItems()روشهای کنترلکننده Media3 و همچنینTransportControls.prepareFrom*/playFrom*روشهای API قدیمی میشود. پیادهسازی نمونهای ازonAddMediaItemsرا میتوانید درPlaybackServiceبرنامه نمایشی جلسه پیدا کنید.جلسه رسانهای را در سایت کد که در آن جلسه خود را قبلاز انتقال ازبین بردید منتشر کنید:
کاتلین
mediaSession?.run { player.release() release() mediaSession = null }
جاوا
if (mediaSession != null) { mediaSession.getPlayer().release(); mediaSession.release(); mediaSession = null; }
عملکرد MediaSessionConnector در Media3
جدول زیر «میاناهای برنامهسازی کاربردی Media3» را نشان میدهد که عملکردی را که قبلاً در MediaSessionConnector پیادهسازی شده بود مدیریت میکنند.
| MediaSessionConnector | AndroidX Media3 |
|---|---|
CustomActionProvider |
MediaSession.Callback.onCustomCommand()/
MediaSession.setMediaButtonPreferences() |
PlaybackPreparer |
MediaSession.Callback.onAddMediaItems()
(prepare() در داخل فراخوانده میشود)
|
QueueNavigator |
ForwardingSimpleBasePlayer |
QueueEditor |
MediaSession.Callback.onAddMediaItems() |
RatingCallback |
MediaSession.Callback.onSetRating() |
PlayerNotificationManager |
DefaultMediaNotificationProvider/
MediaNotification.Provider |
انتقال MediaBrowserService به MediaLibraryService
AndroidX Media3 MediaLibraryService را معرفی میکند که جایگزین
MediaBrowserServiceCompat میشود. JavaDoc مربوط به MediaLibraryService و ابرکلاس آن MediaSessionService مقدمه خوبی برای API و مدل برنامهنویسی ناهمزمان سرویس ارائه میدهد.
MediaLibraryService با
MediaBrowserService سازگار با نسخه قدیمی است. برنامه مشتری که از MediaBrowserCompat یا
MediaControllerCompat استفاده میکند، هنگام اتصال به MediaLibraryService بدون تغییر کد به کار خود ادامه میدهد. برای مشتری، شفاف است که برنامه شما از MediaLibraryService یا MediaBrowserServiceCompat قدیمی استفاده میکند.
برای اینکه سازگاری معکوس کار کند، باید هر دو میانای سرویس را در سرویس خود در
AndroidManifest.xmlثبت کنید. به این ترتیب، کارخواه سرویس شما را ازطریق میانای سرویس موردنیاز پیدا میکند:<service android:name=".MusicService" android:exported="true"> <intent-filter> <action android:name="androidx.media3.session.MediaLibraryService"/> <action android:name="android.media.browse.MediaBrowserService" /> </intent-filter> </service>در فایل
build.gradleکه در آن وابستگیهایتان را نگهداری میکنید، وابستگی پیادهسازی به واحد جلسه AndroidX Media3 اضافه کنید و وابستگی قدیمی را بردارید:implementation "androidx.media3:media3-session:1.11.1"سرویس خود را تغییر دهید تا از
MediaLibraryServiceبهجایMediaBrowserServiceبهارث ببرد. همانطور که قبلاً گفته شد،MediaLibraryServiceباMediaBrowserServiceقدیمی سازگار است. بنابراین، میانای برنامهسازی کاربردی گستردهتری که سرویس به کارخواهان ارائه میدهد همچنان یکسان است. بنابراین احتمالاً یک برنامه میتواند بیشتر منطقی را که برای پیادهسازیMediaBrowserServiceلازم است حفظ کند و آن را برایMediaLibraryServiceجدید تطبیق دهد.تفاوتهای اصلی در مقایسه با نسخه قدیمی
MediaBrowserServiceCompatبه شرح زیر است:پیادهسازی روشهای چرخه حیات سرویس: روشهایی که باید در خود سرویس لغو شوند عبارتاند از
onCreate/onDestroy، که در آن برنامه جلسه کتابخانه، پخشکننده، و سایر منابع را تخصیص/آزاد میکند. علاوهبر روشهای استاندارد چرخه حیات سرویس، برنامه بایدonGetSession(MediaSession.ControllerInfo)را ملغی کند تاMediaLibrarySessionرا که درonCreateساخته شده است برگرداند.پیادهسازی MediaLibraryService.MediaLibrarySessionCallback: ساختن جلسه نیازمند
MediaLibraryService.MediaLibrarySessionCallbackاست که روشهای واقعی میانای برنامهسازی کاربردی دامنه را پیادهسازی کند. بنابراین بهجای ملغی کردن روشهای میانای برنامهسازی کاربردی سرویس قدیمی، روشهایMediaLibrarySession.Callbackرا ملغی خواهید کرد.سپس از این برگشتتماس برای ساختن
MediaLibrarySessionاستفاده میشود:کاتلین
mediaLibrarySession = MediaLibrarySession.Builder(context, player, MySessionCallback()).build()
جاوا
mediaLibrarySession = new MediaLibrarySession.Builder(context, player, new MySessionCallback()).build();
میانای برنامهسازی کاربردی کامل MediaLibrarySessionCallback را در مستندات میانای برنامهسازی کاربردی پیدا کنید.
پیادهسازی
MediaSession.Callback.onAddMediaItems(): تماس برگشتیonAddMediaItems(MediaSession, ControllerInfo, List<MediaItem>)روشهای مختلف میانای برنامهسازی کاربردی فعلی و قدیمی را که موارد رسانهای را به پخشکننده اضافه میکنند برای بازپخش بهروشی سازگار با نسخههای قدیمی ارائه میدهد. این شاملMediaController.set/addMediaItems()روشهای کنترلکننده Media3، و همچنینTransportControls.prepareFrom*/playFrom*روشهای API قدیمی میشود. پیادهسازی نمونهای از پاسخبهتماس را میتوانید درPlaybackServiceبرنامه نمایشی جلسه پیدا کنید.AndroidX Media3 بهجای MediaBrowserCompat.MediaItem و MediaMetadataCompat از
androidx.media3.common.MediaItemاستفاده میکند. بخشهایی از کد شما که به کلاسهای قدیمی مرتبط است باید متناسب با آن تغییر کند یا بهجای آن به Media3MediaItemنگاشت شود.مدل برنامهنویسی ناهمزمان عمومی در مقایسه با رویکرد
ResultجداشدنیMediaBrowserServiceCompatبهFuturesتغییر کرد. پیادهسازی سرویس شما میتواند بهجای جدا کردن نتیجه یا برگرداندن «آینده» فوری برای برگرداندن مستقیم مقدار، یکListenableFutureناهمزمان برگرداند.
برداشتن PlayerNotificationManager
MediaLibraryService بهطور خودکار از اعلانهای رسانه پشتیبانی میکند و
PlayerNotificationManager را میتوان هنگام استفاده از MediaLibraryService یا
MediaSessionService برداشت.
برنامه میتواند با تنظیم کردن اعلان سفارشی
MediaNotification.Provider در onCreate() که جایگزین
DefaultMediaNotificationProvider میشود، اعلان را سفارشیسازی کند. سپس MediaLibraryService مراقب شروع سرویس در پیشزمینه طبق نیاز است.
با ملغی کردن MediaLibraryService.updateNotification()، برنامه میتواند مالکیت کامل ارسال اعلان و شروع/توقف سرویس در پیشزمینه را درصورت نیاز برعهده بگیرد.
انتقال کد کارخواه بااستفاده از MediaBrowser
با AndroidX Media3، یک MediaBrowser رابطهای MediaController/Player را پیادهسازی میکند و میتوان از آن برای کنترل بازپخش رسانه علاوهبر مرور کتابخانه رسانه استفاده کرد. اگر در دنیای قدیمی مجبور بودید MediaBrowserCompat و MediaControllerCompat ایجاد کنید، میتوانید بااستفاده از MediaBrowser در Media3 همان کار را انجام دهید.
یک MediaBrowser میتواند ساخته شود و منتظر بماند تا اتصال به
سرویس برقرار شود:
کاتلین
scope.launch { val sessionToken = SessionToken(context, ComponentName(context, "MusicService")) browser = MediaBrowser.Builder(context, sessionToken) .setListener(BrowserListener()) .buildAsync() .await() }
جاوا
SessionToken sessionToken = new SessionToken(context, new ComponentName(context, "MusicService")); ListenableFuture<MediaBrowser> browserFuture = new MediaBrowser.Builder(context, sessionToken) .setListener(new BrowserListener()) .buildAsync();
برای آشنایی با نحوه ایجاد MediaController برای کنترل بازپخش در پسزمینه، به
کنترل بازپخش در جلسه رسانه
نگاهی بیندازید.
مراحل بعدی و پاکسازی
خطاهای ناپایدار میانای برنامهسازی کاربردی
پساز انتقال به Media3، ممکن است خطاهای lint درباره استفادههای ناپایدار از API مشاهده کنید.
استفاده از این «میاناهای برنامهسازی کاربردی» ایمن است و خطاهای lint محصول جانبی ضمانتهای سازگاری باینری جدید ما است. اگر به سازگاری باینری دقیق نیاز ندارید،
این خطاها را میتوانید با یک
گزارمان @OptIn با اطمینان سرکوب کنید.
پسزمینه
نه ExoPlayer v1 و نه v2 ضمانتهای دقیقی درباره سازگاری باینری کتابخانه بین نسخههای بعدی ارائه نمیدهند. سطح API ExoPlayer بهدلیل طراحی بسیار بزرگ است تا به برنامهها اجازه دهد تقریباً هر جنبهای از بازپخش را سفارشیسازی کنند. نسخههای بعدی ExoPlayer گاهی اوقات تغییر نام نمادها یا سایر تغییرات مخرب (مثلاً روشهای جدید موردنیاز در رابطها) را معرفی میکنند. در اکثر موارد، این شکستگیها با معرفی نماد جدید همراه با منسوخ کردن نماد قدیمی برای چند نسخه کاهش یافتند تا توسعهدهندگان فرصت داشته باشند استفادههای خود را انتقال دهند، اما این همیشه ممکن نبود.
این تغییرات اساسی منجر به دو مشکل برای کاربران کتابخانههای ExoPlayer v1 و v2 شد:
- ارتقا از به نسخه ExoPlayer میتواند باعث شود کد از کامپایل شدن متوقف شود.
- برنامهای که هم بهطور مستقیم و هم ازطریق کتابخانه واسط به ExoPlayer وابسته بود باید مطمئن میشد که هر دو وابستگی نسخه یکسانی دارند، درغیراینصورت ناسازگاریهای دودویی میتوانست منجر به خرابیهای زمان اجرا شود.
بهبودها در Media3
Media3 سازگاری باینری را برای زیرمجموعهای از سطح API تضمین میکند. بخشهایی که سازگاری دودویی را تضمین نمیکنند با
@UnstableApi علامتگذاری شدهاند. برای اینکه این تمایز واضح باشد، استفاده از نمادهای ناپایدار
میانای برنامهسازی کاربردی خطای lint تولید میکند، مگر اینکه با @OptIn حاشیهنویسی شده باشند.
پساز انتقال از ExoPlayer v2 به Media3، ممکن است خطاهای زیادی از نوع lint API ناپایدار ببینید. این ممکن است باعث شود که Media3 «کمتر پایدار» از ExoPlayer v2 بهنظر برسد. اینطور نیست. بخشهای «ناپایدار» میانای برنامهسازی کاربردی Media3 همان سطح پایداری کل سطح میانای برنامهسازی کاربردی ExoPlayer v2 را دارند و ضمانتهای سطح میانای برنامهسازی کاربردی پایدار Media3 اصلاً در ExoPlayer v2 دردسترس نیست. تفاوت این است که اکنون خطای lint شما را از سطوح مختلف پایداری مطلع میکند.
رسیدگی به خطاهای ناپایدار API lint
برای جزئیات مربوط به نحوه حاشیهنویسی کردن استفادههای Java و Kotlin از میاناهای برنامهسازی کاربردی ناپایدار با @OptIn، به بخش عیبیابی این خطاهای lint مراجعه کنید.
میاناهای برنامهسازی کاربردی منسوخ
ممکن است متوجه شوید که تماسهای برقرارشده با میاناهای برنامهسازی کاربردی منسوخشده در Android Studio خطخورده است. توصیه میکنیم چنین تماسهایی را با جایگزین مناسب جایگزین کنید. برای دیدن JavaDoc که میگوید بهجای آن از کدام API استفاده کنید، روی نماد نگهدارید.
نمونههای کد و برنامههای نمایشی
- برنامه نمایشی جلسه AndroidX Media3 (تلفن همراه و WearOS)
- کنشهای سفارشی
- اعلان واسط کاربر سیستم، MediaButton/BT
- کنترل بازپخش «دستیار Google»
- UAMP: Android Media Player (شاخه media3) (تلفن همراه، AutomotiveOS)
- اعلان رابط کاربری سیستم، MediaButton/BT، ازسرگیری بازپخش
- کنترل بازپخش «دستیار Google»/ WearOS
- AutomotiveOS: فرمان سفارشی و ورود به سیستم