3

I have a custom adapter that extends ArrayAdapter. I want to go to MapActivity when the EMAIL is clicked. If I remove the intent part a toast appears with the correct position of the item clicked. However, if I add the startActivity function, the app crashes (no toast). I removed the irrelevant code such as getting distance and setters.getters. Any help or pointer would be appreciated!

ArrayAdapter code

import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import com.firebase.client.ChildEventListener;
import com.firebase.client.DataSnapshot;
import com.firebase.client.Firebase;
import com.firebase.client.FirebaseError;
import com.firebase.client.ValueEventListener;
import com.google.android.gms.maps.model.LatLng;
import com.google.firebase.auth.FirebaseAuth;

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

public class TrackAdapter extends ArrayAdapter{

    private Context c;
    //ArrayLists to save items

    public TrackAdapter(Context context, int resource)
    {
        super(context, resource);
        this.c = context;
    }

    public void add(/*items to be added*/)
    {
       //add to ArrayLists and super.add()
    }

    static class RowHolder
    {
        TextView EMAIL;
        TextView DISTANCE;
    }

    @Override
    public int getCount()
    {
        return this.email.size();
    }

    @Override
    public Object getItem(int position)
    {
        return this.email.get(position);
    }

    /*other setters and getters*/

    @Override
    public View getView(int position, View convertView, ViewGroup parent)
    {
        View row;
        row = convertView;
        RowHolder holder;

        final int currentPosition = position;

        if (convertView == null)
        {
            LayoutInflater inflater = (LayoutInflater) this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            row = inflater.inflate(R.layout.track_item, parent, false);

            holder = new RowHolder();

            holder.EMAIL = (TextView) row.findViewById(R.id.track_item_text);
            holder.DISTANCE = (TextView) row.findViewById(R.id.track_item_distance);

            holder.EMAIL.setOnClickListener(new View.OnClickListener() 
            {
                @Override
                public void onClick(View v) 
                {
                    Toast.makeText(c, "item at position " + currentPosition, Toast.LENGTH_SHORT).show();
                    Intent intent = new Intent(c, MapActivity.class);
                    c.startActivity(intent);
                }
            });

            row.setTag(holder);
        }
        else
        {
            holder = (RowHolder) row.getTag();
        }


        String EM = (String) getItem(position);
        holder.EMAIL.setText(EM);

        //calculate and display distance

        return row;

    }
}

I also tried replacing c with c.getApplicationContext() and v.getContext(), which also doesn't work.

EDIT- I ran the app on an emulator, and it goes to the MapActivity. However, when ran on an android device connected by USB, the app crashes

EDIT2 - Here is the crash report

--------- beginning of crash
03-29 03:23:42.036 7768-7768/com.example.*******
E/AndroidRuntime: FATAL EXCEPTION: main

                                                                                android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity  context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
                                                                                    at android.app.ContextImpl.startActivity(ContextImpl.java:672)
                                                                                at android.app.ContextImpl.startActivity(ContextImpl.java:659)
                                                                                at android.content.ContextWrapper.startActivity(ContextWrapper.java:331)
                                                                                at com.example.ankit.findyourfellow.TrackAdapter$1.onClick(TrackAdapter.java:127)
                                                                                at android.view.View.performClick(View.java:5204)
                                                                                at android.view.View$PerformClick.run(View.java:21153)
                                                                                at android.os.Handler.handleCallback(Handler.java:739)
                                                                                at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                                at android.os.Looper.loop(Looper.java:148)
                                                                                at android.app.ActivityThread.main(ActivityThread.java:5417)
                                                                                at java.lang.reflect.Method.invoke(Native Method)
                                                                                at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
                                                                                at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
ankit
  • 125
  • 4
  • 13

5 Answers5

4

Inside your click listener do something like:

holder.EMAIL.setOnClickListener(new View.OnClickListener() 
        {
            @Override
            public void onClick(View v) 
            {
                Toast.makeText(c, "item at position " + currentPosition, Toast.LENGTH_SHORT).show();
                Intent intent = new Intent(c, MapActivity.class);
                //if you want to send data to called activity uncomment next line
                // intent.putExtra("extra", "value"); 

                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                c.startActivity(intent);
            }
        });

It should work :)

amit srivastava
  • 743
  • 6
  • 25
2

Add flag Intent.FLAG_ACTIVITY_NEW_TASK to your intent.

Use intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK) before starting MapActivity.

Try this:

 Intent intent = new Intent(c, MapActivity.class);
 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
 c.startActivity(intent);
Ferdous Ahamed
  • 21,438
  • 5
  • 52
  • 61
1

Update your code:

public Context c;

// Contractor   
public TrackAdapter(Context mcontext, int resource)
{
    super(mcontext, R.layout.track_item, resource);
    this.c= mcontext;
    this.resource = resource;
}

Call the setOnClickListener after setText label or before return.

holder.EMAIL.setText(EM);
  holder.EMAIL.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                Intent intent = new Intent(c.getApplicationContext(), NEXT_ACTIVITY.class);
                c.startActivity(intent);
            }
        });
Andy Developer
  • 3,071
  • 1
  • 19
  • 39
ITSGuru
  • 194
  • 8
1

Even if it works I am not sure if intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); is desired solution!
Where did you instantiated ArrayAdapter? Can you just try to cast context to activity?
Intent intent = new Intent((Activity)c, MapActivity.class);
Also I wonder why new Intent(v.getContext(), MapActivity.class); doesn't work?

UPDATE:
I found what's the problem... you need to start activity from context other then applicationContext!

Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag

It seems that your Context c is actually aplication context...
So here is the working code to put in onClick

Intent intent = new Intent(c, MapActivity.class); 
v.getContext().startActivity(intent);
makvasic
  • 213
  • 1
  • 8
  • casting to (Activity) does not work. And I'm guessing I need to flag the intent no matter the context. What I'm wondering is why it worked on my emulator without the flag? My emulator is 7.1.1 API 25 where as my device is 6.0.1 API 23 so maybe thats the cause. – ankit Mar 29 '17 at 07:59
  • It seem that on android 7 (just tested on emulator) you actually can start activity from application context without the flag! But please see updated answer for proper solution. – makvasic Mar 29 '17 at 08:51
0

add following code to your adapter class

ClickListener mClickListener;
public void setClickListener(ClickListener clickListener) {
        this.mClickListener = clickListener;
    }

    public interface ClickListener {
        void onItemClick();
    }

Now in Activity class add this where you setting adapter :

mAdapter.setClickListener(new TrackAdapter.ClickListener() {

            @Override
            public void onItemClick() {
                 Intent intent = new Intent(YourActivity.this, MapActivity.class);
                 startActivity(intent);
            }
}

Than onClick method of your adapter class call following :

if (mClickListener != null ) {
                             mClickListener.onItemClick();
                        }
Krishna Meena
  • 5,693
  • 5
  • 32
  • 44