0

So I have this little application where you can call from. In this application, You will be able to log in with your phone-number and get a number from our server (This is not implemented YET)

Depending on "Who you are", our server will give you a number dynamically.

This is not really relevant, but it still has some things to do with my question.

Since our server gives the number, I can't make a "Recent List" with the info I get from Android CallLogs. (It may get numbers A.E "Mom" into your professional contact list, etc etc)

So what I'm doing now, is after each call, insert the info (Name,Number,Date and Duration) Into an Array List.

recentCalls.add(new Recent(aName, aDate, aNumber, "0"));

(0 stands for Seconds, of Duration. Still not completed.)

It would "Save" in the app momentarily, and when the application is fully killed (Or Crashes), everything would be emptied out.

I have considered Saving the Array list in SharedPreferences.

But since we're going to limit the recents to 100, this will be too big.

I have read this: Android Storage Options Either way, I AM still getting all the call logs from the phone itself, for testing purposes.

My questions are:

  • How could I save an ArrayList Safely and Efficiently
  • If I'm not going to work with an ArrayList, How could I "Format" the ACTUAL phone's call_logs to only show numbers dialed from my app. (In order to call "Through" our server, we use "ServerPhoneNumber" + "," + "Inserted PhoneNumber" - Example: 123456789,987654321)
  • Could I say Check if 1st 10 characters equal to "123456789"? Which is not possible, since it changes the number depending on the person.

Here's my Java Code:

package com.example.dragonphone;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.ContentResolver;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.graphics.Color;
import android.graphics.LightingColorFilter;
import android.net.Uri;
import android.os.Bundle;
import android.os.Vibrator;
import android.preference.PreferenceManager;
import android.provider.BaseColumns;
import android.provider.CallLog;
import android.provider.ContactsContract;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TabHost;
import android.widget.TabHost.TabSpec;
import android.widget.TextView;
import android.widget.Toast;

public class Tabs extends Activity implements OnClickListener, OnLongClickListener{
    TabHost th;
    TabSpec specs;
    TextView numberfield;
    ListView recents;
    public String string,number;
    private List<Recent> recentCalls = new ArrayList<Recent>();
    public int counter;
    Button n1,n2,n3,n4,n5,n6,n7,n8,n9,n0,nstar,nhash,sms,contact,call,clear,clearhistory,getinfo;
    //ImageView call, clear;
    public Vibrator vib; 
    //public String phoneNumber;
    String date = new SimpleDateFormat("dd-MM-yyyy").format(new Date());



    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.tabs);
        th = (TabHost)findViewById(R.id.tabhost);
        numberfield = (TextView) findViewById(R.id.etNumberField);
        n1 = (Button) findViewById (R.id.bNumber1);
        n2 = (Button) findViewById (R.id.bNumber2);
        n3 = (Button) findViewById (R.id.bNumber3);
        n4 = (Button) findViewById (R.id.bNumber4);
        n5 = (Button) findViewById (R.id.bNumber5);
        n6 = (Button) findViewById (R.id.bNumber6);
        n7 = (Button) findViewById (R.id.bNumber7);
        n8 = (Button) findViewById (R.id.bNumber8);
        n9 = (Button) findViewById (R.id.bNumber9);
        nstar = (Button) findViewById (R.id.bNumberStar);
        n0 = (Button) findViewById (R.id.bNumber0);
        nhash = (Button) findViewById (R.id.bNumberHash);
        call = (Button) findViewById (R.id.bCall);
        sms = (Button) findViewById (R.id.bSMS);
        clear = (Button) findViewById (R.id.bClear);
        contact = (Button) findViewById (R.id.bContact);
        recents = (ListView) findViewById (R.id.recentList);
        clearhistory = (Button) findViewById (R.id.bClearHistory);
        getinfo = (Button) findViewById (R.id.bGetCallDetails);


        populateRecentList();
        populateListView();
        registerClickCallback();

        th.setBackgroundColor(Color.rgb(202, 233, 252));
        //n1.getBackground().setColorFilter(new LightingColorFilter(0x000033, 0x000099));
        sms.getBackground().setColorFilter(new LightingColorFilter(0xFFFF66, 0xFFFF00));
        vib = (Vibrator) getSystemService(VIBRATOR_SERVICE);



        n1.setOnClickListener(this);
        n2.setOnClickListener(this);
        n3.setOnClickListener(this);
        n4.setOnClickListener(this);
        n5.setOnClickListener(this);
        n6.setOnClickListener(this);
        n7.setOnClickListener(this);
        n8.setOnClickListener(this);
        n9.setOnClickListener(this);
        nstar.setOnClickListener(this);
        n0.setOnClickListener(this);
        n0.setOnLongClickListener(this);
        nhash.setOnClickListener(this);
        call.setOnClickListener(this);
        clear.setOnClickListener(this);
        clear.setOnLongClickListener(this);
        sms.setOnClickListener(this);
        contact.setOnClickListener(this);
        clearhistory.setOnClickListener(this);
        getinfo.setOnClickListener(this);

        th.setup();
        specs = th.newTabSpec("tag1");
        specs.setContent(R.id.Recents);
        specs.setIndicator("Recent Calls");
        th.addTab(specs);

        specs = th.newTabSpec("tag2");
        specs.setContent(R.id.Keypad);
        specs.setIndicator("Keypad");
        th.addTab(specs);

        specs = th.newTabSpec("tag3");
        specs.setContent(R.id.Sms);
        specs.setIndicator("SMS");
        th.addTab(specs);

        specs = th.newTabSpec("tag4");
        specs.setContent(R.id.Ratings);
        specs.setIndicator("Rates");
        th.addTab(specs);

        specs = th.newTabSpec("tag5");
        specs.setContent(R.id.Account);
        specs.setIndicator("Account");
        th.addTab(specs);


    }

    private void populateRecentList() {
         //TODO Auto-generated method stub
        recentCalls.add(new Recent("Zach", "01-12-2013", "064555246", "600"));
        recentCalls.add(new Recent("Adam", "11-12-2013", "00355563315","510"));
        recentCalls.add(new Recent("John", "03-12-2013", "00955587", "100"));
        recentCalls.add(new Recent("Jorge", "15-10-2013" , "445559585", "60"));

    }
    private void populateListView() {
        // TODO Auto-generated method stub
        ArrayAdapter<Recent> adapter = new MyRecentAdapter();
        ListView list = (ListView) findViewById(R.id.recentList);
        list.setAdapter(adapter);

    }
    private class MyRecentAdapter extends ArrayAdapter<Recent>{
        public MyRecentAdapter(){
            super(Tabs.this, R.layout.recents_view, recentCalls);

        }


    @Override
    public View getView(int position, View convertView, ViewGroup parent){
        //Make sure we have a view to work with
        View itemView = convertView;
        if(itemView == null)
        {
            itemView = getLayoutInflater().inflate(R.layout.recents_view, parent,false);
        }
        Recent currentCall =  recentCalls.get(position);

        TextView nameText = (TextView) itemView.findViewById(R.id.tvRecentName);
        nameText.setText(currentCall.getName());

        TextView numberText = (TextView) itemView.findViewById(R.id.tvRecentNumber);
        numberText.setText(currentCall.getPn());

        TextView dateText = (TextView) itemView.findViewById(R.id.tvRecentDate);
        dateText.setText("" + currentCall.getDate());

        TextView durationText = (TextView) itemView.findViewById(R.id.tvRecentDuration);
        durationText.setText("" + currentCall.getDuration());

        return itemView;
        //      return super.getView(position, convertView, parent);

    }

}
    private void registerClickCallback() {
        // TODO Auto-generated method stub
        ListView list = (ListView) findViewById(R.id.recentList);
        list.setOnItemClickListener(new AdapterView.OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> parent, View viewClicked, int position,
                    long id) {
                // TODO Auto-generated method stub
                Recent clickedCall = recentCalls.get(position);
                String name = clickedCall.getName();
                numberfield.setText(clickedCall.getPn());
                counter = numberfield.getText().toString().length();
                String message = "Calling " + name;
                Context context = getApplicationContext();
                int duration = Toast.LENGTH_SHORT;

                Toast toast = Toast.makeText(context, message, duration);
                toast.show();
                call();
            }



        });

    }

    @Override
    public void onClick(View arg0) {
        // TODO Auto-generated method stub
        switch(arg0.getId()){
        case R.id.bNumber1:
            numberfield.setText(numberfield.getText() + "1");
            addCheck();
            vib.vibrate(25);
            break;
        case R.id.bNumber2:
            numberfield.setText(numberfield.getText() + "2");
            addCheck();
            vib.vibrate(25);
            break;

        case R.id.bNumber3:
            numberfield.setText(numberfield.getText() + "3");
            addCheck();
            vib.vibrate(25);
            break;
        case R.id.bNumber4:
            numberfield.setText(numberfield.getText() + "4");
            addCheck();
            vib.vibrate(25);
            break;
        case R.id.bNumber5:
            numberfield.setText(numberfield.getText() + "5");
            addCheck();
            vib.vibrate(25);
            break;
        case R.id.bNumber6:
            numberfield.setText(numberfield.getText() + "6");
            addCheck();
            vib.vibrate(25);
            break;
        case R.id.bNumber7:
            numberfield.setText(numberfield.getText() + "7");
            addCheck();
            vib.vibrate(25);
            break;
        case R.id.bNumber8:
            numberfield.setText(numberfield.getText() + "8");
            addCheck();
            vib.vibrate(25);
            break;
        case R.id.bNumber9:
            numberfield.setText(numberfield.getText() + "9");
            addCheck();
            vib.vibrate(25);
            break;
        case R.id.bNumberStar:
            numberfield.setText(numberfield.getText() + "*");
            addCheck();
            vib.vibrate(25);
            break;
        case R.id.bNumber0:
            numberfield.setText(numberfield.getText() + "0");
            addCheck();
            vib.vibrate(25);
            break;
        case R.id.bNumberHash:
            numberfield.setText(numberfield.getText() + "#");
            addCheck();
            vib.vibrate(25);
            break;

        case R.id.bClear:
            String number = numberfield.getText().toString();
            if(number.length() > 0){
                String newNumber = number.substring(0, number.length()-1);
                        numberfield.setText(newNumber);
                        deleteCheck();
                        vib.vibrate(25);
            }else{
                Context context = getApplicationContext();
                CharSequence text = "The numbers are already cleared.";
                int duration = Toast.LENGTH_SHORT;

                Toast toast = Toast.makeText(context, text, duration);
                toast.show();
            }

            break;
        case R.id.bCall:
            call();

            break;
        case R.id.bContact:
             Intent intent = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI);
              startActivityForResult(intent, 1);   
            break;
        case R.id.bClearHistory:
            recentCalls.clear();
            CharSequence text = "Your recent list has been cleared.";
            int duration = Toast.LENGTH_SHORT;

            Toast toast = Toast.makeText(this, text, duration);
            toast.show();
            th.setCurrentTabByTag("tag1");
            break;
        case R.id.bSMS:
            th.setCurrentTabByTag("tag3");
            CharSequence text2 = "This function is still under construction..";
            int duration2 = Toast.LENGTH_LONG;

            Toast toast2 = Toast.makeText(this, text2, duration2);
            toast2.show();
            break;
        case R.id.bGetCallDetails:
                getCallDetails();
                break;



        }
    }
    private void deleteCheck() {
        // TODO Auto-generated method stub
        counter --;
        if(counter < 14){
            numberfield.setTextSize(25);  //Set text size when amount goes lower.
        }
        if(counter >= 14 && counter < 16){
            numberfield.setTextSize(20);  //Set text size when amount goes lower.
        }
        if(counter >= 16 && counter < 18){
            numberfield.setTextSize(18);
        }
        if(counter >= 18 && counter < 20){
            numberfield.setTextSize(16);
        }
    }
    private void addCheck() {

        // TODO Auto-generated method stub
        counter++;
        if(counter >= 14){
            numberfield.setTextSize(20);  //Set text size when amount goes higher.
            //numberfield.setMaxHeight(10);
        }
        if(counter >= 16){
            numberfield.setTextSize(18);  //Set text size when amount goes higher.
        }
        if(counter >= 18){
            numberfield.setTextSize(16);  //Set text size when amount goes higher.
        }
        if(counter >= 20){
            numberfield.setTextSize(14);  //Set text size when amount goes higher.
        }

        if(counter < 14){
            numberfield.setTextSize(25);  //Set text size when amount goes lower.
        }
        if(counter >= 14 && counter < 16){
            numberfield.setTextSize(20);  //Set text size when amount goes lower.
        }
        if(counter >= 16 && counter < 18){
            numberfield.setTextSize(18);
        }
        if(counter >= 18 && counter < 20){
            numberfield.setTextSize(16);
        }


    }
    private void getCallDetails() {
        StringBuilder sb = new StringBuilder();
        Uri contacts = CallLog.Calls.CONTENT_URI;
        Cursor managedCursor = this.getContentResolver().query(contacts, null, null, null,CallLog.Calls.DATE + " DESC LIMIT 100");
        int number = managedCursor.getColumnIndex(CallLog.Calls.NUMBER);
        int type = managedCursor.getColumnIndex(CallLog.Calls.TYPE);
        int date = managedCursor.getColumnIndex(CallLog.Calls.DATE);
        int duration = managedCursor.getColumnIndex(CallLog.Calls.DURATION);
        sb.append("Call Details :");
        while (managedCursor.moveToNext()) {



            String phNumber = managedCursor.getString(number);
            String callType = managedCursor.getString(type);
            String callDate = managedCursor.getString(date);
            String callDayTime = new Date(Long.valueOf(callDate)).toString();
            // long timestamp = convertDateToTimestamp(callDayTime);
            String callDuration = managedCursor.getString(duration);
            String dir = null;
            int dircode = Integer.parseInt(callType);
            switch (dircode) {
            case CallLog.Calls.OUTGOING_TYPE:
                dir = "OUTGOING";
                break;

            case CallLog.Calls.INCOMING_TYPE:
                dir = "INCOMING";
                break;

            case CallLog.Calls.MISSED_TYPE:
                dir = "MISSED";
                break;
            }
            sb.append("\nPhone Number:--- " + phNumber + " \nCall Type:--- " + dir + " \nCall Date:--- " + callDayTime + " \nCall duration in sec :--- " + callDuration);
            sb.append("\n----------------------------------");


        }
        managedCursor.close();
        System.out.println(sb);
    }
private void call() {
        // TODO Auto-generated method stub
        if(number.length() > 0){
        try {
               Intent callIntent = new Intent(Intent.ACTION_CALL);
                String dsPhoneNumber = "+34965063314,"; // Dynamic number
                    //965063064 
                string = numberfield.getText().toString().trim();                      
                   number = "tel:" + dsPhoneNumber + string;
                callIntent.setData(Uri.parse(number));
                startActivity(callIntent);
                //recentCalls.add(new Recent(aName, aDate, aNumber, "0"));






            } catch (ActivityNotFoundException activityException) {
                 Log.e("helloandroid dialing example", "Call failed");


            }
        }else {
            Context context = getApplicationContext();
            CharSequence text = "Please insert a phone number or choose a contact.";
            int duration = Toast.LENGTH_SHORT;

            Toast toast = Toast.makeText(context, text, duration);
            toast.show();
        }

    }
    @Override
    public boolean onLongClick(View arg0) {
        // TODO Auto-generated method stub
        switch(arg0.getId()){
        case R.id.bClear:
        if(counter != 0){
            counter = 0;
            numberfield.setTextSize(25);
        numberfield.setText("");
        vib.vibrate(100);}
        else{
            Context context = getApplicationContext();
            CharSequence text = "The numbers are already cleared.";
            int duration = Toast.LENGTH_SHORT;

            Toast toast = Toast.makeText(context, text, duration);
            toast.show();
        }
        break;
        case R.id.bNumber0:

            numberfield.setText(numberfield.getText() + "+");
            addCheck();
            vib.vibrate(25);
            break;
        }
        return true;

    }
    public void onActivityResult(int reqCode, int resultCode, Intent data) {

        if(resultCode == RESULT_OK && data != null) {
            Uri uri = data.getData();

            Cursor cursor=this.getContentResolver().query(uri, null, null, null, null);

            while (cursor.moveToNext()) { 
                String contactId = cursor.getString(cursor.getColumnIndex( 
                        ContactsContract.Contacts._ID)); 
                String hasPhone = cursor.getString(cursor.getColumnIndex( 
                        ContactsContract.Contacts.HAS_PHONE_NUMBER)); 
                if (Integer.parseInt(cursor.getString( cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))) > 0) { 
                    // You now have the number so now query it like this
                    Cursor phones = getContentResolver().query( 
                            ContactsContract.CommonDataKinds.Phone.CONTENT_URI, 
                            null, 
                            ContactsContract.CommonDataKinds.Phone.CONTACT_ID +" = "+ contactId, 
                            null, null); 
                    while (phones.moveToNext()) { 
                        String phoneNumber = phones.getString( 
                                phones.getColumnIndex( 
                                        ContactsContract.CommonDataKinds.Phone.NUMBER));  
                        numberfield.setText(phoneNumber);
                        counter = numberfield.getText().toString().length();
                        /*if(counter == 0){

                                Context context = getApplicationContext();
                                //CharSequence text = counter;
                                int duration = Toast.LENGTH_SHORT;

                                Toast toast = Toast.makeText(context, counter, duration);
                                toast.show();

                        }*/
                    } 
                    phones.close(); 


                }
            }

        }
    }
}

Thanks in Advance!

EDIT

private void registerClickCallback() {
        // TODO Auto-generated method stub
        ListView list = (ListView) findViewById(R.id.recentList);
        list.setOnItemClickListener(new AdapterView.OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> parent, View viewClicked, int position,
                    long id) {
                // TODO Auto-generated method stub
                Recent clickedCall = recentCalls.get(position);
               // String name = clickedCall.getName();
                //numberfield.setText(clickedCall.getPn());
                counter = numberfield.getText().toString().length();
               // String message = getResources().getString(R.string.toastCalling) + " " + name + " " + getResources().getString(R.string.toastCalling2); 
                Context context = getApplicationContext();
                int duration = Toast.LENGTH_SHORT;

                //Toast toast = Toast.makeText(context, message, duration);
                //toast.show();
                call();
            }



        });

    }

This is my current call method. (Commented out stuff since it's not like the old code anymore.)

Basically whenever I click call,

case R.id.bCall:   
call();

The Call function:

private void call() {
        // TODO Auto-generated method stub
        if(numberfield.length() > 0){
        try {
               Intent callIntent = new Intent(Intent.ACTION_CALL);
                String dsPhoneNumber = "+34965063314,"; 
                // Dynamic number
                    //965063064 
             String string = numberfield.getText().toString().trim();                      
                 number = "tel:" + dsPhoneNumber + string;
                callIntent.setData(Uri.parse(number));
                startActivity(callIntent);
                //recentCalls.add(new Recent(aName, aDate, aNumber, "0"));






            } catch (ActivityNotFoundException activityException) {
                 Log.e("helloandroid dialing example", "Call failed");


            }
        }else {
            Context context = getApplicationContext();
            CharSequence text = getResources().getText(R.string.keypadViewToastEmptyNumber);
            int duration = Toast.LENGTH_SHORT;

            Toast toast = Toast.makeText(context, text, duration);
            toast.show();
        }

    }

It needs to Insert it in the "List" and show it on the Recents tab. I've spent a couple of hours trying to solve this, No progress. Thanks in advance!

Edit #2

 public View getView(int position, View convertView, ViewGroup parent){
        //Make sure we have a view to work with
        View itemView = convertView;
        if(itemView == null)
        {
            itemView = getLayoutInflater().inflate(R.layout.recents_view, parent,false);
        }
        Recent currentCall =  recentCalls.get(position);

        TextView nameText = (TextView) itemView.findViewById(R.id.tvRecentName);
        nameText.setText(currentCall.getName());

        TextView numberText = (TextView) itemView.findViewById(R.id.tvRecentNumber);
        numberText.setText(currentCall.getPn());

        TextView dateText = (TextView) itemView.findViewById(R.id.tvRecentDate);
        dateText.setText("" + currentCall.getDate());

        TextView durationText = (TextView) itemView.findViewById(R.id.tvRecentDuration);
        durationText.setText("" + currentCall.getDuration());

        return itemView;
        //      return super.getView(position, convertView, parent);

    }

}

So this is the view of the recents tab. The .getDate/.getDuration etc are changed, What should the "new one" be? So basically read

Kara
  • 6,115
  • 16
  • 50
  • 57
Paramone
  • 2,634
  • 4
  • 31
  • 58
  • Why don't you store our data in json format if you really want to write data to a file. It would be super easy to parse as well and you can use Gson. I would just use a sqllite database, which seems most logical to me, then you can query for the 100 most recent numbers. – Sun Dec 13 '13 at 14:39

1 Answers1

2

What I would do is the following:

  • Get a java.io.File to a local (/data/data/f.q.c.n/files/recents) file
  • Open a (buffered) FileOutputStream to it
  • Write the elements of the ArrayList<Recent> to the file
    • Write the name as byte-array (String.getBytes)
    • Write the date as a long (since epoch)
    • Write the number as a string (as there can be different formats)
    • Write the duration as an int
    • Note that long and int are fixed-size and therefore can be read easily
    • You can prefix the byte-array with an int, indicating it's size

Then, of course, you do the same thing in reverse on startup, to rebuild that ArrayList.

Someone called this approach controlled binary serialization. Of course you can have it easier, but it's not really hard to do and you get rid of all reflection (which can have awful performance on early Android devices). This is the fastest (smoothest) approach I can think of.

I didn't choose standard Serialization because it sucks (Tons of reflection and metadata). Note that SharedPreferences have been successfully (ab-) used to store much larger data than you have.

Example:

IO.java:

import java.io.IOException;

public interface IO {

    void write(DataOutputStream out) throws IOException;

    void read(DataInputStream in) throws IOException;

}

Recent.java:

import java.io.IOException;
import java.util.Date;

public class Recent implements IO {

    private String name, number;
    private Date date;
    private int duration; // in milliseconds

    public Recent(String name, String number, Date date, int duration) {
        this.name = name;
        this.number = number;
        this.date = date;
        this.duration = duration;
    }

    public Recent() {
        this(null, null, null, 0);
    }

    @Override
    public void write(DataOutputStream out) throws IOException {
        byte[] nameData = name.getBytes("UTF-8");
        out.writeInt(nameData.length);
        out.write(nameData);

        byte[] numberData = number.getBytes("UTF-8");
        out.writeInt(numberData.length);
        out.write(numberData);

        out.writeLong(date.getTime());

        out.writeInt(duration);
    }

    @Override
    public void read(DataInputStream in) throws IOException {
        int nameDataLength = in.readInt();
        if (nameDataLength > 100000) throw new IllegalStateException("Name shouldn't be this long: " + nameDataLength);
        byte[] nameData = new byte[nameDataLength];
        in.readFully(nameData);
        name = new String(nameData, "UTF-8");

        int numberDataLength = in.readInt();
        if (numberDataLength > 100000) throw new IllegalStateException("Number shouldn't be this long: " + nameDataLength);
        byte[] numberData = new byte[numberDataLength];
        in.readFully(numberData);
        number = new String(numberData, "UTF-8");

        date = new Date(in.readLong());

        duration = in.readInt();
    }

}

RecentsList.java:

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

public class RecentsList implements IO {

    private List<Recent> recents;

    public RecentsList() {
        recents = new ArrayList<Recent>();
    }

    public void addRecent(Recent recent) {
        recents.add(recent);
    }

    @Override
    public void write(DataOutputStream out) throws IOException {
        out.writeInt(recents.size());
        for (Recent r : recents) {
            r.write(out);
        }
    }

    @Override
    public void read(DataInputStream in) throws IOException {
        int size = in.readInt();
        recents = new ArrayList<Recent>(size);
        for (int i = 0; i < size; i++) {
            Recent r = new Recent();
            r.read(in);
            recents.add(r);
        }
    }

    public static void main(String[] args) throws IOException {
        RecentsList test = new RecentsList();

        // build test data
        for (int i = 0; i < 100; i++) {
            String iString = Integer.toString(i);
            Recent r = new Recent(iString, iString, new Date(), i);
            test.addRecent(r);
        }

        // write
        File out = new File("/home/till/recents.bin");
        DataOutputStream dataOut = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(out)));
        test.write(dataOut);
        dataOut.close();

        // read
        RecentsList read = new RecentsList();
        DataInputStream dataIn = new DataInputStream(new BufferedInputStream(new FileInputStream(out)));
        read.read(dataIn);
        dataIn.close();

        System.out.println("read now contains same data as test if everything went ok");
    }

}

Note:

  • You will wan't to simplify writing and reading a byte-array. I do that myself but didn't include it for briefness (it's long enough already)
  • The imports for the Data[Input|Output]Stream are missing
  • You may wan't to change the size for the exception
  • You can shrink the ints for small numbers

If you have any problems/questions, don't hesitate to comment!

tilpner
  • 4,351
  • 2
  • 22
  • 45
  • Hey, Thank you for your answer, I'm trying/writing it as we speak. I'll keep you updated, Pretty sure this is the correct answer. Thanks @StackOverflowException! – Paramone Dec 13 '13 at 12:25
  • Hi, I've been trying for a while now, Looked up some tutorials.. But I couldn't figure out how to change my ArrayList into Bytes. Could you give me a small example? – Paramone Dec 13 '13 at 14:00
  • I understand. Do you possibly have a link that could be useful? I couldn't find anything helpful. http://stackoverflow.com/questions/5618978/convert-arrayliststring-to-byte This helped me a Little, but not completely. – Paramone Dec 13 '13 at 14:02
  • 1
    @Paramone: That way you should be able to write thousands of recents efficiently. – tilpner Dec 13 '13 at 14:38
  • Hey SOE, We've taken a "break" from this project, and I recently started on it. I've literally copy/pasted your example, added classes/interfaces. How exactly do I add my data in the list, and "Show" it in my list? -- Check my edited question for details – Paramone Dec 20 '13 at 14:24
  • @Paramone: It seems to me this has nothing to do with the file serialization... But what's wrong with the commented line `recentCalls.add(new Recent(aName, aDate, aNumber, "0"));`? Any Stacktrace? – tilpner Dec 20 '13 at 14:34
  • The Constructor, Trying to fix it, give me a second – Paramone Dec 20 '13 at 14:39
  • @Paramone: How about swapping number and date? – tilpner Dec 20 '13 at 14:41
  • Should I leave the date as "null" ? What should I leave it as? Any format? Edit: recentCalls.add(new Recent("Adam","06222556246",null,510)); doesn't give any errors. – Paramone Dec 20 '13 at 14:43
  • Uhm, that's up to you... If you wan't a Date for the current time, use `new Date()`. – tilpner Dec 20 '13 at 14:46
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/43603/discussion-between-paramone-and-stackoverflowexception) – Paramone Dec 20 '13 at 14:47