将LatLng数组添加到Android Studio中的ParseObject

时间:2015-08-04 14:16:15

标签: android android-studio parse-platform google-maps-android-api-2

我希望将数组对象添加到我创建的ParseObject中,但是在我的应用程序上执行操作时,logCat会收到以下错误:

  08-04 15:06:26.466  18982-18982/com.khackett.runmate E/AndroidRuntime﹕ FATAL EXCEPTION: main
      Process: com.khackett.runmate, PID: 18982
      java.lang.IllegalArgumentException: invalid type for ParseObject: class com.google.android.gms.maps.model.LatLng
              at com.parse.ParseEncoder.encode(ParseEncoder.java:141)
              at com.parse.ParseEncoder.encode(ParseEncoder.java:101)
              at com.parse.ParseJSONCacheItem.<init>(ParseJSONCacheItem.java:15)
              at com.parse.ParseObject.addToHashedObjects(ParseObject.java:647)
              at com.parse.ParseObject.checkpointMutableContainer(ParseObject.java:1348)
              at com.parse.ParseObject.performOperation(ParseObject.java:3121)
              at com.parse.ParseObject.addAll(ParseObject.java:3215)
              at com.khackett.runmate.RouteRecipientsActivity.createRoute(RouteRecipientsActivity.java:219)
              at com.khackett.runmate.RouteRecipientsActivity.onOptionsItemSelected(RouteRecipientsActivity.java:166)
              at android.app.Activity.onMenuItemSelected(Activity.java:2885)
              at com.android.internal.policy.impl.PhoneWindow.onMenuItemSelected(PhoneWindow.java:1133)
              at com.android.internal.view.menu.MenuBuilder.dispatchMenuItemSelected(MenuBuilder.java:761)
              at com.android.internal.view.menu.MenuItemImpl.invoke(MenuItemImpl.java:152)
              at com.android.internal.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:904)
              at com.android.internal.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:894)
              at android.widget.ActionMenuView.invokeItem(ActionMenuView.java:587)
              at com.android.internal.view.menu.ActionMenuItemView.onClick(ActionMenuItemView.java:141)
              at android.view.View.performClick(View.java:4780)
              at android.view.View$PerformClick.run(View.java:19866)
              at android.os.Handler.handleCallback(Handler.java:739)
              at android.os.Handler.dispatchMessage(Handler.java:95)
              at android.os.Looper.loop(Looper.java:135)
              at android.app.ActivityThread.main(ActivityThread.java:5254)
              at java.lang.reflect.Method.invoke(Native Method)
              at java.lang.reflect.Method.invoke(Method.java:372)
              at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
              at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)

RouteRecipientsActivity的类是:

package com.khackett.runmate;

import android.app.AlertDialog;
import android.app.ListActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.Window;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;

import com.google.android.gms.maps.model.LatLng;
import com.parse.FindCallback;
import com.parse.ParseException;
import com.parse.ParseObject;
import com.parse.ParseQuery;
import com.parse.ParseRelation;
import com.parse.ParseUser;
import com.parse.SaveCallback;

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

public class RouteRecipientsActivity extends ListActivity {

    public static final String TAG = RouteRecipientsActivity.class.getSimpleName();

    // set up a reference to the current user
    protected ParseUser mCurrentUser;
    // set up a member variable to store a list of friends for the current user returned from the parse user query
    protected List<ParseUser> mFriends;
    // set up a ParseRelation member to hold ParseUsers
    protected ParseRelation<ParseUser> mFriendsRelation;

    // create a menu item member variable so that it can be referenced below (it is a send button to be set on and off depending on if a user is selected)
    // set this variable in the onCreateOptionsMenu
    protected MenuItem mSendMenuItem;

    // member variable to represent the array of LatLng values passed into this activity via the intent that started it
    protected ArrayList<LatLng> markerPoints;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
        setContentView(R.layout.activity_route_recipients);

        // line to ensure the action bar displays in the layout
        // ((AppCompatActivity) getSupportActionBar()).setDisplayHomeAsUpEnabled(true);
        getActionBar().setDisplayHomeAsUpEnabled(true);

        // the list view keeps track of items that are selected (this is the check property on each item)
        // loop through the list to see who is checked - do this when we are ready to send

        // get the default list view associated with this activity
        getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);  // we can now check and uncheck multiple friends

        // get the array of LatLng points passed in from the map intent
        markerPoints = getIntent().getParcelableArrayListExtra("markerPoints");
    }

    // get a list of all your friends - this code is copied from the onResume() method in the FriendsFragment with some additions
    @Override
    public void onResume() {
        super.onResume();

        // get the current user using the getCurrentUser() method
        mCurrentUser = ParseUser.getCurrentUser();
        // for the relation, from this user we want to call a method called getRelation()
        mFriendsRelation = mCurrentUser.getRelation(ParseConstants.KEY_FRIENDS_RELATION);

        // start the progress indicator before we run our query
        // use the getActivity() to get a reference to the activity in which the fragment is running (as setProgressBarIndeterminateVisibility() is an Activity method)
        // note: Window provided Progress Bars are now deprecated with Toolbar.
        // see: http://stackoverflow.com/questions/27788195/setprogressbarindeterminatevisibilitytrue-not-working
        // getActivity().setProgressBarIndeterminateVisibility(true);

        // the first thing we need is a list of the users friends...
        // we have the friend relation, but this doesn't give us a list of users to work with
        // the list itself is still on the back end, we need to use the ParseRelation to retrieve it
        // use the build in query to retrieve it - this gets us the query associated with this ParseRelation
        ParseQuery<ParseUser> query = mFriendsRelation.getQuery();

        // sort the list by username before calling it
        query.addAscendingOrder(ParseConstants.KEY_USERNAME);

        query.findInBackground(new FindCallback<ParseUser>() {
            @Override
            public void done(List<ParseUser> friends, ParseException e) {

                // getActivity().setProgressBarIndeterminateVisibility(false);

                // include an if statement to check the exception
                if (e == null) {

                    // set the mFriends variable based on the list of friends that is returned
                    mFriends = friends;

                    // now we need to use mFriends as the data source for the list view in our fragments
                    // we need to create an adapter and set it as the list adapter, just like we do for lost activities
                    // this is very similar to what we are ding for all users in the EditFriends activity, so copy and paste that code

                    // create an array of strings to store the usernames and set the size equal to that of the list returned
                    String[] usernames = new String[mFriends.size()];
                    // enhanced for loop to go through the list of parse users and create an array of usernames
                    int i = 0;
                    for (ParseUser user : mFriends) {
                        usernames[i] = user.getUsername();
                        i++;
                    }
                    // create an array adapter and set it as the adapter for this activity
                    ArrayAdapter<String> adapter = new ArrayAdapter<String>(
                            // for the first parameter here, need to get the context of a fragment through the list view itself
                            // the list view knows which context it is in because of its layout in the fragment and in the activity that contains the fragment, so use...
                            getListView().getContext(),
                            android.R.layout.simple_list_item_checked,
                            usernames);
                    // need to call setListAdapter for this activity.  This method is specifically from the ListActivity class
                    setListAdapter(adapter);
                } else {
                    // display a message to the user (copied from EditFriendsActivity)
                    // there was an error - log the message
                    Log.e(TAG, e.getMessage());
                    // display an alert to the user
                    // if there is a parse exception then...
                    AlertDialog.Builder builder = new AlertDialog.Builder(RouteRecipientsActivity.this);
                    // set the message from the exception
                    builder.setMessage(e.getMessage())
                            .setTitle(R.string.error_title)
                            .setPositiveButton(android.R.string.ok, null);
                    AlertDialog dialog = builder.create();
                    dialog.show();
                }
            }
        });

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_route_recipients, menu);

        // once the menu is inflated, we can can get a menu item object using the getItem() method of the menu that is passed in
        // use the int parameter to specify its position in the menu - since we only have 1 item, it will be at position 0
        mSendMenuItem = menu.getItem(0);
        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();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        } else if (id == R.id.action_send) {
            // create a parse object for our message

            ParseObject route = createRoute();

            // the message variable will be null if something goes wrong
            // so we only want to call the send() method if it is not null
            if (route == null) {
                // display error message
                AlertDialog.Builder builder = new AlertDialog.Builder(this);
                builder.setMessage(R.string.error_selecting_file)
                        .setTitle(R.string.error_selecting_file_title)
                        .setPositiveButton(android.R.string.ok, null);
                AlertDialog dialog = builder.create();
                dialog.show();
            } else {
                // create a send message that will accept the message as a parameter
                send(route);

                // In either case, we want to send the user back to the main activity right after the message is sent.
                // Use the activity method finish() to close the activity - this finishes the current activity and the
                // the previous activity (main activity) will be displayed in the message once again
                finish();
            }

            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    // change the visibility of the send button (set in menu_recipients.xml) whenever a a friend is selected
    // we create the menu in onCreateOptionsMenu
    @Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
        super.onListItemClick(l, v, position, id);

        // check the number of items that are checked on the list
        if (l.getCheckedItemCount() > 0) {
            // set the menuItem to visible if an item is clicked
            mSendMenuItem.setVisible(true);
        } else {
            // otherwise, if it is 0, then hide the menu item
            mSendMenuItem.setVisible(false);
        }

        // add a listener for the send button
        // menu items fire the onOptionsItemSelected() method (such as the home button)

    }

    protected ParseObject createRoute() {
        // create a new parse object called route
        // (we can create a whole new class of parse objects in the back end by simply using a new name)
        ParseObject route = new ParseObject(ParseConstants.CLASS_ROUTES);

        route.addAll(ParseConstants.KEY_LATLNGPOINTS, markerPoints);

        // now that we have an object, we can start adding data, using the key-value pairs...
        // first, get a String representation of the ID
        route.put(ParseConstants.KEY_SENDER_IDS, ParseUser.getCurrentUser().getObjectId());
        // put the senders name
        route.put(ParseConstants.KEY_SENDER_NAME, ParseUser.getCurrentUser().getUsername());
        // put the recipient ID's
        // get the selected friends from the list through the helper method getRecipientIds()
        route.put(ParseConstants.KEY_RECIPIENT_IDS, getRecipientIds());

        // return a successful route
        return route;
    }

    /**
     * method to return a collection of ID's
     *
     * @return
     */
    protected ArrayList<String> getRecipientIds() {
        ArrayList<String> recipientIds = new ArrayList<String>();
        // iterate though each user in the list
        for (int i = 0; i < getListView().getCount(); i++) {
            // if the user is checked on the recipients list
            if (getListView().isItemChecked(i)) {
                // add their ID to the array list
                recipientIds.add(mFriends.get(i).getObjectId());
            }
        }
        return recipientIds;
    }

    // method that uploads a file to the backend where recipients will be able to check for it
    protected void send(ParseObject route) {
        route.saveInBackground(new SaveCallback() {
            @Override
            public void done(ParseException e) {
                if (e == null) {
                    // successful
                    Toast.makeText(RouteRecipientsActivity.this, R.string.success_message, Toast.LENGTH_LONG).show();
                } else {
                    // there is an error - notify the user so they don't miss it
                    AlertDialog.Builder builder = new AlertDialog.Builder(RouteRecipientsActivity.this);
                    builder.setMessage(R.string.error_sending_message)
                            .setTitle(R.string.error_selecting_file_title)
                            .setPositiveButton(android.R.string.ok, null);
                    AlertDialog dialog = builder.create();
                    dialog.show();
                }
            }
        });
    }

}

包含LatLng值的数组排列如下:     [lat / lng:(54.58534930540805,-5.933924429118633),lat / lng:(54.587550929128106,-5.9355418011546135),lat / lng:(54.58754451793631,-5.93791488558054)]

有人能看到我在哪里错了吗?

1 个答案:

答案 0 :(得分:1)

Parse不知道LatLng是什么,您需要在ArrayList中使用名为ParseGeoPoint的特定于解析的对象,或者在保存时将所有LatLng转换为它们