অ্যান্ড্রয়েডে বিশ্বব্যাপী অপেশাদার হ্যান্ডলার সেট করার আদর্শ উপায় I


88

আমি আমার অ্যান্ড্রয়েড অ্যাপ্লিকেশনটিতে সমস্ত থ্রেডের জন্য একটি বিশ্বব্যাপী অপ্রয়োজনীয় হ্যান্ডলার সেট করতে চাই। সুতরাং, আমার Applicationসাবক্লাসে আমি Thread.UncaughtExceptionHandlerঅবিচ্ছিন্ন ব্যতিক্রমগুলির জন্য ডিফল্ট হ্যান্ডলার হিসাবে একটি বাস্তবায়ন সেট করেছি ।

Thread.setDefaultUncaughtExceptionHandler(
                new DefaultExceptionHandler(this));

আমার বাস্তবায়নে, আমি একটি AlertDialogযথাযথ ব্যতিক্রম বার্তা প্রদর্শন করার চেষ্টা করছি ।

তবে, এটি কাজ করে বলে মনে হচ্ছে না। যখনই, কোনও থ্রেডের জন্য একটি ব্যতিক্রম ছুঁড়ে দেওয়া হয় যা হ্যান্ডেল করা হয় না, তখন আমি স্টক পেয়ে যাই, ওএস-ডিফল্ট ডায়ালগ ("দুঃখিত! -অবশ্যক-বন্ধ হয়েছে - অপ্রত্যাশিতভাবে ডায়ালগ")।

বাদ পড়া ব্যতিক্রমগুলির জন্য একটি ডিফল্ট হ্যান্ডলার সেট করার সঠিক এবং আদর্শ উপায় কী?


4
আপনি কি দয়া করে এর জন্য কোডটি ভাগ করতে পারেন ...
কোড_লাইফ

4
আপনি যদি নিজের ব্যতিক্রমগুলি লগ করতে চান তবে acra.ch এ দেখুন । এসিআরএ আপনাকে একটি গুগল-ডক্সে বা ই-মেইলের মাধ্যমে আপনাকে ত্রুটি-প্রতিবেদনগুলি প্রেরণের অনুমতি দেয়।
আলেকজান্ডার পাচা

4
@ আলেকজান্ডার বা আপনি কেবল অ্যান্ড্রয়েডের জন্য গুগল অ্যানালিটিকাগুলি ব্যবহার করতে পারেন এবং আপনি যে সমস্ত ব্যতিক্রম চান তা লগ করতে পারেন ...
ইগোরগানপলস্কি

উত্তর:


24

আপনার যা করা দরকার তা হ'ল। (নিশ্চিত হয়ে নিন যে আপনি পরে প্রক্রিয়াটি থামিয়ে দিয়েছেন - জিনিসগুলি অনিশ্চিত অবস্থায় থাকতে পারে))

অ্যান্ড্রয়েড হ্যান্ডলারটি এখনও কল হচ্ছে কিনা তা যাচাই করার জন্য প্রথম জিনিসটি। এটি সম্ভব যে আপনার সংস্করণটি বলা হচ্ছে কিন্তু মারাত্মকভাবে ব্যর্থ হচ্ছে এবং প্রক্রিয়া ক্র্যাশ হওয়ার পরে সিস্টেম_সার্ভার একটি জেনেরিক ডায়ালগ দেখায়।

আপনার হ্যান্ডলারের শীর্ষে কিছু লগ বার্তা যুক্ত করুন এটি দেখতে পাচ্ছে কিনা। GetDefaultUncaughtExceptionHandler থেকে ফলাফলটি মুদ্রণ করুন এবং তারপরে ক্র্যাশ হওয়ার জন্য একটি অচল ব্যতিক্রম নিক্ষেপ করুন। কি চলছে তা দেখার জন্য লগক্যাট আউটপুটটিতে নজর রাখুন।


10
"ত্রুটিটি পরিচালনা করার পরে ক্র্যাশ ঘটানোর জন্য একটি অচেনা ব্যতিক্রম ছোঁড়া" এখনও গুরুত্বপূর্ণ। আমি এটি অভিজ্ঞ। আমি ব্যতিক্রমটি পরিচালনা করার পরে আমার অ্যাপ্লিকেশনটি লক হয়ে গেছে এবং কোনও অযৌক্তিক ব্যতিক্রম ছুঁড়ে না ফেলে।
ওয়ানওয়ার্ল্ড

@ ওনওয়ার্ল্ড জ্যাপ এখানে একই - কমপক্ষে লকিং অংশের জন্য - মনে হচ্ছে অ্যাপটি সর্বোপরি বিধ্বস্ত হওয়ার হাত থেকে "সংরক্ষণ" করার কোনও উপায় নেই।
এজেন্টকনফফ

@ জয়নোডিস আমি এই প্রশ্নের একটি হালকা অফ-টপিক উত্তর পোস্ট করেছি যা সমালোচকদের একটি লিঙ্ক দেয় - আমার কাছে মনে হয় তাদের একটি বৈশিষ্ট্য রয়েছে যা আপনাকে অ্যাপটিকে সর্বোপরি ক্রাশ হতে "সংরক্ষণ" করতে দেয় allows নিশ্চিত নয় - আমি কেবল বিনামূল্যে সংস্করণ এটিএম ব্যবহার করছি।
রিচার্ড লে মেসুরিয়ার

@ রিচার্ডলিমেসুরিয়ার ইঙ্গিতটির জন্য ধন্যবাদ - আমি এটি যাচাই করব :)!
এজেন্টকনফফ

অদ্ভুত !!! আমি যদি আমার তীব্রতা নিয়ে ব্যতিক্রম হ্যান্ডেল করি তবে অবাক করা কল্পনা। কোন ধারণা.
হিরেন দাবি

12

আমি অ্যান্ড্রয়েড ক্র্যাশগুলির কাস্টম হ্যান্ডলিংয়ের সহজ সমাধান পোস্ট করেছি । এটি সামান্য হ্যাকি তবে এটি সমস্ত অ্যান্ড্রয়েড সংস্করণে (ললিপপ সহ) কাজ করে।

প্রথমে কিছুটা তত্ত্ব। অ্যান্ড্রয়েডে অপ্রকাশিত ব্যতিক্রম হ্যান্ডলারটি ব্যবহার করার সময় মূল সমস্যাগুলি মূল (ওরফে ইউআই) থ্রেডে ফেলে দেওয়া ব্যতিক্রমগুলি নিয়ে আসে। এবং এখানে কেন। যখন অ্যাপ্লিকেশন সিস্টেমটি অ্যাক্টিভিটিথ্রেড.মাইন পদ্ধতিতে কল করে যা আপনার অ্যাপ্লিকেশনটির মূল লুপ প্রস্তুত করে এবং শুরু করে :

public static void main(String[] args) {
  …
  …
    Looper.prepareMainLooper();
  …
    Looper.loop();
    throw new RuntimeException("Main thread loop unexpectedly exited");
}

মেইন লুপার ইউআই থ্রেডে পোস্ট হওয়া বার্তাগুলি (ইউআই রেন্ডারিং এবং ইন্টারঅ্যাকশন সম্পর্কিত সমস্ত বার্তা সহ) প্রক্রিয়াকরণের জন্য দায়বদ্ধ। যদি ইউআই থ্রেডে কোনও ব্যতিক্রম ছুঁড়ে দেওয়া হয় তবে এটি আপনার ব্যতিক্রম হ্যান্ডলার দ্বারা ধরা পড়বে, তবে আপনি loop()পদ্ধতি ছাড়ার কারণে আপনি কোনও সংলাপ বা ক্রিয়াকলাপ প্রদর্শন করতে পারবেন না কারণ ইউআই বার্তাগুলি প্রক্রিয়া করার মতো কেউ নেই left তোমার জন্য.

প্রস্তাবিত সমাধানটি বেশ সহজ। আমরা Looper.loopআমাদের নিজস্ব পদ্ধতি চালাই এবং চেষ্টা-ব্লক দিয়ে এটিকে ঘিরে। কোনও ব্যতিক্রম ধরা পড়লে আমরা যেমনটি চাই তেমন প্রক্রিয়া করি (উদাহরণস্বরূপ আমাদের কাস্টম প্রতিবেদনের ক্রিয়াকলাপ শুরু করুন) এবং Looper.loopআবার কল পদ্ধতিতে।

নিম্নলিখিত পদ্ধতিটি এই কৌশলটি দেখায় (এটি Application.onCreateশ্রোতার কাছ থেকে কল করা উচিত ):

private void startCatcher() {
    UncaughtExceptionHandler systemUncaughtHandler = Thread.getDefaultUncaughtExceptionHandler();

    // the following handler is used to catch exceptions thrown in background threads
    Thread.setDefaultUncaughtExceptionHandler(new UncaughtHandler(new Handler()));

    while (true) {
        try {
            Looper.loop();
            Thread.setDefaultUncaughtExceptionHandler(systemUncaughtHandler);
            throw new RuntimeException("Main thread loop unexpectedly exited");
        } catch (Throwable e) {
            showCrashDisplayActivity(e);
        }
    }
}

আপনি দেখতে পাচ্ছেন যে অনাবৃত ব্যতিক্রম হ্যান্ডলারটি কেবল ব্যাকগ্রাউন্ড থ্রেডে ফেলে দেওয়া ব্যতিক্রমগুলির জন্য ব্যবহৃত হয়। নিম্নলিখিত হ্যান্ডলার সেই ব্যতিক্রমগুলি ধরে এবং তাদের ইউআই থ্রেডে প্রচার করে:

static class UncaughtHandler implements UncaughtExceptionHandler {

    private final Handler mHandler;

    UncaughtHandler(Handler handler) {
        mHandler = handler;
    }

    public void uncaughtException(Thread thread, final Throwable e) {
        mHandler.post(new Runnable() {
            public void run() {
                throw new BackgroundException(e);
            }
        });
    }
}

এই কৌশলটি ব্যবহার করে এমন একটি প্রকল্প যা আমার গিটহাব রেপোতে উপলব্ধ: https://github.com/idolon-github/android-crash-catcher


যেহেতু কেউ অনুমান করতে পারে, এইভাবে কাস্টম ত্রুটি ডায়লগ প্রদর্শন করা সম্ভব নয়, তবে ব্যবহারকারীকে ব্যতিক্রম উপেক্ষা করতে এবং অ্যাপ্লিকেশনটির সাথে কাজ চালিয়ে যাওয়ার অনুমতি দেওয়া (এবং এটি প্রকাশিত অ্যাপ্লিকেশনগুলির জন্য খারাপ ধারণা বলে মনে হলেও এটি হতে পারে) একটি ডিবাগ বা পরীক্ষার সেশনের সময় বেশ সুবিধাজনক)।
আইডলন

হাই, যদিও এটি অবিচ্ছিন্ন ব্যতিক্রমগুলি ধরতে কাজ করে তবে কোনও কারণে, এই কোডটি সর্বদা ব্যতিক্রম ছুঁড়ে মারছে। প্রাথমিকভাবে আমি যদিও এটি রানটাইম এক্সসেপশন লাইনের কারণে হয়েছিল যে আপনি স্টার্টগ্যাচার পদ্ধতিতে এসেছিলেন তবে এটি অপসারণের পরেও আমি ব্যতিক্রম পাচ্ছি। আমি নিশ্চিত নই যে এটি কোনও প্রয়োজনীয় জিনিস কিনা। যাইহোক আমি ব্যতিক্রম যে পেতে java.lang.RuntimeException: Performing pause of activity that is not resumed। আমি বিশ্বাস করি যখন আমি নিজের লুপটি চালু করার চেষ্টা করছি তখন সিস্টেমটি যে ক্রিয়াকলাপটি শুরু হতে চলেছে তাতে বিরতি দেয়? আমি নিশ্চিত না তবে কোনও সাহায্যের প্রশংসা হবে। ধন্যবাদ
sttaq

এছাড়াও আমি যদি স্টার্টগ্যাচারটি অপসারণ করি অর্থাৎ আপনার কোড ছাড়াই অ্যাপটি চালাও তবে কোনও ব্যতিক্রম ছাড়াই সবকিছু ঠিকঠাক কাজ করে।
sttaq

@sttaq আপনি Android এর কোন সংস্করণ ব্যবহার করেন?
আইডলন

আমি মনে করি আমি এটি 2.3.x
sttaq

3

আমি অক্ষম করার জন্য মনে করি যে আপনার অবিচ্ছিন্ন ধারণা () পদ্ধতিতে পূর্ববর্তী হ্যান্ডেল.আরকুটএক্সেপশন () কল করবেন না যেখানে পূর্ববর্তী হ্যান্ডলার সেট করেছে

previousHandler = Thread.getDefaultUncaughtExceptionHandler();

2

এফডব্লিউআইডাব্লু আমি জানি এটি সামান্য অফ-টপিক, তবে আমরা সাফল্যের সাথে ক্রিট্রিসিজমের মুক্ত পরিকল্পনাটি ব্যবহার করছি । এগুলি ব্যতিক্রমগুলি পরিচালনা করার মতো কিছু প্রিমিয়াম বৈশিষ্ট্যও সরবরাহ করে যাতে অ্যাপটি ক্রাশ হয় না।

নিখরচায় সংস্করণে, ব্যবহারকারী এখনও ক্র্যাশটি দেখতে পান তবে কমপক্ষে আমি ইমেল এবং স্ট্যাক ট্রেস পাই।

আমরা আইওএস সংস্করণও ব্যবহার করি (তবে আমি আমার সহকর্মীদের কাছ থেকে শুনেছি যে এটি ততটা ভাল নয়)।


এখানে একই রকম প্রশ্ন:


1

আপনি কল না করা পর্যন্ত এটি কাজ করে না

android.os.Process.killProcess(android.os.Process.myPid());

আপনার আনকডএক্সেপশনহ্যান্ডলারের একেবারে শেষে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.