9

私はSamsungS3を除いて、試したすべての電話で問題なく動作するAndroidアプリを作成しました。何が起こるかというと、私のアプリの実行中に、他のバックグラウンドプロセス(つまり、他のアプリ)が停止し始めます。たとえば、アプリをしばらく使用すると、ライブ壁紙が停止し、ユーザーはアプリを終了した後、携帯電話の背景が黒くなります。そして最後に、それをしばらく使用した後、私のアプリもOSによって強制終了されます。イライラするのは、ログにエラーメッセージが表示されないことです。これにより、問題が正確に何であるかについてのヒントが得られます。

これはSamsungS3でのみ発生します(たとえば、S2では発生しません)。

私のアプリは非常にメモリを大量に消費するため(Webから大量の画像を読み込んでいるため)、メモリに関連していると思いましたが、ログに「メモリなし」のエラーは表示されません。

また、使用しているHTTPフレームワークにバグがあるのではないかと思ったので、Apache HttpComponentsからjava.net.HttpURLConnectionに切り替えましたが、役に立ちませんでした。

これが発生している理由についてのアイデアや、デバッグ方法のヒントをいただければ幸いです。

これは、いくつかのバックグラウンドプロセスが停止していることを示すログからの抜粋です(たとえば、ライブ壁紙)。

01-07 01:57:37.245: I/InputDispatcher(2296): Delivering touch to current input target: action: 0x1
01-07 01:57:37.505: D/dalvikvm(29490): GC_FOR_ALLOC freed 1535K, 17% free 28032K/33735K, paused 71ms, total 71ms
01-07 01:57:37.580: D/dalvikvm(6718): WAIT_FOR_CONCURRENT_GC blocked 0ms
01-07 01:57:37.620: D/dalvikvm(6718): GC_EXPLICIT freed 91K, 9% free 17663K/19399K, paused 3ms+5ms, total 40ms
01-07 01:57:38.190: I/InputReader(2296): Touch event's action is 0x0 (deviceType=0) [pCnt=1, s=0.428 ]
01-07 01:57:38.190: I/InputDispatcher(2296): Delivering touch to current input target: action: 0x0
01-07 01:57:38.190: I/InputDispatcher(2296): Delivering touch to current input target: action: 0x0
01-07 01:57:38.190: I/InputDispatcher(2296): Delivering touch to current input target: action: 0x0
01-07 01:57:38.190: I/InputDispatcher(2296): Delivering touch to current input target: action: 0x0
01-07 01:57:38.190: I/InputDispatcher(2296): Delivering touch to current input target: action: 0x0
01-07 01:57:38.335: I/InputReader(2296): Touch event's action is 0x1 (deviceType=0) [pCnt=1, s=]
01-07 01:57:38.335: I/InputDispatcher(2296): Delivering touch to current input target: action: 0x1
01-07 01:57:38.335: I/InputDispatcher(2296): Delivering touch to current input target: action: 0x1
01-07 01:57:38.335: I/InputDispatcher(2296): Delivering touch to current input target: action: 0x1
01-07 01:57:38.750: D/dalvikvm(29490): GC_FOR_ALLOC freed 1688K, 18% free 27981K/33735K, paused 114ms, total 114ms
01-07 01:57:39.695: W/PowerManagerService(2296): Timer 0x3->0x3|0x0
01-07 01:57:39.700: D/PowerManagerService(2296): setTimeoutLocked::SmartSleep : after19500
01-07 01:57:39.930: I/InputReader(2296): Touch event's action is 0x0 (deviceType=0) [pCnt=1, s=0.429 ]
01-07 01:57:39.930: I/InputDispatcher(2296): Delivering touch to current input target: action: 0x0
01-07 01:57:39.930: I/InputDispatcher(2296): Delivering touch to current input target: action: 0x0
01-07 01:57:39.930: I/InputDispatcher(2296): Delivering touch to current input target: action: 0x0
01-07 01:57:39.930: I/InputDispatcher(2296): Delivering touch to current input target: action: 0x0
01-07 01:57:39.930: I/InputDispatcher(2296): Delivering touch to current input target: action: 0x0
01-07 01:57:40.020: D/DeviceInfo(2296): SysScope Service has unexpectedly disconnected!
01-07 01:57:40.065: I/InputReader(2296): Touch event's action is 0x1 (deviceType=0) [pCnt=1, s=]
01-07 01:57:40.065: I/InputDispatcher(2296): Delivering touch to current input target: action: 0x1
01-07 01:57:40.065: I/InputDispatcher(2296): Delivering touch to current input target: action: 0x1
01-07 01:57:40.065: I/InputDispatcher(2296): Delivering touch to current input target: action: 0x1
**01-07 01:57:40.080: I/ActivityManager(2296): Process com.android.smspush (pid 28031) (adj 1) has died.**
01-07 01:57:40.090: W/WallpaperService(2296): Wallpaper service gone: ComponentInfo{com.sec.ccl.csp.app.secretwallpaper.themetwo/com.sec.ccl.csp.app.secretwallpaper.themetwo.SecretWallpaperService}
01-07 01:57:40.125: D/KeyguardViewMediator(2296): setHidden false
**01-07 01:57:40.135: I/ActivityManager(2296): Process com.android.server.device.enterprise:remote (pid 28016) (adj 1) has died.**
**01-07 01:57:40.145: I/ActivityManager(2296): Process com.sec.ccl.csp.app.secretwallpaper.themetwo (pid 29715) (adj 1) has died.**
01-07 01:57:40.285: D/dalvikvm(29490): GC_CONCURRENT freed 1616K, 17% free 28289K/33735K, paused 27ms+21ms, total 178ms
01-07 01:57:40.285: D/dalvikvm(29490): WAIT_FOR_CONCURRENT_GC blocked 112ms
01-07 01:57:40.445: D/dalvikvm(2296): GC_CONCURRENT freed 1869K, 59% free 24186K/57991K, paused 26ms+12ms, total 197ms
01-07 01:57:40.660: D/dalvikvm(29490): GC_CONCURRENT freed 1587K, 16% free 28622K/33735K, paused 3ms+7ms, total 51ms
01-07 01:57:40.685: D/KeyguardViewMediator(2296): setHidden false
4

2 に答える 2

9

バックグラウンドプロセスが停止する主な理由は3つあります。まず、可能性の低いものから最も可能性の高いものへと始めます。

あなたはうっかりしてそれをやめるように頼んだ

厄介な状況でサービスの停止を要求する可能性のあるバグがないか、コードを確認してください。これは、サービス内またはアプリケーションの他のアクティビティ内にある可能性があります。

捕捉されなかった例外

サービスはキャッチされない例外をヒットしました。この状況では、ログに情報が表示されるはずですが、ログは長くは続かず、欠落している可能性があります。

この可能性に対処するには、次のDefaultUncaughtExceptionHandlerように設定できます。

UncaughtExceptionHandler currentHandler = Thread.getDefaultUncaughtExceptionHandler();
if (!(currentHandler instanceof DefaultExceptionHandler)) {
    // Register default exceptions handler
    Thread.setDefaultUncaughtExceptionHandler(
            new DefaultExceptionHandler(currentHandler));
}

DefaultExceptionHandler次のように一時ファイルに書き込むクラスを定義します。

public class DefaultExceptionHandler implements UncaughtExceptionHandler {
    private UncaughtExceptionHandler defaultExceptionHandler;

    public DefaultExceptionHandler(UncaughtExceptionHandler pDefaultExceptionHandler)
    {
        defaultExceptionHandler = pDefaultExceptionHandler;
    }

    public void uncaughtException(Thread t, Throwable e) {
        final Writer result = new StringWriter();
        final PrintWriter printWriter = new PrintWriter(result);
        e.printStackTrace(printWriter);
        try {
            String filename = "your_temp_filename";
            BufferedWriter bw = new BufferedWriter(new FileWriter(filename));
            bw.write(result.toString());
        bw.flush();
        bw.close();
        } catch (Exception e2) {
            e2.printStackTrace();
        }
        defaultExceptionHandler.uncaughtException(t, e);        
    }
}

AndroidOSがサービスの停止を要求しました

あなたの説明に基づくと、これは最も可能性の高い原因であり、あなたがそれを制御することができない原因です。

追加のリソースが必要な場合、またはサービスの実行時間が長すぎるとAndroidが判断した場合に、Androidがアプリケーションを強制終了するのを防ぐ方法はありません。サービスが強制終了されるまでに許可される時間は、割り当てられたリソース(つまり、画像のメモリ要件が画面サイズによって変化する)と使用可能なリソースに依存するため、デバイスごとに変わる可能性があります。

この場合、あなたができる唯一の合理的なことは、foreground service以下を使用してサービスを開始することです。

    startForeground(int id, Notification notification);

これは、サービスにユーザーの可視性があり、サービスを強制終了する可能性が低いことをOSに通知します。いくつかのデバイスでそれを使用した私の経験では、その間に他のいくつかのアプリケーションを使用している場合でも、サービスは中断することなく実行され続けます。

よろしく。

于 2013-01-09T22:59:28.983 に答える
7

問題を追跡しました。これは、実際には、ここで説明するTypeface.createFromAsset()メソッドによって引き起こされたメモリリークでした。リークしていたメモリはネイティブメモリ(Javaヒープ上ではない)であるため、OutOfMemory例外は発生しませんでした。

奇妙なことに、この問題はHoneycomb(3.0)以降で修正されるはずですが、私の場合は、JellyBean(4.1)を実行しているS3で発生しています。(私はいくつかのS3を試しましたが、それらすべてにこの問題があります)。JellyBeanを実行している別の電話にアクセスできる人がテストして、そこで再現されるかどうかを確認できると面白いでしょう(私が投稿したリンクはそれを再現する簡単な方法を示しています)。

于 2013-01-15T18:07:20.660 に答える