توسعه اپلیکیشن: چگونه میتوان 13 خطای رایج در اندروید را برطرف کرد؟ – بخش دوم
در مطلب قبلی به برخی از خطاهای رایج در اندروید پرداخته شد و در ادامه به سایر خطاها و روش برطرف کردن آنها پرداخته خواهد شد، با ما همراه باشید.
5. INSTALL_FAILED_INSUFFICIENT_STORAGE
این خطا در زمان نصب پروژه به این معناست که گوشی حافظه کافی ندارد. در صورتی که پروژه خود را بر روی یک AVD نصب کرده اید، باید این موضوع را بررسی کنید که چقدر فضا به آن AVD خاص اختصاص داده اید:
- AVD Manager را اجرا کنید
- AVD موردنظر را پیدا کرده و بر روی آیکون Edit this AVD کلیک کنید
- در پنجره باز شده، بر روی Show Advanced Settings کلیک کنید
- به قسمت Memory and Storage مراجعه کنید
این بخش انواع مختلفی از حافظه را که به این AVD خاص اختصاص داده اید فهرست میکند. اگر هریک از مقادیر کم هستند باید آنها را افزایش دهید تا در حد حافظه در دسترس در اسمارت فون یا تبلت اندرویدی شما باشد.
- RAM. حجم رم در دسترس برای گوشی شبیه سازی شده
- VM Heap. مقدار فضای پشته (حافظه) که به VM (ماشین مجازی) اسمارت فون یا گوشی شبیه سازی شده اختصاص داده شده است
- Internal Storage. حجم حافظه جدانشدنی در دسترس برای گوشی شبیه سازی شده میباشد
- SD card. حجم حافظه جداشدنی در دسترس میباشد. چنانچه بخواهید با اندروید استودیو اس دی کارت را کنترل کنید، Studio-managed را انتخاب کرده و حجم دلخواه برای اس دی کارت مجازی را وارد کنید (حداقل حجم پیشنهادی 100 مگابایت میباشد). علاوه بر این میتوانید با انتخاب External file و مشخص کردن مکانی که مایل به استفاده از آن هستید نیز، فضای اس دی کارت را کنترل کنید.
چنانچه حافظه AVD کم نیست یا میخواهید اپلیکیشن را بر روی اسمارت فون یا تبلت واقعی نصب کنید، در این شرایط این خطا به معنای این است که اپلیکیشن کامپایل شده شما حجم بسیار بالایی دارد. اپلیکیشنی که هنگام نصب حجم زیادی از حافظه را به خود اختصاص دهد، در آینده نیز خوب کار نمیکند.
برای کم کردن حجم APK، از تکنیک های زیر بهره بگیرید:
- از ProGuard برای حذف کلاس ها، فیلدها، متدها و ویژگی های استفاده نشده استفاده کنید.
برای فعال سازی ProGuard باید فایل build.gradle را باز کرده و موارد زیر را به آن اضافه کنید:
buildTypes {
release {
//Enable ProGuard//
minifyEnabled true
//Since we want to reduce our APK size as much as possible, I’m using the settings from the proguard-android-optimize.txt file//
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
- استفاده از ابزار appt برای بهینه سازی drawableها با استفاده از فشرده سازی بدون اتلاف، یا استفاده از برنامه ای که برای کاهش اندازه فایل های PNG مانند از zopflipng، pngcrush، OptiPNG، TinyPNG یا pngquant یا فایل های JPEG مانند packJPG طراحی شده است. جایگزین کردن فایل های PNG و JPEG با فرمت WebP نیز ایده خوبی میباشد.
- تمامی عملیات مربوط به دیباگ را نیز از نسخه نهایی اپلیکیشن حذف کنید. اندروید برای اجرا به این اطلاعات نیازی ندارد، بنابراین این داده ها تنها فضای اضافی اشغال میکنند.
- بررسی کنید که پروژه شما هیچگونه منبع تکراری نداشته باشد. حتی منابع کم حجم مانند رشته های تکراری نیز در افزایش حجم APK سهیم اند.
- از Lint برای تشخیص منابعی که در کد به آن ارجاع داده نشده استفاده کرده و تمامی منابع این چنینی را حذف کنید. برای اجرای Lint باید از نوار ابزار اندروید استودیو، Analyze> Inspect Code را انتخاب کنید.
- با افزودن shrinkResources true به فایل build.gradle، فشرده سازی منبع را فعال کنید.
- اگر میخواهید نسخه های مختلفی از یک عکس را استفاده کنید، به جای افزودن نسخه های متعدد از عکس به پروژه، از یک عکس اصلی استفاده کرده و آن را در ران تایم شخصی سازی نمایید. برای مثال میتوانید با استفاده از android:tint و tintMode رنگ های مختلفی بر روی عکس اعمال کنید یا با استفاده از android:fromDegrees، android:toDegrees، android:pivotX و android:pivotY عکس را بچرخانید.
کتابخانه های خود را بهینه سازی کنید و کتابخانه های غیرضروری را از پروژه خود حذف کنید. اگر میخواهید از یک کتابخانه حجیم استفاده کنید، باید ببینید آیا راهی برای بهینه سازی این کتابخانه برای محیط موبایل وجود دارد یا خیر، زیرا معمولا کد کتابخانه اکسترنال برای موبایل نوشته نشده است. در ذهن داشته باشید که بسیاری از کتابخانه ها دربرگیرنده حجم زیادی از رشته های محلی شده میباشند. اگر اپلیکیشن شما از این کتابخانه ها پشتیبانی نمیکند، باید به Gradle بگویید که این رشته ها در فایل APK کامپایل شده درج نکند. جهت تعیین زبان هایی که اپلیکیشن پشتیبانی میکند، فایل build.gradle را باز کرده و از resconfigsattribute استفاده کنید، در مثال زیر مشخص شده که تنها مایل به درج رشته های انگلیسی در پروژه خود هستیم.
android {
defaultConfig {
resConfigs "en"
- شاید APK شما دربرگیرنده حجم زیادی محتواست که کاربر باید دانلود کند، اما این محتوا مورد استفاده قرار نمی گیرد، برای مثال یک گوشی با نمایشگر hdpi از xxxhdpi استفاده چندانی نمیکند. یکی از موثرترین روش ها برای کاهش اندازه APK جدا کردن آن به چندین APK میباشد، با این کار وقتی کاربر اپلیکیشن را دانلود کند، تنها APK را دریافت خواهد کرد که شامل کد و منابعی است که برای یک گوشی خاص مناسب است.
6. ActivityNotFoundException
خطای ActivityNotFoundException زمانی نمایش داده میشود که فراخوانی (startActivity(Intent یا یکی از نسخه های آن به دلیل اینکه Activity قادر به اجرای Intent موردنظر نیست، شکست میخورد.
در صورتی که اینتنت را در منیفست مشخص نکنید با خطای ActivityNotFoundException مواجه میشوید، لذا باید فایل منیفست را باز کرده و مطمئن شوید که تمامی اکتیویتی های خود را تعریف کرده اید و هر اکتیویتی را به درستی و با نام کامل کلاس یا یک نقطه به عنوان مخفف نام پکیج تعریف کرده اید.
برای مثال هر دو مورد زیر معتبر میباشند:
<activity android:name=".MainActivity">
<activity android:name="com.jessicathornsby.myapplication.MainActivity">
چنانچه مشکل به فایل منیفست مربوط نباشد، امکان دارد بعد از جابجا کردن کلاس Activity از یک پکیج به پکیج دیگر به این خطا برخورده باشید، در این شرایط باید پروژه را پاک کرده و ری بیلد کنید.
وجود خطا در Activity که موجب عدم بارگذاری صحیح آن میشود نیز دلیل دیگر این خطا در اندروید است، برای تست این موضوع باید کد اینتنت را در یک بلوک try-catch قرار دهید:
try {
//Your code here//
} catch ( ActivityNotFoundException e) {
e.printStackTrace();
}
مجددا اپلیکیشن خود را اجرا کرده و در Logcat Monitor اندروید استودیو موضوع را بررسی کنید و ببینید آیا حالت های استثنایی وجود دارند که اکتیویتی تارگت را از ساخته شدن بازمیدارند. با برطرف کردن مشکل، خطای ActivityNotFoundException نیز حل میشود.
7. ClassCastException
خطای ClassCastException به قابلیت تغییر نوع در جاوا مربوط است که شما را قادر به تبدیل متغیرهایی از یک نوع به دیگری میکند. زمانی به خطای ClassCastException برمیخورید که یک آبجکت را به کلاسی که آن آبجکت نمونه ای از آن نیست تبدیل کنید. برای مثال هر دو قطعه کد زیر به خطای ClassCastException می انجامند:
Object x = new Integer(0);
System.out.println((String)x);
ImageView image = (ImageView)context.findViewById(R.id.button);
این پیام دربرگیرنده اطلاعاتی درباره خط کدی است که منجر به خطای ClassCastException شده، بنابراین باید به آن بخش از پروژه خود رفته و ببینید چه آبجکت هایی در آنجا تبدیل میشوند و هر گونه عدم مطابقت را برطرف کنید.
اگر نتوانستید این کار را انجام دهید، باید ببینید آیا اخیرا Views را از فایل های منبع لی اوت جابجا کرده اید یا خیر، زیرا به گفته برخی از کاربران، آنها با چیدمان مجدد Views به این خطا برخورده اند. برای این کار باید در اندروید استودیو فایل های لی اوت را مجددا تولید کرده و عملیات clean/rebuid را انجام دهید. این کار اندروید استودیو را مجبور میکند تا تغییرات اخیر اعمال شده در لی اوت را ثبت کند که موجب برطرف شدن خطا خواهد شد.
8. NullPointerException
در جاوا وقتی یک متغیر رفرنس تعریف میکنید، در واقع یک اشاره گر به آبجکت میسازید. میتوانید با تخصیص مقدار خالی به رفرنس آبجکت، تعیین کنید که آبجکت در حال حاضر به یک بخش نامشخصی از داده اشاره میکند. مقادیر خالی برای کدنویسی برخی الگوهای طراحی مورد استفاده قرار میگیرند، اما اگر خطا (NullPointerException (NPE را مشاهده کردید، به این معناست که خواسته اید از یک رفرنس استفاده کنید که به یک مقدار خالی اشاره میکند. از آنجا که در مکان رفرنس داده شده کدی برای اجرا وجود ندارد، با NPE مواجه میشوید.
NPE اطلاعات جایی را که خطا وجود دارد نیز دربر میگرد، از این رو logcat Monitor باید شامل خط کد دقیق از مکان خطا باشد. به آن بخش از پروژه خود مراجعه کرده و رفرنسی را که مساوی خالی است پیدا کنید، سپس باید مکانی را پیدا کنید که مقدار باید در آنجا ست شود.
متد fineViewById نیز در صورتی که View موردنظر پیدا نشود، null برمیگرداند، از این رو اگر NPE در جایی اتفاق افتاده که findViewById دارید، بررسی کنید که لی اوت شامل این ویو را اینیشیالایز کرده باشید. به علاوه باید خطاهای تایپی در فراخوانی findViewById را نیز بررسی کنید، چرا که این مشکل نیز ممکن است به خطای NPE منجر شود.
برای اجتناب از NPE مطمئن شوید که پیش از استفاده، تمامی آبجکت ها اینیشایلایز شده اند و پیش از درخواست متد یا فیلد از آبجکت از عدم null بودن متغیرها نیز اطمینان حاصل کنید.
در مطلب بعدی به سایر خطاهای رایج در اندروید و روش برطرف کردن آنها خواهیم پرداخت، با ما همراه باشید.