ان كنت مطور اندرويد فـ بالتأكيد قد واجهتك مشكلة Force close في احد تطبيقاتك والتي تنتج تنيجة لوجود خطأ برمجي لم تقم بمعالجته او لوجود Bug في تطبيقك, في هذه المقالة سنوضح طريقة لمعالجة هذه المشكلة.

ماسنقوم بفعله هو بعرض رسالة للمستخدم تخبره بوجود خطأ في التطبيق بدلاً من الرسالة المزعجة والتي ربما تجعلك تخسر الكثير من المستخدمين بسببها.

ExceptionHandler

سنقوم بإنشاء كلاس جديد وظيفته الاساسية هي التقاط اي خطأ في التطبيق, سيقوم الكلاس بتسجيل سِجل الخطأ بالكامل بالاضافة الى معلومات جهاز المستخدم وذلك لأن بعض الاخطأ ربما تكون بسبب جهاز المستخدم ولاعلاقة لتطبيقك بهذا الخطأ.

بعدما يقوم الكلاس بتجميع الأخطاء سنقوم باستدعاء Activity ونرسل لها السِجل بالكامل عن طريق الـ Intent (تستطيع تصميم واجهتها بنفسك والتي تخبر المستخدم بان هناك خطأ في التطبيق وتستطيع اضافة بعض الخصائص مثل ارسال الخطأ لبريدك الالكتروني او غيرها).

package com.example.forceclose;

import <span class="skimlinks-unlinked">java.io.PrintWriter</span>;
import <span class="skimlinks-unlinked">java.io.StringWriter</span>;

import <span class="skimlinks-unlinked">android.app.Activity</span>;
import android.content.Intent;
import <span class="skimlinks-unlinked">android.os.Build</span>;

public class ExceptionHandler implements
        <span class="skimlinks-unlinked">java.lang.Thread.UncaughtExceptionHandler</span> {
    private final Activity myContext;
    private final String LINE_SEPARATOR = "\n";

    public ExceptionHandler(Activity context) {
        myContext = context;
    }

    public void uncaughtException(Thread thread, Throwable exception) {
        StringWriter stackTrace = new StringWriter();
        exception.printStackTrace(new PrintWriter(stackTrace));
        StringBuilder errorReport = new StringBuilder();
        errorReport.append("************ CAUSE OF ERROR ************\n\n");
        errorReport.append(stackTrace.toString());

        errorReport.append("\n************ DEVICE INFORMATION ***********\n");
        errorReport.append("Brand: ");
        errorReport.append(<span class="skimlinks-unlinked">Build.BRAND</span>);
        errorReport.append(LINE_SEPARATOR);
        errorReport.append("Device: ");
        errorReport.append(Build.DEVICE);
        errorReport.append(LINE_SEPARATOR);
        errorReport.append("Model: ");
        errorReport.append(<span class="skimlinks-unlinked">Build.MODEL</span>);
        errorReport.append(LINE_SEPARATOR);
        errorReport.append("Id: ");
        errorReport.append(<span class="skimlinks-unlinked">Build.ID</span>);
        errorReport.append(LINE_SEPARATOR);
        errorReport.append("Product: ");
        errorReport.append(Build.PRODUCT);
        errorReport.append(LINE_SEPARATOR);
        errorReport.append("\n************ FIRMWARE ************\n");
        errorReport.append("SDK: ");
        errorReport.append(<span class="skimlinks-unlinked">Build.VERSION.SDK</span>);
        errorReport.append(LINE_SEPARATOR);
        errorReport.append("Release: ");
        errorReport.append(Build.VERSION.RELEASE);
        errorReport.append(LINE_SEPARATOR);
        errorReport.append("Incremental: ");
        errorReport.append(Build.VERSION.INCREMENTAL);
        errorReport.append(LINE_SEPARATOR);

        Intent intent = new Intent(myContext, <span class="skimlinks-unlinked">AnotherActivity.class</span>);
        intent.putExtra("error", errorReport.toString());
        myContext.startActivity(intent);

        <span class="skimlinks-unlinked">android.os.Process.killProcess(android.os.Process.myPid</span>());
        <span class="skimlinks-unlinked">System.exit(10</span>);
    }

}

استخدام ExceptionHandler

تستطيع استخدام الكلاس بالاعلى لالتقاط الاخطاء في اي Activity موجودة في تطبيقك او تستطيع تطبيقها على مستوى التطبيق بالكامل في كلاس Application من خلال اضافة السطر التالي في ميثود OnCreate وبعد سطر الـ super

Thread.setDefaultUncaughtExceptionHandler(new ExceptionHandler(this));

الشكل النهائي للـ Activity سيكون كالاسفل:

public class MainActivity extends AppCompatActivity {`` @Override`` protected void onCreate(Bundle savedInstanceState) {`` super.onCreate(savedInstanceState);`` Thread.setDefaultUncaughtExceptionHandler(new ExceptionHandler(this));`` setContentView(R.layout.activity_main);`` }``}