致命信号16(SIGSTKFLT)意外发生

时间:2014-01-14 00:36:20

标签: android android-asynctask signals fatal-error

今天我遇到了一个奇怪的问题。 我在三台设备上安装了我的应用程序

  1. 华硕Transformer Pad Infinity TF700T
  2. 三星I9082 Galaxy Grand Duos
  3. LG Optimus L7 II Dual p715
  4. 首先,我在Eclipse模式下使用所有这些设备运行我的应用程序。没关系。

    然后,我以通常的方式运行我的应用程序(在设备上)。就这样,我所有的坏事都已经开始了。对于1和2设备都可以。但是3个设备没有像我预期的那样工作。 LogCat向我展示了以下致命错误:

      

    01-14 01:36:47.529:E / dalvikvm(11294):threadid = 1:卡在上面   threadid = 14,放弃01-14 01:36:47.529:A / libc(11294):致命信号   16(SIGSTKFLT)位于0x00002c1e(代码= -6),线程11315(AsyncTask#4)

    我真的无法理解,发生了什么以及为什么1和2设备都能正常工作,但第3设备没有正常工作。

    有人能解释一下,这个错误意味着什么以及如何纠正这个错误?

    UPD1 我不使用NDK呼叫和任何第三方库。

    UPD2 导致错误的大代码片段(我在这里包含所有事件调用绘制过程并停止它):

    //I included all imports for sure that I don't use nothing instead of standard things
    import java.io.File;
    import java.io.FileFilter;
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.ArrayList;
    import java.util.List;
    import android.content.BroadcastReceiver;
    import android.content.Context;
    import android.content.Intent;
    import android.content.IntentFilter;
    import android.content.SharedPreferences;
    import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
    import android.content.res.Configuration;
    import android.content.res.Resources;
    import android.graphics.Bitmap;
    import android.graphics.Bitmap.Config;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Matrix;
    import android.graphics.Paint;
    import android.graphics.Path;
    import android.graphics.Region;
    import android.graphics.drawable.Drawable;
    import android.os.AsyncTask;
    import android.os.Build;
    import android.os.Handler;
    import android.service.wallpaper.WallpaperService;
    import android.util.DisplayMetrics;
    import android.util.Log;
    import android.view.Display;
    import android.view.GestureDetector;
    import android.view.GestureDetector.SimpleOnGestureListener;
    import android.view.MotionEvent;
    import android.view.SurfaceHolder;
    import android.view.WindowManager;
    
    public class MyLiveWallpaper extends WallpaperService {
        public static final String CONFIGS = "configs";
        private WallpaperEngine we;
    
        @Override
        public void onCreate() {
                super.onCreate();
        }
    
        @Override
        public void onDestroy() {
                super.onDestroy();
                if(we.myDrawTask!=null){
                        we.myDrawTask.cancel(false);
                }
        }
    
        @Override
        public Engine onCreateEngine() {
                we = new WallpaperEngine();
                return we;
        }
    
        //DeviceScreenSize is some class where I just incapsulate screen width, height and depth obtained in getScreenSize() method
        DeviceScreenSize dss = new DeviceScreenSize(0, 0, 0);
    
        class WallpaperEngine extends Engine implements
                        OnSharedPreferenceChangeListener {
                //Some definitions below
                ............................
                public DrawTask myDrawTask = null;
                ............................
                //Some definitions above
    
                WallpaperEngine() {
                        ..............
                        doubleTapDetector = new GestureDetector(HDLiveWallpaper.this,
                                        new SimpleOnGestureListener() {
                                @Override
                                public boolean onDoubleTap(MotionEvent e) {
                                        if (mTouchEvents) {
                                                mLastDrawTime = 0;
                                                if(myDrawTask!=null){
                                                        myDrawTask.stopAnimationFlag = true;
                                                }
                                                else{
                                                        myDrawTask = new DrawTask(getSurfaceHolder(), mPaint);
                                                        myDrawTask.execute();
                                                }
                                                return true;
                                        }
                                        return false;
                                }
                        });
                }
    
                @Override
                public void onCreate(SurfaceHolder surfaceHolder) {
                        super.onCreate(surfaceHolder);
                        // Register receiver for media events
                        IntentFilter filter = new IntentFilter();
                        filter.addAction(Intent.ACTION_MEDIA_BAD_REMOVAL);
                        filter.addAction(Intent.ACTION_MEDIA_CHECKING);
                        filter.addAction(Intent.ACTION_MEDIA_MOUNTED);
                        filter.addAction(Intent.ACTION_MEDIA_EJECT);
                        filter.addAction(Intent.ACTION_MEDIA_NOFS);
                        filter.addAction(Intent.ACTION_MEDIA_REMOVED);
                        filter.addAction(Intent.ACTION_MEDIA_SHARED);
                        filter.addAction(Intent.ACTION_MEDIA_UNMOUNTED);
                        filter.addDataScheme("file");
                        mReceiver = new BroadcastReceiver() {
                                @Override
                                public void onReceive(Context context, Intent intent) {
                                        String action = intent.getAction();
                                        if (action.equals(Intent.ACTION_MEDIA_MOUNTED) || action.equals(Intent.ACTION_MEDIA_CHECKING)) {
                                                mStorageReady = true;
                                                setTouchEventsEnabled(true);
    
                                                if(myDrawTask!=null){
                                                        myDrawTask.cancel(false);
                                                }
                                                myDrawTask = new DrawTask(getSurfaceHolder(), mPaint);
                                                myDrawTask.execute();
    
                                        } else {
                                                mStorageReady = false;
                                                setTouchEventsEnabled(false);
                                                if(myDrawTask!=null) myDrawTask.cancel(false);
                                        }
                                }
                        };
                        registerReceiver(mReceiver, filter);
    
                        // Register receiver for screen on events
                        mScreenOnReciever = new BroadcastReceiver() {
                                @Override
                                public void onReceive(Context context, Intent intent) {
                                        System.out.println(Intent.ACTION_SCREEN_ON);
                                        if (mScreenWake) {
                                                mLastDrawTime = 0;
                                        }
                                        if(myDrawTask!=null){
                                                myDrawTask.cancel(false);
                                        }
                                        myDrawTask = new DrawTask(getSurfaceHolder(), mPaint);
                                        myDrawTask.execute();
                                }
                        }; 
                        registerReceiver(mScreenOnReciever, new IntentFilter(Intent.ACTION_SCREEN_ON));
    
                        mScreenOffReciever = new BroadcastReceiver() {
                                @Override
                                public void onReceive(Context context, Intent intent) {
                                        System.out.println(Intent.ACTION_SCREEN_OFF);
                                        if (mScreenWake) {
                                                mLastDrawTime = 0;
                                        }
                                        if(myDrawTask!=null){
                                                myDrawTask.cancel(false);
                                        }
                                }
                        }; 
                        registerReceiver(mScreenOffReciever, new IntentFilter(Intent.ACTION_SCREEN_OFF));
    
                        setTouchEventsEnabled(mStorageReady);
                }
    
                @Override
                public void onDestroy() {
                        super.onDestroy();
                        mPrefs.unregisterOnSharedPreferenceChangeListener(this);
                        unregisterReceiver(mReceiver);
                        unregisterReceiver(mScreenOnReciever);
                        unregisterReceiver(mScreenOffReciever);
                        if(myDrawTask!=null){
                                myDrawTask.cancel(false);
                        }
                }
    
                @Override
                public void onVisibilityChanged(boolean visible) {
                        mVisible = visible;
                        if (visible) {
                                if(myDrawTask!=null){
                                        myDrawTask.cancel(false);
                                }
                                myDrawTask = new DrawTask(getSurfaceHolder(), mPaint);
                                myDrawTask.execute();
                                mLastDrawTime = 0;
                        } else {
                                if(myDrawTask!=null){
                                        myDrawTask.cancel(false);
                                }
                        }
                }
    
                @Override
                public void onSurfaceChanged(SurfaceHolder holder, int format,
                int width, int height) {
                        super.onSurfaceChanged(holder, format, width, height);
                        .....................
                        if (mBitmap != null) {
                                mBitmap.recycle();
                        }
    
                        if(myDrawTask!=null){
                                myDrawTask.cancel(false);
                        }
                        myDrawTask = new DrawTask(getSurfaceHolder(), mPaint);
                        myDrawTask.execute();
                }
    
                @Override
                public void onSurfaceCreated(SurfaceHolder holder) {
                        super.onSurfaceCreated(holder);
                        if(myDrawTask!=null){
                                myDrawTask.cancel(false);
                        }
                        myDrawTask = new DrawTask(getSurfaceHolder(), mPaint);
                        myDrawTask.execute();
                        mLastDrawTime = 0;
                }
    
                @Override
                public void onSurfaceDestroyed(SurfaceHolder holder) {
                        super.onSurfaceDestroyed(holder);
                        mVisible = false;
                        if(myDrawTask!=null){
                                myDrawTask.cancel(false);
                        }
                }
    
                @Override
                public void onOffsetsChanged(float xOffset, float yOffset, float xStep,
                float yStep, int xPixels, int yPixels) {
                        mXOffset = xOffset;
                        mYOffset = yOffset;
                        if(myDrawTask!=null){
                                myDrawTask.cancel(false);
                        }
                        myDrawTask = new DrawTask(getSurfaceHolder(), mPaint);
                        myDrawTask.execute();
                }
    
                @Override
                public void onTouchEvent(MotionEvent event) {
                        super.onTouchEvent(event);
                        this.doubleTapDetector.onTouchEvent(event);
                }
    
                public final Bitmap drawableToBitmap(Drawable drawable) {
                        int targetWidth = (mScroll) ? mMinWidth : dss.getWidth();
                        int targetHeight = (mScroll) ? mMinHeight : dss.getHeight();
    
                        Bitmap bitmap = Bitmap.createBitmap(targetWidth, targetHeight, Config.ARGB_8888);
    
                        Canvas canvas = new Canvas(bitmap);
                        drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
                        drawable.draw(canvas);
    
                        // Rotate
                        .....................
    
                        // Scale bitmap
                        .....................
                        return bitmap;
                }
    
                void getScreenSize() {
                        WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
                        Display d = wm.getDefaultDisplay();
                        DisplayMetrics metrics = new DisplayMetrics();
                        d.getMetrics(metrics);
    
                        // since SDK_INT = 1;
                        dss.setDeviceScreenParams(metrics.widthPixels, metrics.heightPixels, metrics.densityDpi);
    
                        // includes window decorations (statusbar bar/menu bar)
                        if (Build.VERSION.SDK_INT >= 14 && Build.VERSION.SDK_INT < 17)
                                try {
                                        dss.setDeviceScreenParams((Integer) Display.class.getMethod("getRawWidth").invoke(d), (Integer) Display.class.getMethod("getRawHeight").invoke(d), metrics.densityDpi);
                                } catch (Exception ignored) {}
    
                        // includes window decorations (statusbar bar/menu bar)
                        if (Build.VERSION.SDK_INT >= 17)
                                try {
                                        DisplayMetrics realSize = new DisplayMetrics();
                                        Display.class.getMethod("getRealMetrics", DisplayMetrics.class).invoke(d, realSize);
                                        dss.setDeviceScreenParams(realSize.widthPixels, realSize.heightPixels, realSize.densityDpi);
                                } catch (Exception ignored) {}
                }
    
                //
                // ************************
                // DRAW AND ANIMATION TASK
                // ************************
                //
                public class DrawTask extends AsyncTask<Void, Void, Void> {
                        private final SurfaceHolder _surfaceHolder;
                        private Paint myPaint;
                        boolean CancelFlag = false, stopAnimationFlag = false;
    
                        //HANDLERS
                        private final Handler mDrawHandler = new Handler(){
                                public void handleMessage(android.os.Message msg) { };
                        };
    
                        //WORKERS
                        private final Runnable mDrawWorker = new Runnable() {
                                public void run() {
                                        if (mDuration > 0)
                                        {
                                                drawFrame();
                                        }
                                }
                        };
    
                        DrawTask(SurfaceHolder holder, Paint paint){
                                _surfaceHolder = holder;
                                myPaint = paint;
                                CancelFlag = false;
                        }
    
                        SurfaceHolder getSurfHolder(){
                                return _surfaceHolder;
                        }
    
                        Paint getPaint(){
                                return myPaint;
                        }
    
                        @Override
                        protected void onPreExecute() {
                                super.onPreExecute();
                        }   
    
                        @Override
                        protected Void doInBackground(Void... params) {
                                drawFrame();
                                while(!CancelFlag){}
                                return null;
                        }
    
                        @Override
                        protected void onPostExecute(Void result) {
                                // TODO Auto-generated method stub
                                super.onPostExecute(result);
                        }
    
                        @Override
                        protected void onCancelled() {
                                // TODO Auto-generated method stub
                                super.onCancelled();
                                CancelFlag = true;
                        }
    
                        void drawFrame() {
                                final SurfaceHolder holder = _surfaceHolder;
                                Canvas c = null;
                                boolean getImage = false;
    
                                try {
                                        // Lock the canvas for writing
                                        c = holder.lockCanvas();
    
                                        // Do we need to get a new image?
                                        if (mBitmap == null) {
                                                getImage = true;
                                        } else if (mDuration > 0 && mLastDrawTime < System.currentTimeMillis() - mDuration) {
                                                getImage = true;
                                        } else if (mLastDrawTime == 0) {
                                                getImage = true;
                                        }
    
                                        // Get image to draw
                                        if (getImage) {
                                                // Get a list of files
                                                String[] assets_files = null;
                                                try {
                                                        assets_files = getApplicationContext().getAssets().list("");
                                                } catch (IOException e) {
                                                        e.printStackTrace();
                                                }
    
                                                List<String> str_list = new ArrayList<String>();
                                                for (int fi = 0; fi < assets_files.length; fi++) {
                                                        String ext = BitmapUtil.getExtension(assets_files[fi]);
                                                        if (ext != null) {
                                                                if (ext.equals("jpg") || ext.equals("jpeg") || ext.equals("png") || ext.equals("gif")) {
                                                                        str_list.add(assets_files[fi]);
                                                                }
                                                        }
                                                }
                                                assets_files = str_list.toArray(new String[str_list.size()]);
    
                                                // Increment counter
                                                int nFiles = assets_files.length;
                                                if (mRandom) {
                                                        int i = mIndex;
                                                        do {
                                                                mIndex = (int) (Math.random() * nFiles);
                                                        } while (nFiles > 1 && mIndex == i);
                                                } else {
                                                        if (++mIndex >= nFiles) {
                                                                mIndex = 0;
                                                        }
                                                }
    
                                                InputStream ims = null;
                                                try {
                                                        ims = getAssets().open(assets_files[mIndex]);
                                                } catch (IOException e) {
                                                        e.printStackTrace();
                                                }
                                                d = Drawable.createFromStream(ims, null);
    
                                                // Read file to bitmap
                                                mBitmap=null;
                                                mBitmap = drawableToBitmap(d);
    
                                                // Save the current time
                                                mLastDrawTime = System.currentTimeMillis();
                                        } else if (mBitmap != null && mBitmap.isRecycled()){
                                                mBitmap=null;
                                                mBitmap = drawableToBitmap(d);
                                        }
                                } catch (NullPointerException npe) {
                                        holder.unlockCanvasAndPost(c);
                                        return;
                                } catch (RuntimeException re) {
                                        holder.unlockCanvasAndPost(c);
                                        return;
                                }
    
                                try {
                                        if (c != null) {
                                                int xPos;
                                                int yPos;
                                                if (mScroll) {
                                                        xPos = 0 - (int) (mWidth * mXOffset);
                                                        yPos = 0 - (int) (mHeight * mYOffset);
                                                } else {
                                                        xPos = 0;
                                                        yPos = 0;
                                                }
                                                try {
                                                        c.drawColor(Color.BLACK);
                                                        c.drawBitmap(mBitmap, xPos, yPos, myPaint);        
                                                } catch (Throwable t) {}
                                        }
                                } finally {
                                        if (c != null){
                                                if((mPreviousBitmap==null) || (mPreviousBitmap==mBitmap))
                                                        holder.unlockCanvasAndPost(c);
                                                else{                       
                                                        if(mTransition!=0)
                                                                startAnimation(mTransition, holder, c);
                                                        else
                                                                holder.unlockCanvasAndPost(c);
                                                }
                                                        mPreviousBitmap=null;
                                                        mPreviousBitmap = mBitmap;
                                        }
                                }
    
                                // Reschedule the next redraw
                                mDrawHandler.removeCallbacks(mDrawWorker);
    
                                if (mVisible) {
                                        mDrawHandler.postDelayed(mDrawWorker, 1000 / 2);
                                }
                                else{CancelFlag=true;}
                        }
    
    
    
                        void startAnimation(int animNumber, SurfaceHolder holder, Canvas canvas)
                        {
                                switch(animNumber){
                                        case 1:{
                                                canvas.drawBitmap(mBitmap, 0, 0, myPaint);
                                                int tmpPaintAlpha = myPaint.getAlpha();
                                                myPaint.setAlpha(255);
                                                canvas.drawBitmap(mPreviousBitmap, 0, 0, myPaint);
                                                holder.unlockCanvasAndPost(canvas);
                                                myPaint.setAlpha(tmpPaintAlpha);
    
                                                int i=224;
                                                while(i>=0){
                                                        canvas = holder.lockCanvas();
                                                        canvas.drawBitmap(mBitmap, 0, 0, myPaint);
                                                        myPaint.setAlpha(i);
                                                        canvas.drawBitmap(mPreviousBitmap, 0, 0, myPaint);
                                                        holder.unlockCanvasAndPost(canvas);
                                                        myPaint.setAlpha(255);
                                                        i-=18;
                                                }
                                                mLastDrawTime=System.currentTimeMillis();
                                                break;
                                        }
                                        case 2:{
                                                ....................
                                                break;
                                        }
                                }
                        }
                }
        ...................
        }
        ...................
    }
    

    每当我们落入 DrawTask.drawFrame()方法时,即使没有任何任何关系(mTransition == 0),也会出现错误。结果我看到了:

    (1)初始图像和下一图像的第一步正确完成;

    (2)当需要改变第二到第三等图像的时候,我只是在非恒定时段看到黑屏,然后我再次看到我的初始图像并在(2)中无限重复。任何设置更改都不会改变此行为。

    UPD3 希望我对此问题的详细描述(UPD1,UPD2)有助于找到这种奇怪行为的原因。但不幸的是,现在不适合我。

    提前非常感谢!

2 个答案:

答案 0 :(得分:2)

当设备内存不足时发生SIGSTKFLT,尤其是在底层的Linux OS层中使用malloc()调用时。当OS无法在malloc中返回失败时,它会产生这种致命信号。

尝试使用一些内存保存技术(如后期绑定图像解码)来解决低内存设备上的上述问题,因为它们占用大量内存时处理图像。

首先,您可以尝试将图片重新调整为屏幕分辨率或更低,然后再将其发布到画布上。

答案 1 :(得分:0)

感谢大家支持我!我找到了问题的真正原因。对于正确的线程问题,这只是一种愚蠢的方法。例如,在启动时调用的事件序列如下:

  

WallpaperService.onCreate()

     

onSharedPreferenceChanged()

     

WallpaperService.onCreateEngine()

     

Engine.onCreate()

     

Engine.onSurfaceCreated()(这里创建了DrawTask#1)

     

Engine.onSurfaceChanged()(这里创建了DrawTask#2)

     

Engine.onVisibilityChanged()(这里创建了DrawTask#3)

     

Engine.onOffsetChanged()(这里创建了DrawTask#4)

     

Engine.onOffsetChanged()(这里创建了DrawTask#5)

     

Engine.onOffsetChanged()(这里创建了DrawTask#6)

     

Engine.onOffsetChanged()(这里创建了DrawTask#7)

     

Engine.onOffsetChanged()(这里创建了DrawTask#8)

     

Engine.onOffsetChanged()(这里创建了DrawTask#9)

     

Engine.onOffsetChanged()(这里创建了DrawTask#10)

     

Engine.onOffsetChanged()(这里创建了DrawTask#11)

     

Engine.onOffsetChanged()(这里创建了DrawTask#12)

     

Engine.onOffsetChanged()(这里创建了DrawTask#13)

     

DrawTask#2已停止

     

DrawTask#3已停止

     

DrawTask#4已停止

     

DrawTask#6已停止

     

DrawTask#5已停止......

因此,除了onVisibilityChanged()和onSurfaceChanged()之外,如果变量mVisible为true,我将整体删除所有AsyncTask生成。现在,至少我的所有设备都可以。