com.hangulo.powercontact.ErrorContactsListFragment.java Source code

Java tutorial

Introduction

Here is the source code for com.hangulo.powercontact.ErrorContactsListFragment.java

Source

/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.hangulo.powercontact;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.support.v4.app.ListFragment;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v4.widget.CursorAdapter;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.QuickContactBadge;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

import com.hangulo.powercontact.data.PowerContactContract;
import com.hangulo.powercontact.model.PowerContactAddress;
import com.hangulo.powercontact.service.FetchPowerAddressIntentService;
import com.hangulo.powercontact.util.CircleTransform;
import com.squareup.picasso.Picasso;

import java.util.ArrayList;

/*
*   ================================================
*        Android Devlelopment Nanodegree
*        Project 8: Capstone, Stage 2 - Build
*        PowerContact by Kwanghyun Jung (ihangulo@gmail.com)
*   ================================================
*
*   date : Apr. 4th 2016
*
*    ErrorContactsListFragment.java
*    -------------
*      Fix problem
*     list of erorr sync
*
*
*/

// http://developer.android.com/training/contacts-provider/retrieve-names.html

public class ErrorContactsListFragment extends ListFragment
        implements AdapterView.OnItemClickListener, LoaderManager.LoaderCallbacks<Cursor> {

    final String LOG_TAG = ErrorContactsListFragment.class.getSimpleName();

    private static final int ERROR_CONTACT_LOADER = 0;
    private static final String LAST_DATA_ID_KEY = "LAST_DATA_ID_KEY";
    private static final String LAST_CONTACT_ID_KEY = "LAST_CONTACT_ID";
    private static final String LAST_LOOKUP_KEY = "LAST_LOOKUP_KEY";

    private boolean mTwoPane;

    private ContactsCursorAdapter mAdapter; // The main query adapter
    private ArrayList<PowerContactAddress> mErrorContactList;
    private View mRootView;
    private String mSearchKeyword = null; // searchString

    private int mPosition = ListView.INVALID_POSITION;
    public Spinner mSpinnerDistance;
    ImageView mBtnHomeUp; // ?   ( )

    long mLastContactId = -1;
    long mLastDataId = -1;
    String mLastLookupKey;

    public ErrorContactsListFragment() {
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mTwoPane = getResources().getBoolean(R.bool.two_pane);

        if (mErrorContactList == null)
            mErrorContactList = new ArrayList<>(0); // prevent null exception error

        mAdapter = new ContactsCursorAdapter(getActivity(), null, 0); // 
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        // Inflate the list fragment layout
        mRootView = inflater.inflate(R.layout.fragment_error_contact_list, container, false);
        getActivity().getSupportLoaderManager().initLoader(ERROR_CONTACT_LOADER, null, this);

        if (savedInstanceState != null) {

        }
        return mRootView;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        // Set up ListView, assign adapter and set some listeners. The adapter was previously
        // created in onCreate().
        setListAdapter(mAdapter);
        getListView().setOnItemClickListener(this);
        getListView().setChoiceMode(AbsListView.CHOICE_MODE_SINGLE);

        if (savedInstanceState != null) {

            mLastDataId = savedInstanceState.getLong(LAST_DATA_ID_KEY, -1);
            mLastContactId = savedInstanceState.getLong(LAST_CONTACT_ID_KEY, -1);
            mLastLookupKey = savedInstanceState.getString(LAST_LOOKUP_KEY, "");
        }

    }

    @Override
    public void onStart() {
        if (mPosition != ListView.INVALID_POSITION) {
            getListView().smoothScrollToPosition(mPosition); // restore listview
            getListView().setSelection(mPosition);
        }
        super.onStart();
    }

    // ? --> Quick view .
    // http://developer.android.com/intl/ko/training/contacts-provider/modify-data.html
    @Override
    public void onItemClick(AdapterView<?> parent, View v, int position, long id) {

        PowerContactAddress item = mErrorContactList.get(position); // ? ? ?  -->  .
        mPosition = position; //  ?? ?

        mLastDataId = item.getData_id();
        mLastContactId = item.getContact_id();
        mLastLookupKey = item.getLookup_key();
        Uri mSelectedContactUri = ContactsContract.Contacts.getLookupUri(mLastContactId, mLastLookupKey);
        // Creates a new Intent to edit a contact
        Intent editIntent = new Intent(Intent.ACTION_EDIT);
        /*
         * Sets the contact URI to edit, and the data type that the
         * Intent must match
         */
        editIntent.setDataAndType(mSelectedContactUri, ContactsContract.Contacts.CONTENT_ITEM_TYPE);
        // Sets the special extended data for navigation
        editIntent.putExtra("finishActivityOnSaveCompleted", true);
        // Sends the Intent
        getActivity().startActivityForResult(editIntent, Constants.RESULT_ERROR_CONTACTSLIST);

    }

    // ?  ?  ..  .
    public void onAddressChanged() {

        //  Toast.makeText(getActivity(), "GET CODE", Toast.LENGTH_LONG).show();

        // ok, then check if this address is effective & can saved
        // ..    ?, ?  ??  ? ??
        startIntentService();

    }

    boolean onFetching = false;
    private BroadcastReceiver messageReceiver;

    protected void startIntentService() {

        if (onFetching)
            return; // it cannot running twice same time.

        // register message receiver
        if (messageReceiver == null) {
            messageReceiver = new MessageReciever();
        }

        LocalBroadcastManager.getInstance(getActivity()).registerReceiver(messageReceiver,
                new IntentFilter(Constants.MESSAGE_EVENT)); //register receiver

        Intent intent = new Intent(getActivity(), FetchPowerAddressIntentService.class);
        intent.putExtra(Constants.DATA_ID_KEY, String.valueOf(mLastDataId));
        intent.putExtra(Constants.CONTACT_ID_KEY, String.valueOf(mLastContactId));
        intent.putExtra(Constants.LOOKUP_KEY, mLastLookupKey);
        getActivity().startService(intent);

    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        // save mSearchkeyword

        outState.putLong(LAST_DATA_ID_KEY, mLastDataId);
        outState.putLong(LAST_CONTACT_ID_KEY, mLastContactId);
        outState.putString(LAST_LOOKUP_KEY, mLastLookupKey);
        super.onSaveInstanceState(outState);

    }

    // contact adapter -------------------------------
    private class ContactsCursorAdapter extends CursorAdapter {

        public ContactsCursorAdapter(Context context, Cursor cursor, int flags) {
            super(context, cursor, 0);
        }

        @Override
        public View newView(Context context, Cursor cursor, ViewGroup parent) {
            View view = LayoutInflater.from(context).inflate(R.layout.error_contact_list_item, parent, false);

            ViewHolder viewHolder = new ViewHolder(view);
            view.setTag(viewHolder);

            return view;
        }

        @Override
        public void bindView(View view, Context context, Cursor cursor) {

            ViewHolder holder = (ViewHolder) view.getTag();

            long contact_id = cursor.getLong(INDEX_COL_CONTACT_ID);
            long data_id = cursor.getLong(INDEX_COL_DATA_ID);
            String lookup_key = cursor.getString(INDEX_COL_LOOKUP_KEY);
            String displayName = cursor.getString(INDEX_COL_NAME);
            String displayAddr = cursor.getString(INDEX_COL_ADDR);
            int type = cursor.getInt(INDEX_COL_TYPE);
            String label = cursor.getString(INDEX_COL_LABEL);
            double lat = cursor.getDouble(INDEX_COL_LAT);
            double lng = cursor.getDouble(INDEX_COL_LNG);
            String photo = cursor.getString(INDEX_COL_PHOTO); // photo
            int data_type = cursor.getInt(INDEX_COL_DATA_TYPE); // demo(0), normal(1), error(-1)

            // ?  
            String strStatusMsg = (data_type == PowerContactContract.PowerContactEntry.POWERCONTACT_MODE_NORMAL)
                    ? getString(R.string.title_status_ok)
                    : getString(R.string.title_status_error);

            Uri photoUri;
            if (photo == null || photo.length() == 0) {
                photo = "";
                photoUri = null;
            } else
                photoUri = Uri.parse(photo);

            holder.address.setText(displayAddr); // plain text
            holder.name.setText(displayName);
            holder.status_msg.setText(strStatusMsg); // ? ?

            // photo
            final Uri contactUri = ContactsContract.Contacts.getLookupUri(contact_id, lookup_key);

            // Binds the contact's lookup Uri to the QuickContactBadge
            holder.photo_thumbnail.assignContactUri(contactUri);

            if (photoUri != null) { // defalut

                // http://stackoverflow.com/questions/26112150/android-create-circular-image-with-picasso
                Picasso.with(getActivity()).load(photoUri).transform(new CircleTransform())
                        .into(holder.photo_thumbnail);
            } else {
                Picasso.with(getActivity()).load(R.drawable.ic_person_40dp).transform(new CircleTransform())
                        .into(holder.photo_thumbnail);
            }

        }

        private class ViewHolder {
            TextView name;
            TextView address;
            TextView status_msg;
            //ImageView photo_thumbnail;// ?  ??  ? 
            QuickContactBadge photo_thumbnail;

            public ViewHolder(View view) {
                name = (TextView) view.findViewById(R.id.name);
                address = (TextView) view.findViewById(R.id.address);
                status_msg = (TextView) view.findViewById(R.id.my_status); // ? 
                photo_thumbnail = (QuickContactBadge) view.findViewById(R.id.photo_thumbnail);

            }

        }

    }

    // Loader callback
    // Query index
    static final int INDEX_COL_COLUMN_ID = 0;
    static final int INDEX_COL_CONTACT_ID = 1;
    static final int INDEX_COL_DATA_ID = 2;
    static final int INDEX_COL_LOOKUP_KEY = 3;
    static final int INDEX_COL_NAME = 4;
    static final int INDEX_COL_ADDR = 5;
    static final int INDEX_COL_TYPE = 6;
    static final int INDEX_COL_LABEL = 7;
    static final int INDEX_COL_PHOTO = 8;
    static final int INDEX_COL_LAT = 9;
    static final int INDEX_COL_LNG = 10;
    static final int INDEX_COL_DATA_TYPE = 11;

    @Override
    public Loader<Cursor> onCreateLoader(int i, Bundle bundle) {

        String[] projection = { PowerContactContract.PowerContactEntry.COLUMN_ID, // cursor adapter? .
                PowerContactContract.PowerContactEntry.COLUMN_CONTACT_ID,
                PowerContactContract.PowerContactEntry.COLUMN_DATA_ID,
                PowerContactContract.PowerContactEntry.COLUMN_LOOKUP_KEY,
                PowerContactContract.PowerContactEntry.COLUMN_NAME,
                PowerContactContract.PowerContactEntry.COLUMN_ADDR,
                PowerContactContract.PowerContactEntry.COLUMN_TYPE,
                PowerContactContract.PowerContactEntry.COLUMN_LABEL,
                PowerContactContract.PowerContactEntry.COLUMN_PHOTO,
                PowerContactContract.PowerContactEntry.COLUMN_LAT,
                PowerContactContract.PowerContactEntry.COLUMN_LNG,
                PowerContactContract.PowerContactEntry.COLUMN_CONTACT_DATA_TYPE, };

        Log.v(LOG_TAG, "LOADER:MainActivity/onCreateLoader : ");

        return new CursorLoader(getActivity(),
                PowerContactContract.PowerContactEntry
                        .buildLocationByMode(PowerContactContract.PowerContactEntry.POWERCONTACT_MODE_ERROR), // only error status
                projection, // projection // only works
                null, // cols for "where" clause // ignored  ?
                null, // values for "where" clause // ignored  ?
                PowerContactContract.PowerContactEntry.COLUMN_NAME + " ASC"); // sort order --> by name);
    }

    @Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor data) {

        //Log.v(LOG_TAG, "LOADER:MainActivity/onLoaderFinished : cursor num " + cursor.getCount());

        //  if (cursor==null) return;

        mErrorContactList.clear(); // first clear!

        if (data.moveToFirst()) {
            do {
                long contact_id = data.getLong(INDEX_COL_CONTACT_ID);
                long data_id = data.getLong(INDEX_COL_DATA_ID);
                String lookup_key = data.getString(INDEX_COL_LOOKUP_KEY);
                String name = data.getString(INDEX_COL_NAME);
                String addr = data.getString(INDEX_COL_ADDR);
                int type = data.getInt(INDEX_COL_TYPE);
                String label = data.getString(INDEX_COL_LABEL);
                double lat = data.getDouble(INDEX_COL_LAT);
                double lng = data.getDouble(INDEX_COL_LNG);
                //double dist = cursor.getDouble(INDEX_COL_DISTANCE); // distance
                String photo = data.getString(INDEX_COL_PHOTO); // photo
                mErrorContactList.add(new PowerContactAddress(contact_id, data_id, lookup_key, name, addr, type,
                        label, photo, lat, lng, 0));

            } while (data.moveToNext());
        }

        mAdapter.swapCursor(data);
        //
    }

    @Override
    public void onLoaderReset(Loader<Cursor> loader) {

        mAdapter.swapCursor(null);
    }

    // Broadcast receiver ====================================================================
    // get message from
    private class MessageReciever extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            int result = intent.getIntExtra(Constants.RESULT_KEY, Constants.FAILURE_RESULT);
            String msgKey = intent.getStringExtra(Constants.MESSAGE_KEY);
            if (msgKey != null)
                Toast.makeText(getActivity(), intent.getStringExtra(Constants.MESSAGE_KEY), Toast.LENGTH_LONG)
                        .show();

            //  .. retry ...  ?
            // ? ? progress integer    ?? . pass1 pass2?....

            switch (result) {
            // if message contains "service is ended" then delete it's result
            case Constants.SUCCESS_RESULT:
            case Constants.FAILURE_RESULT:

                Log.v(LOG_TAG, "Loader restarted");
                getActivity().getSupportLoaderManager().restartLoader(ERROR_CONTACT_LOADER, null,
                        ErrorContactsListFragment.this);

                LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(messageReceiver);
                messageReceiver = null;
                break;

            case Constants.START_LOADING:
                break;
            }
        }
    }

}