4

The Android app using OData WCF - The Android app continues to crash

 2 years ago
source link: https://www.codesd.com/item/the-android-app-using-odata-wcf-the-android-app-continues-to-crash.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

The Android app using OData WCF - The Android app continues to crash

advertisements

I am fairly new to Android development and I am trying to create an app that will display a list of manifests for verification.

As I am new to this, I followed an example found in the "OData Programming Cookbook for .NET Developers" book to develop a prototype of this app. I have tested the example in the book (Chapter 5) (it works fine), but it crashes for some reason.

I suspect that it may have to do with my WCF OData Service. It was developed in Entity Framework and is hosted on my local PC i.e. http:192.168.0.105:8090/PODDataService.svc.

As per the example of the book, I have also created 2 mapping classes, since the app only interacts with 2 OData entities.

Here are the 6 classes I've used to build the project:

package com.podcheck;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.core4j.Enumerable;
import org.odata4j.consumer.ODataConsumer;
import org.odata4j.core.OEntity;
import org.odata4j.core.OLink;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.widget.ListView;

public class MainActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        ListView lvManifests = (ListView)findViewById(R.id.lvManifests);

        // Add item click action listener
        lvManifests.setOnItemClickListener(
                new ManifestListItemClickListener(this)
        );

        // Populate category items on lstCategory
        ArrayList<ManifestObj> manifestList = GetManifestItems();
        ManifestsAdapter mAdapter = new ManifestsAdapter(this, R.layout.list_item, manifestList);
        lvManifests.setAdapter(mAdapter);
    }

    // Query Category list from Northwind based WCF DataService
    ArrayList<ManifestObj> GetManifestItems()
    {
        String svcUri = "http://192.168.0.105:8090/PODDataService.svc/";
        ODataConsumer c = ODataConsumer.create(svcUri);        

        ArrayList<ManifestObj> manifestList = new ArrayList<ManifestObj>();

        Enumerable<OEntity> cursor = c.getEntities("Manifests").expand("ManifestItems").execute();
        for (OEntity entityObj : cursor)
        {
            ManifestObj mObj = new ManifestObj();

            mObj.ManifestID =  entityObj.getProperty("ManifestID", Integer.class).getValue();
            mObj.ManifestCode = entityObj.getProperty("ManifestCode", String.class).getValue();
            mObj.ManifestDate = entityObj.getProperty("ManifestDate", Date.class).getValue();

            Date date = new Date();
            if(mObj.ManifestDate == date)
            {

                List<OEntity> entityList = entityObj.getLink("ManifestItems", OLink.class).getRelatedEntities();
                mObj.ManifestItems = new ArrayList<ManifestItemObj>();

                for(OEntity pEntity: entityList)
                {
                    ManifestItemObj miObj = new ManifestItemObj();
                    miObj.JobType = pEntity.getProperty("JobType", String.class).getValue();
                    miObj.FKID = pEntity.getProperty("FKID", Integer.class).getValue();
                    //miObj.SupplierID = pEntity.getProperty("SupplierID", Integer.class).getValue();
                    //miObj.UnitPrice =  pEntity.getProperty("UnitPrice", BigDecimal.class).getValue();
                    mObj.ManifestItems.add(miObj);
                }
                manifestList.add(mObj);
            }
        }
            return manifestList;
    }

    public void ShowItemsOfManifest(ManifestObj manifest)
    {
        Bundle bundle = new Bundle();
        Intent newIntent = new Intent(this.getApplicationContext(), SubActivity.class);
        newIntent.putExtras(bundle);
        newIntent.putExtra("Manifest", manifest);

        this.startActivity(newIntent);

    }

}

package com.podcheck;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class SubActivity extends Activity implements OnClickListener {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.sub);

        ManifestObj mObj = (ManifestObj)this.getIntent().getSerializableExtra("Manifest");

        TextView tv = (TextView)this.findViewById(R.id.tvContent);  

        StringBuffer sb = new StringBuffer();
        sb.append("You have selected the following Category:");
        sb.append("\nManifest: " + mObj.getManifestCode());
        sb.append("\nManifest Raised On: " + mObj.getManifestDate());
        sb.append("\nItems under this Manifest(" + mObj.ManifestItems.size() + "):");
        sb.append("\n----------------------------------------------------------");

        for(ManifestItemObj miObj: mObj.ManifestItems){
            sb.append("\nJob:" + miObj.getJobType() + Integer.toString(miObj.getFKID()));
            sb.append("\n\t");
        }

        tv.setText(sb.toString());

        Button btn = (Button)this.findViewById(R.id.btnReturn);
        btn.setOnClickListener(
            this
        );
    }

    public void onClick(View v) {
        //this.finishActivity(0);
        System.out.println("finish activity");
        this.finish();
    }

package com.podcheck;

import java.util.ArrayList;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.LinearLayout;
import android.widget.TextView;

public class ManifestsAdapter extends ArrayAdapter<ManifestObj> {

    int resourceId = 0;

    public ManifestsAdapter(Context context, int resource, ArrayList<ManifestObj> items) {
        super(context, resource, items);
        this.resourceId = resource;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent)
    {
        LinearLayout itemRoot;
        ManifestObj manifest;

        manifest = this.getItem(position);

        //Inflate the view
        if(convertView==null)
        {
            itemRoot = new LinearLayout(getContext());
            String inflater = Context.LAYOUT_INFLATER_SERVICE;
            LayoutInflater vi;
            vi = (LayoutInflater)getContext().getSystemService(inflater);
            vi.inflate(this.resourceId, itemRoot, true);
        }
        else
        {
            itemRoot = (LinearLayout) convertView;
        }

        TextView tvName =(TextView)itemRoot.findViewById(R.id.tvCategoryName);
        tvName.setText(manifest.getManifestCode());
        itemRoot.setTag(manifest);

        return itemRoot;
    }

}

package com.podcheck;

//import android.content.Intent;
//import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.LinearLayout;

public class ManifestListItemClickListener implements OnItemClickListener {

    MainActivity _mainActivity;
    public ManifestListItemClickListener(MainActivity ma){
        _mainActivity = ma;
    }

    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        LinearLayout itemRoot = (LinearLayout)view;
        ManifestObj mObj = (ManifestObj)itemRoot.getTag();

        StringBuffer sb = new StringBuffer();
        sb.append("You have selected the following Manifest:");
        sb.append("\nID: " + mObj.getManifestID());
        sb.append("\nName: " + mObj.getManifestCode());
        sb.append("\nManifestDate: " + mObj.getManifestDate());

//      new AlertDialog.Builder(parent.getContext())
//      .setTitle("Manifest Selected")
//      .setMessage(sb.toString())
//      .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
//          public void onClick(DialogInterface dialog, int which) {
//              // do something else
//
//          }
//       })
//       .show();

        _mainActivity.ShowItemsOfManifest(mObj);
    }

}

package com.podcheck;

import java.io.Serializable;

public class ManifestItemObj implements Serializable
{
    int ManifestItemID;
    int FKID;
    String JobType;

    public int getManifestItemsID()
    {
        return ManifestItemID;
    }

    public void setManifestItemID(int manifestItemID)
    {
        ManifestItemID = manifestItemID;
    }

    public int getFKID()
    {
        return FKID;
    }
    public void setFKID(int fkid)
    {
        FKID = fkid;
    }
    public String getJobType()
    {
        return JobType;
    }
    public void setJobType(String jobType)
    {
        JobType = jobType;
    }

}

package com.podcheck;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;

import org.joda.time.DateTime;

public class ManifestObj implements Serializable{

    int ManifestID;
    String ManifestCode;
    Date ManifestDate;
    boolean Consolidated;
    ArrayList<ManifestItemObj> ManifestItems;

    public int getManifestID() {
        return ManifestID;
    }
    public void setManifestID(int manifestID) {
        ManifestID = manifestID;
    }
    public String getManifestCode() {
        return ManifestCode;
    }
    public void setManifestCode(String manifestCode) {
        ManifestCode = manifestCode;
    }
    public Date getManifestDate() {
        return ManifestDate;
    }
    public void setManifestDate(Date manifestDate) {
        ManifestDate = manifestDate;
    }
    public boolean getConsolidated() {
        return Consolidated;
    }
    public void setConsolidated(boolean consolidated) {
        Consolidated = consolidated;
    }

    public ArrayList<ManifestItemObj> ManifestItems()
    {
        return ManifestItems;
    }

    public void setManifestItems(ArrayList<ManifestItemObj> manifestItems)
    {
        ManifestItems = manifestItems;
    }
}

I don't think it has anything to do with my Manifest or my XML files at this moment.

I am a little lost as there is virtually nothing different. I have tested my WCF Data service countless times.

Could it also be the dataset size? My Manifest table in the SQL Server DB does have close to 31000 records.

EDIT: Here's the log:-

'02-03 23:11:20.609: D/dalvikvm(617): GC_CONCURRENT freed 272K, 4% free 8197K/8519K, paused 33ms+5ms, total 79ms
02-03 23:11:20.609: D/dalvikvm(617): WAIT_FOR_CONCURRENT_GC blocked 32ms
02-03 23:11:20.769: D/AndroidRuntime(617): Shutting down VM
02-03 23:11:20.780: W/dalvikvm(617): threadid=1: thread exiting with uncaught exception (group=0x40a13300)
02-03 23:11:20.809: E/AndroidRuntime(617): FATAL EXCEPTION: main
02-03 23:11:20.809: E/AndroidRuntime(617): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.podcheck/com.podcheck.MainActivity}: com.sun.jersey.api.client.ClientHandlerException: android.os.NetworkOnMainThreadException
02-03 23:11:20.809: E/AndroidRuntime(617):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2059)
02-03 23:11:20.809: E/AndroidRuntime(617):  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084)
02-03 23:11:20.809: E/AndroidRuntime(617):  at android.app.ActivityThread.access$600(ActivityThread.java:130)
02-03 23:11:20.809: E/AndroidRuntime(617):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
02-03 23:11:20.809: E/AndroidRuntime(617):  at android.os.Handler.dispatchMessage(Handler.java:99)
02-03 23:11:20.809: E/AndroidRuntime(617):  at android.os.Looper.loop(Looper.java:137)
02-03 23:11:20.809: E/AndroidRuntime(617):  at android.app.ActivityThread.main(ActivityThread.java:4745)
02-03 23:11:20.809: E/AndroidRuntime(617):  at java.lang.reflect.Method.invokeNative(Native Method)
02-03 23:11:20.809: E/AndroidRuntime(617):  at java.lang.reflect.Method.invoke(Method.java:511)
02-03 23:11:20.809: E/AndroidRuntime(617):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
02-03 23:11:20.809: E/AndroidRuntime(617):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
02-03 23:11:20.809: E/AndroidRuntime(617):  at dalvik.system.NativeStart.main(Native Method)
02-03 23:11:20.809: E/AndroidRuntime(617): Caused by: com.sun.jersey.api.client.ClientHandlerException: android.os.NetworkOnMainThreadException
02-03 23:11:20.809: E/AndroidRuntime(617):  at com.sun.jersey.client.urlconnection.URLConnectionClientHandler.handle(URLConnectionClientHandler.java:128)
02-03 23:11:20.809: E/AndroidRuntime(617):  at com.sun.jersey.api.client.Client.handle(Client.java:457)
02-03 23:11:20.809: E/AndroidRuntime(617):  at com.sun.jersey.api.client.WebResource.handle(WebResource.java:557)
02-03 23:11:20.809: E/AndroidRuntime(617):  at com.sun.jersey.api.client.WebResource.access$300(WebResource.java:69)
02-03 23:11:20.809: E/AndroidRuntime(617):  at com.sun.jersey.api.client.WebResource$Builder.method(WebResource.java:539)
02-03 23:11:20.809: E/AndroidRuntime(617):  at org.odata4j.consumer.ODataClient.doRequest(ODataClient.java:214)
02-03 23:11:20.809: E/AndroidRuntime(617):  at org.odata4j.consumer.ODataClient.getMetadata(ODataClient.java:66)
02-03 23:11:20.809: E/AndroidRuntime(617):  at org.odata4j.consumer.ODataConsumer$CachedEdmDataServices.refreshDelegate(ODataConsumer.java:592)
02-03 23:11:20.809: E/AndroidRuntime(617):  at org.odata4j.consumer.ODataConsumer$CachedEdmDataServices.getDelegate(ODataConsumer.java:586)
02-03 23:11:20.809: E/AndroidRuntime(617):  at org.odata4j.internal.EdmDataServicesDecorator.findEdmEntitySet(EdmDataServicesDecorator.java:46)
02-03 23:11:20.809: E/AndroidRuntime(617):  at org.odata4j.consumer.ODataConsumer$CachedEdmDataServices.findEdmEntitySet(ODataConsumer.java:598)
02-03 23:11:20.809: E/AndroidRuntime(617):  at org.odata4j.consumer.ODataConsumer.getFeedCustomizationMapping(ODataConsumer.java:559)
02-03 23:11:20.809: E/AndroidRuntime(617):  at org.odata4j.consumer.ODataConsumer.getEntities(ODataConsumer.java:313)
02-03 23:11:20.809: E/AndroidRuntime(617):  at org.odata4j.consumer.ODataConsumer.getEntities(ODataConsumer.java:300)
02-03 23:11:20.809: E/AndroidRuntime(617):  at com.podcheck.MainActivity.GetManifestItems(MainActivity.java:46)
02-03 23:11:20.809: E/AndroidRuntime(617):  at com.podcheck.MainActivity.onCreate(MainActivity.java:33)
02-03 23:11:20.809: E/AndroidRuntime(617):  at android.app.Activity.performCreate(Activity.java:5008)
02-03 23:11:20.809: E/AndroidRuntime(617):  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079)
02-03 23:11:20.809: E/AndroidRuntime(617):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2023)
02-03 23:11:20.809: E/AndroidRuntime(617):  ... 11 more
02-03 23:11:20.809: E/AndroidRuntime(617): Caused by: android.os.NetworkOnMainThreadException
02-03 23:11:20.809: E/AndroidRuntime(617):  at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1117)
02-03 23:11:20.809: E/AndroidRuntime(617):  at libcore.io.BlockGuardOs.connect(BlockGuardOs.java:84)
02-03 23:11:20.809: E/AndroidRuntime(617):  at libcore.io.IoBridge.connectErrno(IoBridge.java:127)
02-03 23:11:20.809: E/AndroidRuntime(617):  at libcore.io.IoBridge.connect(IoBridge.java:112)
02-03 23:11:20.809: E/AndroidRuntime(617):  at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:192)
02-03 23:11:20.809: E/AndroidRuntime(617):  at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:459)
02-03 23:11:20.809: E/AndroidRuntime(617):  at java.net.Socket.connect(Socket.java:842)
02-03 23:11:20.809: E/AndroidRuntime(617):  at libcore.net.http.HttpConnection.<init>(HttpConnection.java:76)
02-03 23:11:20.809: E/AndroidRuntime(617):  at libcore.net.http.HttpConnection.<init>(HttpConnection.java:50)
02-03 23:11:20.809: E/AndroidRuntime(617):  at libcore.net.http.HttpConnection$Address.connect(HttpConnection.java:341)
02-03 23:11:20.809: E/AndroidRuntime(617):  at libcore.net.http.HttpConnectionPool.get(HttpConnectionPool.java:87)
02-03 23:11:20.809: E/AndroidRuntime(617):  at libcore.net.http.HttpConnection.connect(HttpConnection.java:117)
02-03 23:11:20.809: E/AndroidRuntime(617):  at libcore.net.http.HttpEngine.openSocketConnection(HttpEngine.java:315)
02-03 23:11:20.809: E/AndroidRuntime(617):  at libcore.net.http.HttpEngine.connect(HttpEngine.java:310)
02-03 23:11:20.809: E/AndroidRuntime(617):  at libcore.net.http.HttpEngine.sendSocketRequest(HttpEngine.java:289)
02-03 23:11:20.809: E/AndroidRuntime(617):  at libcore.net.http.HttpEngine.sendRequest(HttpEngine.java:239)
02-03 23:11:20.809: E/AndroidRuntime(617):  at libcore.net.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:273)
02-03 23:11:20.809: E/AndroidRuntime(617):  at libcore.net.http.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:486)
02-03 23:11:20.809: E/AndroidRuntime(617):  at com.sun.jersey.client.urlconnection.URLConnectionClientHandler._invoke(URLConnectionClientHandler.java:215)
02-03 23:11:20.809: E/AndroidRuntime(617):  at com.sun.jersey.client.urlconnection.URLConnect
02-03 23:11:20.839: D/dalvikvm(617): GC_CONCURRENT freed 463K, 6% free 8261K/8775K, paused 25ms+6ms, total 91ms
02-03 23:11:20.839: D/dalvikvm(617): WAIT_FOR_CONCURRENT_GC blocked 14ms'

EDIT:

I suspect that this is now the issue:-

ODataConsumer c = ODataJerseyConsumer.create("http://192.168.0.105:8090/PODDataService.svc"); 

for (OEntity entityObj : c.getEntities("Manifests").expand("ManifestItems").execute())
{
//opcode
}

This means that it is not reading the WCF service. Right?

ANOTHER EDIT: The same application now works in Android 2.3. How different is Android 4 to 2.3? Another mystery to be uncovered.


If this is Still open and being read the actual problem is that in android 4.0 you can not run network calls on the main thread. It will throw a network on main thread error, in android 2.3 you were allowed to do this. Thats why one works and one doesn't. What you want to do is run all of your network operations in an Async Task. Check out the documentation below.

http://developer.android.com/reference/android/os/AsyncTask.html


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK