简体   繁体   English

在真实设备上调试Android应用

[英]Android app debugging on real device

I am testing my last android app on a real device and it crashes on the second screen. 我正在真实设备上测试我的最后一个android应用程序,它在第二个屏幕上崩溃。

Tested on the simulator it works fine. 在模拟器上测试它可以正常工作。

This is the debugging message when it crashes..... 这是当它崩溃时的调试消息。

Any help is welcome to find out where to begin to solve the issue. 欢迎任何帮助以找出从哪里开始解决问题的方法。

10-22 21:31:09.364: E/WindowManager(31009): android.view.WindowLeaked: Activity com.solinpromex.casajuventudtrescantos.Cursos_MainActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView{456e0908 V.E..... R......D 0,0-580,163} that was originally added here
10-22 21:31:09.364: E/WindowManager(31009):     at android.view.ViewRootImpl.<init>(ViewRootImpl.java:468)
10-22 21:31:09.364: E/WindowManager(31009):     at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:267)
10-22 21:31:09.364: E/WindowManager(31009):     at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:69)
10-22 21:31:09.364: E/WindowManager(31009):     at android.app.Dialog.show(Dialog.java:289)
10-22 21:31:09.364: E/WindowManager(31009):     at com.solinpromex.casajuventudtrescantos.Cursos_MainActivity$DownloadJSON.onPreExecute(Cursos_MainActivity.java:77)
10-22 21:31:09.364: E/WindowManager(31009):     at android.os.AsyncTask.executeOnExecutor(AsyncTask.java:587)
10-22 21:31:09.364: E/WindowManager(31009):     at android.os.AsyncTask.execute(AsyncTask.java:535)
10-22 21:31:09.364: E/WindowManager(31009):     at com.solinpromex.casajuventudtrescantos.Cursos_MainActivity.onResume(Cursos_MainActivity.java:145)
10-22 21:31:09.364: E/WindowManager(31009):     at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1198)
10-22 21:31:09.364: E/WindowManager(31009):     at android.app.Activity.performResume(Activity.java:5538)
10-22 21:31:09.364: E/WindowManager(31009):     at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3053)
10-22 21:31:09.364: E/WindowManager(31009):     at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3092)
10-22 21:31:09.364: E/WindowManager(31009):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2463)
10-22 21:31:09.364: E/WindowManager(31009):     at android.app.ActivityThread.access$900(ActivityThread.java:172)
10-22 21:31:09.364: E/WindowManager(31009):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1305)
10-22 21:31:09.364: E/WindowManager(31009):     at android.os.Handler.dispatchMessage(Handler.java:102)
10-22 21:31:09.364: E/WindowManager(31009):     at android.os.Looper.loop(Looper.java:146)
10-22 21:31:09.364: E/WindowManager(31009):     at android.app.ActivityThread.main(ActivityThread.java:5598)
10-22 21:31:09.364: E/WindowManager(31009):     at java.lang.reflect.Method.invokeNative(Native Method)
10-22 21:31:09.364: E/WindowManager(31009):     at java.lang.reflect.Method.invoke(Method.java:515)
10-22 21:31:09.364: E/WindowManager(31009):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1283)
10-22 21:31:09.364: E/WindowManager(31009):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1099)
10-22 21:31:09.364: E/WindowManager(31009):     at dalvik.system.NativeStart.main(Native Method)

ACTIVITY CODE ADDED: 添加的活动代码:

package com.solinpromex.casajuventudtrescantos;


import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.os.Build;
import android.app.Activity;

import android.widget.Toast;

public class MainActivity extends Activity implements View.OnTouchListener  {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ImageView iv = (ImageView) findViewById (R.id.image);
        if (iv != null) {
           iv.setOnTouchListener (this);
        }





    }


    public boolean onTouch (View v, MotionEvent ev) 
    {
        boolean handledHere = false;

        final int action = ev.getAction();

        final int evX = (int) ev.getX();
        final int evY = (int) ev.getY();
        int nextImage = -1;         // resource id of the next image to display

        // If we cannot find the imageView, return.
        ImageView imageView = (ImageView) v.findViewById (R.id.image);
        if (imageView == null) return false;

        // When the action is Down, see if we should show the "pressed" image for the default image.
        // We do this when the default image is showing. That condition is detectable by looking at the
        // tag of the view. If it is null or contains the resource number of the default image, display the pressed image.
        Integer tagNum = (Integer) imageView.getTag ();
        int currentResource = (tagNum == null) ? R.drawable.p2_ship_default : tagNum.intValue ();

        // Now that we know the current resource being displayed we can handle the DOWN and UP events.

        switch (action) {
        case MotionEvent.ACTION_DOWN :
           if (currentResource == R.drawable.p2_ship_default) {
            //  nextImage = R.drawable.p2_ship_pressed;
              handledHere = true;
           /*
           } else if (currentResource != R.drawable.p2_ship_default) {
             nextImage = R.drawable.p2_ship_default;
             handledHere = true;
           */
           } else handledHere = true;
           break;

        case MotionEvent.ACTION_UP :
           // On the UP, we do the click action.
           // The hidden image (image_areas) has three different hotspots on it.
           // The colors are red, blue, and yellow.
           // Use image_areas to determine which region the user touched.
           int touchColor = getHotspotColor (R.id.image_areas, evX, evY);

           // Compare the touchColor to the expected values. Switch to a different image, depending on what color was touched.
           // Note that we use a Color Tool object to test whether the observed color is close enough to the real color to
           // count as a match. We do this because colors on the screen do not match the map exactly because of scaling and
           // varying pixel density.
           ColorTool ct = new ColorTool ();
           int tolerance = 25;
          // nextImage = R.drawable.p2_ship_default;


           if (ct.closeMatch (Color.RED, touchColor, tolerance))
           {
               Toast.makeText(getApplicationContext(), 
                       "CASA DE LA JUVENTUD", Toast.LENGTH_LONG).show();
               Intent intent = new Intent(MainActivity.this, categorias_list.class);
            startActivity(intent);
           }

           else if (ct.closeMatch (Color.YELLOW, touchColor, tolerance))
           {
               Toast.makeText(getApplicationContext(), 
                       "ZONAS OFICIALES", Toast.LENGTH_LONG).show();
               Intent intent = new Intent(MainActivity.this, categorias_list.class);
            startActivity(intent);
           }
           else if (ct.closeMatch (Color.rgb(164,199,57) , touchColor, tolerance))
           {
               Toast.makeText(getApplicationContext(), 
                       "ZONAS WI-FI", Toast.LENGTH_LONG).show();
               Intent intent = new Intent(MainActivity.this, categorias_list.class);
            startActivity(intent);
           }
           else if (ct.closeMatch (Color.LTGRAY , touchColor, tolerance))
           {
               Toast.makeText(getApplicationContext(), 
                       "ZONA DEPORTES", Toast.LENGTH_LONG).show();
               Intent intent = new Intent(MainActivity.this, categorias_list.class);
            startActivity(intent);
           }
           else if (ct.closeMatch (Color.BLUE , touchColor, tolerance))
           {
               Toast.makeText(getApplicationContext(), 
                       "ZONA COPAS", Toast.LENGTH_LONG).show();
               Intent intent = new Intent(MainActivity.this, categorias_list.class);
            startActivity(intent);
           }
           else if (ct.closeMatch (Color.WHITE , touchColor, tolerance))
           {
               Toast.makeText(getApplicationContext(), 
                       "ZONA QUEDADAS", Toast.LENGTH_LONG).show();
               Intent intent = new Intent(MainActivity.this, categorias_list.class);
            startActivity(intent);
           }
           else if (ct.closeMatch (Color.BLACK , touchColor, tolerance))
           {
               Toast.makeText(getApplicationContext(), 
                       "ZONA CULTURA", Toast.LENGTH_LONG).show();
               Intent intent = new Intent(MainActivity.this, Cursos_MainActivity.class);
            startActivity(intent);
           }


           // If the next image is the same as the last image, go back to the default.
           // toast ("Current image: " + currentResource + " next: " + nextImage);
           if (currentResource == nextImage) {
              nextImage = R.drawable.p2_ship_default;
           } 
           handledHere = true; 
           break;

        default:
           handledHere = false;

        } // end switch

        if (handledHere) {

           if (nextImage > 0) {
              imageView.setImageResource (nextImage);
              imageView.setTag (nextImage);
           }
        }
        return handledHere;
    } 


    public void openOfertas(View view) 
    {
        Intent intent = new Intent(MainActivity.this, categorias_list.class);
        startActivity(intent);
    }

    public void openArtesania(View view) 
    {
        Intent intent = new Intent(MainActivity.this, Artesania_MainActivity.class);
        startActivity(intent);
    }

    public void openCursos(View view) 
    {
        Intent intent = new Intent(MainActivity.this, Cursos_MainActivity.class);
        startActivity(intent);
    }
    public void openAvisos(View view) 
    {
        Intent intent = new Intent(MainActivity.this, Avisos_MainActivity.class);
        startActivity(intent);
    }

    public void openMapa(View view) 
    {
        Intent intent = new Intent(MainActivity.this, Mapa_MainActivity.class);
        startActivity(intent);
    }





    @Override
    public boolean onCreateOptionsMenu(Menu menu) {

        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
    public int getHotspotColor (int hotspotId, int x, int y) {
        ImageView img = (ImageView) findViewById (hotspotId);
        if (img == null) {
           Log.d ("ImageAreasActivity", "Hot spot image not found");
           return 0;
        } else {
          img.setDrawingCacheEnabled(true); 
          Bitmap hotspots = Bitmap.createBitmap(img.getDrawingCache()); 
          if (hotspots == null) {
             Log.d ("ImageAreasActivity", "Hot spot bitmap was not created");
             return 0;
          } else {
            img.setDrawingCacheEnabled(false);
            return hotspots.getPixel(x, y);
          }
        }
    }




}

ADDED ACTIVITY Cursos_MainActivity 增加的活动Cursos_MainActivity

package com.solinpromex.casajuventudtrescantos;

import java.util.ArrayList;
import java.util.HashMap;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.widget.ListView;

public class Cursos_MainActivity extends Activity {
    // Declare Variables


    JSONObject jsonobject;
    JSONArray jsonarray;
    ListView listview;
    Cursos_ListViewAdapter adapter;
    ProgressDialog mProgressDialog;
    ArrayList<HashMap<String, String>> arraylist;

    static String VALORACIONARTESANO = "valoracionArtesano";
    static String NOMBREARTESANO = "nombreArtesano";
    static String DIRECCIONARTESANO = "direccionArtesano";
    static String LOGOARTESANO = "logoArtesano";
    static String TELEFONOARTESANO = "telefonoArtesano";
    static String FACEBOOKARTESANO = "facebookArtesano";
    static String EMAILARTESANO = "emailArtesano";
    static String TEXTARTESANO = "textArtesano";
    static String LATITUD = "latitud";
    static String LONGITUD = "longitud";
    static String IDARTESANO = "idArtesano";
    static String CIUDAD = "ciudad";
    static String CP = "cp";
    static String WEB = "web";



    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.v("MVASCO", "context is null!");
         // getting intent data
        Intent in = getIntent();
     // JSON node keys



        this.setTitle("Zona Cultura");
        // Get the view from listview_main.xml
        setContentView(R.layout.cursos_listview_main);
        // Execute DownloadJSON AsyncTask
        //new DownloadJSON().execute();
    }

    // DownloadJSON AsyncTask
    private class DownloadJSON extends AsyncTask<Void, Void, Void> {

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            // Create a progressdialog
            mProgressDialog = new ProgressDialog(Cursos_MainActivity.this);
            // Set progressdialog title
            mProgressDialog.setTitle("Casa de la Juventud");
            // Set progressdialog message
            mProgressDialog.setMessage("Zona Cultura");
            mProgressDialog.setIndeterminate(false);
            // Show progressdialog
            mProgressDialog.show();
        }

        @Override
        protected Void doInBackground(Void... params) {
            // Create an array
            arraylist = new ArrayList<HashMap<String, String>>();
            // Retrieve JSON Objects from the given URL address
            jsonobject = JSONfunctions
                    .getJSONfromURL("http://www.solinpromex.com/casajuventud/android/android_centros.php");

            try {
                // Locate the array name in JSON
                jsonarray = jsonobject.getJSONArray("Categorias");

                for (int i = 0; i < jsonarray.length(); i++) {
                    HashMap<String, String> map = new HashMap<String, String>();
                    jsonobject = jsonarray.getJSONObject(i);
                    // Retrive JSON Objects
                    String codpostal = jsonobject.getString("cp_zonacultura");
                    map.put("valoracionArtesano", jsonobject.getString("valoracion_zonacultura"));
                    map.put("nombreArtesano", jsonobject.getString("nombre_zonacultura"));
                    map.put("direccionArtesano", jsonobject.getString("direccion_zonacultura"));
                    map.put("logoArtesano", jsonobject.getString("imagen_zonacultura"));
                    map.put("telefonoArtesano", jsonobject.getString("tel_zonacultura"));
                    map.put("emailArtesano", jsonobject.getString("email_zonacultura"));
                    map.put("textArtesano", jsonobject.getString("desc_zonacultura"));
                    map.put("facebookArtesano", jsonobject.getString("facebook_zonacultura"));
                    map.put("latitud", jsonobject.getString("latitud_zonacultura"));
                    map.put("longitud", jsonobject.getString("longitud_zonacultura"));
                    map.put("idArtesano", jsonobject.getString("id_zonacultura"));
                    map.put("ciudad", codpostal+" "+jsonobject.getString("ciudad_zonacultura"));
                    map.put("cp", jsonobject.getString("cp_zonacultura"));
                    map.put("web", jsonobject.getString("web_zonacultura"));




Log.d("NOMBRE DEL SITIO ", "Value: " + (jsonobject.getString("nombre_zonacultura")));

                    // Set the JSON Objects into the array
                    arraylist.add(map);
                }
            } catch (JSONException e) {
                Log.e("Error", e.getMessage());
                e.printStackTrace();
            }
            return null;
        }

        @Override
        protected void onPostExecute(Void args) {
            // Locate the listview in listview_main.xml
            listview = (ListView) findViewById(R.id.listview);
            // Pass the results into ListViewAdapter.java
            adapter = new Cursos_ListViewAdapter(Cursos_MainActivity.this, arraylist);
            // Set the adapter to the ListView
            listview.setAdapter(adapter);

            // Close the progressdialog
            mProgressDialog.dismiss();
        }
    }

    @Override
    protected void onResume() {
        // TODO Auto-generated method stub
        super.onResume();
        new DownloadJSON().execute();
    }

}

your mProgressDialog is leaking memory. 您的mProgressDialog正在泄漏内存。

try this 尝试这个

mProgressDialog = new ProgressDialog(this.getApplicationContext());

I think that the problem is in : 我认为问题出在:

adapter = new Cursos_ListViewAdapter(Cursos_MainActivity.this, arraylist);
        // Set the adapter to the ListView
        listview.setAdapter(adapter);

I have no idea what is in your adapter but usual you are dealing there with views. 我不知道您的适配器中有什么,但是通常您正在那里处理视图。

Don't forget that "onPostExecute" is still in the other Thread and you are trying to work with the views from the main thread/activity ... 不要忘记“ onPostExecute”仍然在另一个线程中,并且您正在尝试使用主线程/活动中的视图...

The best solution for things like that is to pass to the AsyncTask some Interface and when is done the AsyncTask will pass the data back to the activity. 最好的解决方案是将某些接口传递给AsyncTask,完成后AsyncTask会将数据传递回活动。

This is also much more close to SOLID . 这也更接近SOLID The AsyncTask shall get the data and pass it over. AsyncTask应获取数据并将其传递。 The adapter shall shown the received data. 适配器应显示收到的数据。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM