How to read and write from file

JSON

It’s very esay to read and write from a file.

Download code

public static void writeToFile(String data, Activity activity) {
		try {
			OutputStreamWriter outputStreamWriter = new OutputStreamWriter(
					activity.openFileOutput("config.txt", Context.MODE_PRIVATE));
			outputStreamWriter.write(data);
			outputStreamWriter.close();
		} catch (IOException e) {
			Log.e("Exception", "File write failed: " + e.toString());
		}
	}

	public static String readFromFile(Activity activity) {

		String ret = "";

		try {
			InputStream inputStream = activity.openFileInput("config.txt");

			if (inputStream != null) {
				InputStreamReader inputStreamReader = new InputStreamReader(
						inputStream);
				BufferedReader bufferedReader = new BufferedReader(
						inputStreamReader);
				String receiveString = "";
				StringBuilder stringBuilder = new StringBuilder();

				while ((receiveString = bufferedReader.readLine()) != null) {
					stringBuilder.append(receiveString);
				}

				inputStream.close();
				ret = stringBuilder.toString();
			}
		} catch (FileNotFoundException e) {
			Log.e("login activity", "File not found: " + e.toString());
		} catch (IOException e) {
			Log.e("login activity", "Can not read file: " + e.toString());
		}
		 return ret;
	}

How to use Retrofit library

Retrofit parse JSON of your web service. Use Retrofit library is very simple

Retrofit turns your REST API into a Java interface.

you can download this example from here

You need these librarires.

JSON

Then you can get your JSON, We use this chrome app. Now you can build your model from JSON in this web

You create a new class which name is RestClient

package com.thedeveloperworldisyours.simpleretrofic.webservice;

import retrofit.Callback;
import retrofit.RestAdapter;
import retrofit.RetrofitError;
import retrofit.client.OkClient;
import retrofit.client.Response;
import retrofit.http.GET;
import retrofit.http.Query;
import android.os.Handler;
import android.util.Log;

import com.squareup.okhttp.OkHttpClient;
import com.thedeveloperworldisyours.simpleretrofic.model.Question;
import com.thedeveloperworldisyours.simpleretrofic.utils.Constants;

public class RestClient {

	public interface ClientInterface{
		  @GET("/questions")
		  void getQuestions( @Query("sort") String sort, @Query("site") String site,@Query("pagesize") String pagesize,@Query("page") String page, Callback<Question> callback);
		}

	public static ClientInterface initRestAdapter()
    {
        OkHttpClient client = new OkHttpClient();

        return (ClientInterface) new RestAdapter.Builder()
                .setClient(new OkClient(client))
                .setEndpoint(Constants.URL)
                .build()
                .create(ClientInterface.class);
    }
	public static void GetQuestions(final Handler mHandler) {
		Callback<Question> callback = new Callback<Question>() {

			@Override
			public void failure(RetrofitError resp) {
				Log.v("failure", String.valueOf(resp.getMessage()));
			}

			@Override
			public void success(Question info, Response resp) {
				Log.v("success", String.valueOf(resp.getStatus()));
			}
		};
		RestClient.initRestAdapter().getQuestions(Constants.SORT, Constants.SITE,
				Constants.PAGESIZE, Constants.PAGE, callback);
	}

}

Now in your MainActivity put this:

package com.thedeveloperworldisyours.simpleretrofic;

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

import retrofit.Callback;
import retrofit.RetrofitError;
import retrofit.client.Response;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.HeaderViewListAdapter;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.Toast;

import com.thedeveloperworldisyours.simpleretrofic.model.Question;
import com.thedeveloperworldisyours.simpleretrofic.utils.Constants;
import com.thedeveloperworldisyours.simpleretrofic.utils.Utils;
import com.thedeveloperworldisyours.simpleretrofic.webservice.RestClient;

public class MainActivity extends ActionBarActivity {

	List<String> mListTitle = new ArrayList<String>();
	private ListView mListView;

		protected ListView getListView() {
		    if (mListView == null) {
		        mListView = (ListView) findViewById(android.R.id.list);
		    }
		    return mListView;
		}

		protected void setListAdapter(ListAdapter adapter) {
		    getListView().setAdapter(adapter);
		}

		protected ListAdapter getListAdapter() {
		    ListAdapter adapter = getListView().getAdapter();
		    if (adapter instanceof HeaderViewListAdapter) {
		        return ((HeaderViewListAdapter)adapter).getWrappedAdapter();
		    } else {
		        return adapter;
		    }
		}

	public void onCreate(Bundle icicle) {
		super.onCreate(icicle);
		setContentView(R.layout.activity_main);
		getQuestionCheckInternet();

	}

	@Override
    public boolean onCreateOptionsMenu(Menu menu)
    {
        MenuInflater menuInflater = getMenuInflater();
        menuInflater.inflate(R.menu.main, menu);
        return true;
    }
	@Override
    public boolean onOptionsItemSelected(MenuItem item)
    {

        switch (item.getItemId())
        {
        case R.id.action_refresh:
        	refreshList();
        	if(Utils.isOnline(MainActivity.this)){
    			Toast.makeText(this, R.string.action_refresh, Toast.LENGTH_SHORT).show();
    		}
            return true;

        default:
            return super.onOptionsItemSelected(item);
        }
        }
	public void refreshList(){
		mListTitle.clear();
		getQuestionCheckInternet();
		createList();

	}

	public void getQuestionCheckInternet(){
		if(Utils.isOnline(MainActivity.this)){
			getQuestions();
		}else{
			Toast.makeText(this, R.string.info_offline, Toast.LENGTH_LONG).show();
		}
	}

	protected void onListItemClick(ListView lv, View v, int position, long id) {
	    getListView().getOnItemClickListener().onItemClick(lv, v, position, id);
	    String item = (String) getListAdapter().getItem(position);
		Toast.makeText(this, item, Toast.LENGTH_LONG).show();
	}

	public void getQuestions() {
		Callback<Question> callback = new Callback<Question>() {

			@Override
			public void failure(RetrofitError resp) {
				Log.v("failure", String.valueOf(resp.getMessage()));
			}

			@Override
			public void success(Question info, Response resp) {
				Log.v("success", String.valueOf(resp.getStatus()));
				getTitle(info);
	            createList();
			}
		};
		RestClient.initRestAdapter().getQuestions(Constants.SORT, Constants.SITE,
				Constants.PAGESIZE, Constants.PAGE, callback);
	}

	public List<String> getTitle(Question info) {
		for (int i = 0; i < info.getItems().size(); i++) {
			mListTitle.add(info.getItems().get(i).getTitle());
		}
		return mListTitle;
	}
	public void createList(){

		// use your custom layout
		ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
		        android.R.layout.simple_list_item_1,mListTitle);
		setListAdapter(adapter);
	}
}

you can download this example from here

How-to create a Magento 2 Composer Module

MAgento 2If you are a developer new to Magento 2, you are probably wondering how to create a Magento 2 Composer Module. Hopefully the below steps will be useful to you. This is how I managed to do it, eventually.

First of all, you should familiarise yourself with composer, and it’s basic usage.

This guide asumes you’ve already installed and configured a vanilla Magento 2 project. If you haven’t done that yet, I’d advise you to check this out and follow the official guide. Feel free to drop me a line if you have any issues.

I’ve found quite a few sites that show how to create a Magento 2 module “the old way”, by copying the module contents inside app/code folder (note that in Magento 1.x it used to be app/code/codePool, but that doesn’t exist anymore in Magento 2).

However, as I’ve recently been working on Symfony 2 projects, I’m quite used to composer, and it’s usage to easily integrate third party components/packages. So, once I saw the file “composer.json” on the root directory of Magento 2, I knew that it should be the way forward in order to develop Magento 2 extensions.

Let’s get started. I’m assuming you’ve developed already your Magento 2 extension, as the purpose of this guide is to show how to package the extension within a composer (sub) module, and the creation of an extension would go beyond the scope of this post. Check this guide to find out how to create a Magento 2 extension, or just clone it’s source code from github.

  • To begin with, you should create a new (github/bitbucket…) repository, and place your source code inside.
  • In the root folder, create a new file named composer.json. This fille will describe the details of your package. This is how mine looks like:
    {
        "name": "lumbrales-software/magento2-first-module",
        "description": "Hello world Magento 2 Composer Module!",
        "require": {
            "magento/project-community-edition": "*"
        },
        "type": "magento2-module",
        "version": "0.1.0",
        "extra": {
            "map": [
                [
                    "*",
                    "Yourcompany/YourModule/"
                ]
            ]
        },
        "authors": [
            {
                "name": "Javi Lumbrales",
                "homepage": "https://www.lumbrales-software.com/",
                "role": "Developer"
            }
        ]
    }

    The most important parts described below:

    • The name of the package: This will serve as identifier of your package, and will be used later on.
    • Requirements: We’ve added “magento/project-community-edition” as a requirement, as this module requires Magento 2 in order to work.
    • Type: We specify “magento2-module” so that it’s contents are copied to app/local once the package is installed (more about this later).
    • Version: Not important, as we’ll use git tagging to handle the composer module updates.
    • Extra: – Map: This tells composer to copy all (*) contents into app/code/LumbralesSoftware/HelloWorld, so the root of your extension should be structured already. This means that you don’t need to keep your files under app/code/YourCompany/YourModule in your repository. Instead, they should be in the root straightly. This is how it your repository should look like:

Repository Root:
Block/
Controller/
etc/

  • Push all your code to the master branch (I’ll explain the tagging on a separated post later on)
  • Go to the root folder of your Magento 2 installation, and type the following commands in your terminal:
composer require magento/magento-composer-installer

This is a submodule required to properly install third party Magento 2 extensions as composer submodules (Remember the type:magento2-module mentioned at the beginning).

  • Then, as your module is still not in a packages repository such as packagist.org, or packages.magento.com, you need to specify your own VCS repository so that composer can find it. In the repositories section of the composer.json file of the Magento 2 project (if the repositories section doesn’t exist, create it, else, add your repository at the end) add the following:
 "repositories": [
    {
      "type": "vcs",
      "url": "https://github.com/youraccount/yourmodule-repository"
    }
  ],
  • Since your package is in a development stage, you will need to add the minimum-stability as well to the composer.json file:
"minimum-stability": "dev",

Note that this could be removed later on, once we have properly tagged/released a stable version of our package/extension.

  • After that, you should be able to install your module as follows (remember how you named it):
composer require your-package/name #In our example the name was lumbrales-software/magento2-first-module

The above command should download your module and copy it’s content to app/code/YourCompany/YourModule

  • Last, but not least, you will need to enable your module and clear Magento cache. Add a new entry in app/etc/config.php, under the ‘modules’ section (Magento 2 project):
    'Yourcompany_YourModule' => 1,

Note that this name should match with the name that you’ve put on the composer.json, section extra -> map.

That’s it, after that your module should be ready to go.

You can download the source code of my Magento 2 Composer Module sample here.

I hope it helps, and let me know if you have any issues!

In my next post I’ll show a basic usage of git tagging and composer to be able to easily release your module updates.

Credits:
https://www.ashsmith.io/2014/12/simple-magento2-controller-module/
https://alankent.wordpress.com/2014/08/03/creating-a-magento-2-composer-module/ 

 

OK – A communication app – I

OK - Communication App LogoI’m glad to announce that our communication app for android: OK has just been released.

OK is a communication app made for lazy people, with the aim of easing the communication. Basically, it allows you customise a predefined list of the messages that you use more often, so that you can use them rather than type them all the time.

Our aim is to let the app learn from each individual usage, and automatically generate a relevant list of messages for each recipient, time and situation. There is still la long way to get there, but we already have the basics in place.

Please, feel free to try out the app and don’t forget to give us some feedback, as we are looking forward to hear peoples thoughts of it.

Enough introduction, this post is the first of a series where we will show you step by step how we built the app, along with all the challenges we faced, and our approaches to solve them.

To begin with, since this is a communication app, we need to display the list of contacts.

In order to do load the contacts we need to do add the following in your AndroidManifest.xml:

<uses-permission android:name="android.permission.READ_CONTACTS" />

Then, create a new method in your activity to fetch all the contacts and put them into a List:

public List<ContactItem> getDataForListView(Context context)
{
    List<ContactItem> contactsList = new ArrayList<ContactItem>();
    Cursor cursor;

    cursor = context.getContentResolver().query(
            ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null,
            null,
            ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " ASC");
    while (cursor.moveToNext()) {
        String contactName = cursor
                .getString(cursor
                        .getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
        String storedNumber = cursor
                .getString(cursor
                        .getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
        String phNumber = new String(storedNumber).replace(" ", "");
        int contactID = cursor.getInt(cursor.getColumnIndexOrThrow(ContactsContract.PhoneLookup._ID));
        ContactItem contact = new ContactItem(contactName, phNumber, contactID);
        contactsList.add(contact);
    }
    cursor.close();

    return contactsList;
}

We use ContactItem which is a custom class to allow us to store the name, id and phone number of the contact. The class is defined as:

public class ContactItem
{

    String name;
    String phone;
    int id;

    public ContactItem(String name, String phone, int id)
    {
        super();
        this.name = name;
        this.phone = phone;
        this.id = id;
    }

    public String getName()
    {
        return name;
    }

    public void setName(String name)
    {
        this.name = name;
    }

    public String getPhone()
    {
        return phone;
    }

    public void setPhone(String phone)
    {
        this.phone = phone;
    }

    public int getId()
    {
        return id;
    }

    public void setId(int id)
    {
        this.id = id;
    }
}

Now, we have all the contacts into a list, and we can easily display them inside a list view, but first we have to solve the following problem:
We are trying to use the phone number as the unique identifier of the users, but that would only work if they are in international format (including the country code), and unfortunately, there are many contacts that doesn’t have the full number stored in the device.

We needed a mechanism to convert or validate the numbers so that they are all in a standard format, otherwise we wouldn’t have a reliable way to identify the contacts as registered users of the app.

Stay tuned to find out how we solved that problem… and much more!

GAE – Reading a big CSV Blobstore in Python

Last week I was trying to upload and parse a big CSV blobstore to Google App Engine (GAE) using python. If you are familiar with GAE you will probably know already that uploading files is not allowed in the standard way, as the application is running in a sandbox within a read-only system. Therefore, if you need to upload something, you have to use the blobstore API provided by google.

In order to do that you need to do the following steps:

1. Request an upload url (somewhere in your app):

from google.appengine.ext import blobstore
url = blobstore.create_upload_url('/destination_after_upload')

This is the url where you have to submit the form with the file and (optionally) any additional data. Once the submission of the form has been completed, the request will be automatically redirected to the provided handler/url (in the example: /destination_after_upload) with all the form data plus the blobstore information.

Note: Everywhere I’ve seen, people assume that you put the generated url in the action of a form in your template/view. However, it is possible for instance to return the url, and then perform a POST request to it programatically, and it will work as well. Example:

#The result of this request will be just the url generated by the previous sample code
upload_url=`curl http://your.appengine.site/get_upload_url/`
#We can curl-post a file to that url, and it will work exactly the same as if we were submitting a form through the browser.
curl -vX POST -F "file=@/path/to/your/file.csv" $upload_url

2. Retrieve the data (in the destination url), for this I’ve used the helper get_uploads:

def destination_after_upload(request):
    # Note that 'file' is the name of the file element used in the form
    upload_files = get_uploads(request, field_name='file', populate_post=True)
    blob = upload_files[0]

3. Parse the CSV file: For this I tried reading the file normally with the csv module, but after facing some issues with the new line characters I ended up using the class BlobIterator and it was working like a charm. Then, I started noticing some random error in the logs due some line of the CSV being corrupted. I was using the following code to parse the CSV:

    # Read CSV content from Blobstore
    blob_reader = blobstore.BlobReader(blob.key())
    blob_iterator = BlobIterator(blob_reader)
    reader = csv.reader(blob_iterator, skipinitialspace=True, delimiter=',')

    # headers = next(reader)
    for row in reader:
        print row
        # do something...
    blobstore.delete(blob.key())

It was all working fine except for some random lines, but I checked the original CSV file and the lines were correct there. I started debugging the execution with PyCharm and I noticed that the issue seemed to be in the next method of the class BlobIterator. Let’s have a look at the code:

def next(self):
        if not self.buffer or len(self.lines) == self.line_num:
            self.buffer = self.blob_reader.read(1048576) # 1MB buffer
            self.lines = self.buffer.splitlines()
            self.line_num = 0

            # Handle special case where our block just happens to end on a new line
            if self.buffer[-1:] == "\n" or self.buffer[-1:] == "\r":
                self.lines.append("")

        if not self.buffer:
            raise StopIteration

        if self.line_num == 0 and len(self.last_line) > 0:
            result = self.last_line + self.lines[self.line_num] + "\n"
        else:
            result = self.lines[self.line_num] + "\n"

        self.last_line = self.lines[self.line_num]
        self.line_num += 1

        return result

I placed a break point in side the first “if” statement, which is the point where it loads one megabyte of data into an internal buffer. The way it works is, summarizing: Load one megabyte of data, split it by the newlines and keep a counter of the current line, returning it on each “next” iteration. The problem is that by loading one megabyte of data, it’s very likely that the last line will be cut in the middle, so you have to concatenate the last line of the first buffer with the first line of the next one, in order to return the proper result. However, the code was already doing it, and the debugger was showing the proper value on the “result” variable, but then when the execution was going back to my “for” loop, the value of the row was actually like this: “last,part,of,first,buffer\n,last,part,of,first,buffer,first,part,next,buffer”

Apparently, it was returning the proper line but prepended by the residual content of the first buffer plus a \n. I was going crazy trying to find out the problem, I even thought that there was an issue on the csv reader module, until I tried to reproduce the issue in a simpler sample:

import unittest
import csv

class TestIterator:
    def __init__(self, data):
        self.data = data
        self.last_line = ""
        self.line_num = 0
        self.lines = []
        self.buffer = None

    def __iter__(self):
        return self

    def next(self):
        if not self.buffer or len(self.lines) == self.line_num:
            self.buffer = self.data[:15]
            self.data = self.data[15:]
            self.lines = self.buffer.splitlines()
            self.line_num = 0

            # Handle special case where our block just happens to end on a new line
            if self.buffer[-1:] == "\n" or self.buffer[-1:] == "\r":
                self.lines.append("")

        if not self.buffer:
            raise StopIteration

        if self.line_num == 0 and len(self.last_line) > 0:
            result = self.last_line + self.lines[self.line_num] + "\n"
        else:
            result = self.lines[self.line_num] + "\n"

        self.last_line = self.lines[self.line_num]
        self.line_num += 1

        return result

class IteratorTest(unittest.TestCase):

    def setUp(self):
        # Read CSV content from string data
        data = """1,2,3,4,5
1,2,3,4,5
1,2,3,4,5
1,2,3,4,5
1,2,3,4,5
1,2,3,4,5
1,2,3,4,5
"""
        self.test_iterator = TestIterator(data)

    def test_iterator(self):
        reader = csv.reader(self.test_iterator, skipinitialspace=True, delimiter=',')
        for row in reader:
            print row
            if row:
                self.assertEqual(row, ['1', '2', '3', '4', '5'])

def main():
    unittest.main()

if __name__ == '__main__':
    main()

And with this code I was able to reproduce the issue. It turns out that the problem is in the line_num counter that starts from zero and hence it was loading the next buffer one iteration later than it should. I managed to fix it with the following changes:

    def next(self):
        if not self.buffer or len(self.lines) == (self.line_num + 1):
            if self.lines:
                self.last_line = self.lines[self.line_num]
            self.buffer = self.data[:15]
            self.data = self.data[15:]
            self.lines = self.buffer.splitlines()
            self.line_num = 0
            print self.lines

            # Handle special case where our block just happens to end on a new line
            if self.buffer[-1:] == "\n" or self.buffer[-1:] == "\r":
                self.lines.append("")

        if not self.buffer:
            raise StopIteration

        if self.line_num == 0 and len(self.last_line) > 0:
            print 'fixing'
            result = self.last_line + self.lines[self.line_num] + "\n"
        else:
            print self.line_num
            print len(self.lines)
            result = self.lines[self.line_num] + "\n"

        self.line_num += 1

        return result

Note that the first three lines are different and the line “self.last_line = self.lines[self.line_num]” has been moved inside the if. With this changes the iterator seems to work fine when changing between buffer iterations, so the fixed/final version of the BlobstoreIterator is:

class BlobIterator:
    """Because the python csv module doesn't like strange newline chars and
    the google blob reader cannot be told to open in universal mode, then
    we need to read blocks of the blob and 'fix' the newlines as we go.
    Fixed the problem with the corrupted lines when fetching new data into the buffer."""

    def __init__(self, blob_reader):
        self.blob_reader = blob_reader
        self.last_line = ""
        self.line_num = 0
        self.lines = []
        self.buffer = None

    def __iter__(self):
        return self

    def next(self):
        if not self.buffer or len(self.lines) == self.line_num + 1:
            if self.lines:
                self.last_line = self.lines[self.line_num]
            self.buffer = self.blob_reader.read(1048576) # 1MB buffer
            self.lines = self.buffer.splitlines()
            self.line_num = 0

            # Handle special case where our block just happens to end on a new line
            if self.buffer[-1:] == "\n" or self.buffer[-1:] == "\r":
                self.lines.append("")

        if not self.buffer:
            raise StopIteration

        if self.line_num == 0 and len(self.last_line) > 0:
            result = self.last_line + self.lines[self.line_num] + "\n"
        else:
            result = self.lines[self.line_num] + "\n"

        self.line_num += 1
        return result

I hope it helps you to save a headache if you are having the same issue.