diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..9c4de58
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,7 @@
+.gradle
+/local.properties
+/.idea/workspace.xml
+/.idea/libraries
+.DS_Store
+/build
+/captures
diff --git a/.idea/.name b/.idea/.name
new file mode 100644
index 0000000..1a552d3
--- /dev/null
+++ b/.idea/.name
@@ -0,0 +1 @@
+DemoApp
\ No newline at end of file
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
new file mode 100644
index 0000000..96cc43e
--- /dev/null
+++ b/.idea/compiler.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml
new file mode 100644
index 0000000..e7bedf3
--- /dev/null
+++ b/.idea/copyright/profiles_settings.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/.idea/encodings.xml b/.idea/encodings.xml
new file mode 100644
index 0000000..97626ba
--- /dev/null
+++ b/.idea/encodings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
new file mode 100644
index 0000000..cb2e36e
--- /dev/null
+++ b/.idea/gradle.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..c60d22d
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1.7
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..31553db
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml
new file mode 100644
index 0000000..7f68460
--- /dev/null
+++ b/.idea/runConfigurations.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..6564d52
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DemoApp.iml b/DemoApp.iml
new file mode 100644
index 0000000..77055b6
--- /dev/null
+++ b/DemoApp.iml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/README.md b/README.md
index 671960d..8b1e9c4 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,5 @@
+# I have done with the assignment.
+
# MI Developer Test
You have just been hired as a mobile developer in a new company.
@@ -26,3 +28,4 @@ Multithreading is a plus.
## How to submit your work?
Fork this repository. This exercise should take about 2 days. However, you are not timed and you can send us a pull request whenever you are ready to show us your work.
And if you have something live going on, even better!
+
diff --git a/app/.gitignore b/app/.gitignore
new file mode 100644
index 0000000..796b96d
--- /dev/null
+++ b/app/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/app/app.iml b/app/app.iml
new file mode 100644
index 0000000..4cee8d7
--- /dev/null
+++ b/app/app.iml
@@ -0,0 +1,107 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ generateDebugAndroidTestSources
+ generateDebugSources
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
new file mode 100644
index 0000000..eba5e97
--- /dev/null
+++ b/app/build.gradle
@@ -0,0 +1,32 @@
+apply plugin: 'com.android.application'
+
+android {
+ compileSdkVersion 23
+ buildToolsVersion "23.0.2"
+
+ defaultConfig {
+ applicationId "com.sharad.demoapp"
+ minSdkVersion 14
+ targetSdkVersion 23
+ versionCode 1
+ versionName "1.0"
+ }
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+}
+
+dependencies {
+ compile fileTree(dir: 'libs', include: ['*.jar'])
+ testCompile 'junit:junit:4.12'
+ compile 'com.android.support:appcompat-v7:23.1.1'
+ compile 'com.android.support:design:23.1.1'
+ compile 'com.android.support:cardview-v7:23.1.1'
+ compile 'com.loopj.android:android-async-http:1.4.9'
+ compile 'com.google.code.gson:gson:2.5'
+ compile 'com.android.support:recyclerview-v7:23.1.1'
+ compile 'com.squareup.picasso:picasso:2.5.2'
+}
diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro
new file mode 100644
index 0000000..a5eff3d
--- /dev/null
+++ b/app/proguard-rules.pro
@@ -0,0 +1,17 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in E:\Sharad\software\adt-bundle-windows-x86-20130219\sdk/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..52fe8b8
--- /dev/null
+++ b/app/src/main/AndroidManifest.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/java/com/sharad/demoapp/activities/MainActivity.java b/app/src/main/java/com/sharad/demoapp/activities/MainActivity.java
new file mode 100644
index 0000000..3153e6e
--- /dev/null
+++ b/app/src/main/java/com/sharad/demoapp/activities/MainActivity.java
@@ -0,0 +1,63 @@
+package com.sharad.demoapp;
+
+import android.os.Bundle;
+import android.support.design.widget.FloatingActionButton;
+import android.support.design.widget.Snackbar;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentManager;
+import android.support.v7.app.AppCompatActivity;
+import android.support.v7.widget.Toolbar;
+import android.view.View;
+import android.view.Menu;
+import android.view.MenuItem;
+
+import com.sharad.demoapp.fragments.HomeFragment;
+
+public class MainActivity extends AppCompatActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
+
+ FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
+ fab.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Snackbar.make(view, "Add Your Device Details", Snackbar.LENGTH_LONG)
+ .setAction("Action", null).show();
+ }
+ });
+
+ selectItem(new HomeFragment());
+ }
+
+ @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_main, menu);
+ 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;
+ }
+
+ return super.onOptionsItemSelected(item);
+ }
+
+ public void selectItem(Fragment fragment) {
+ FragmentManager fragmentManager = getSupportFragmentManager();
+ fragmentManager.beginTransaction().addToBackStack(null).replace(R.id.fl_content_frame, fragment).commit();
+ }
+}
diff --git a/app/src/main/java/com/sharad/demoapp/adapter/PhoneDetailAdapter.java b/app/src/main/java/com/sharad/demoapp/adapter/PhoneDetailAdapter.java
new file mode 100644
index 0000000..5939d4b
--- /dev/null
+++ b/app/src/main/java/com/sharad/demoapp/adapter/PhoneDetailAdapter.java
@@ -0,0 +1,108 @@
+package com.sharad.demoapp.adapter;
+
+import android.content.Context;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentActivity;
+import android.support.v4.app.FragmentManager;
+import android.support.v7.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.sharad.demoapp.R;
+import com.sharad.demoapp.entity.AndroidEntity;
+import com.sharad.demoapp.entity.DeviceEntity;
+import com.sharad.demoapp.entity.PhoneDetailEntity;
+import com.sharad.demoapp.fragments.PhoneDetailsFragment;
+import com.squareup.picasso.Picasso;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Created by SharadW on 25-01-2016.
+ */
+public class PhoneDetailAdapter extends RecyclerView.Adapter {
+
+ private List mDeviceEntityArrayList;
+ private PhoneDetailEntity mPhoneDetailEntity;
+ private FragmentActivity mContext;
+
+ public PhoneDetailAdapter(FragmentActivity mContext, PhoneDetailEntity mPhoneDetailEntity) {
+ this.mContext = mContext;
+ this.mPhoneDetailEntity = mPhoneDetailEntity;
+ this.mDeviceEntityArrayList = mPhoneDetailEntity.getDevices();
+ }
+
+ @Override
+ public PhoneViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ View itemView = LayoutInflater.from(parent.getContext()).
+ inflate(R.layout.custom_cardview_row, parent, false);
+
+ return new PhoneViewHolder(itemView);
+ }
+
+ @Override
+ public void onBindViewHolder(PhoneViewHolder holder, int position) {
+ final DeviceEntity mDeviceEntity = mDeviceEntityArrayList.get(position);
+ if (mDeviceEntity != null) {
+ String url = mDeviceEntity.getImageUrl();
+ if (url != null && url.length() > 0) {
+ Picasso.with(mContext).load(url).into(holder.phoneImageView);
+ } else {
+ holder.phoneImageView.setBackgroundResource(R.drawable.motorolaxoom);
+ }
+ holder.snippetTextView.setText(mDeviceEntity.getSnippet());
+ holder.phoneNameTextView.setText(mDeviceEntity.getName());
+ holder.carrierTextView.setText(mDeviceEntity.getCarrier());
+
+ holder.phoneImageView.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ AndroidEntity mAndroidEntity = filterArrayByID(mDeviceEntity);
+ if(mAndroidEntity != null)
+ selectItem(new PhoneDetailsFragment(mAndroidEntity,mDeviceEntity));
+ }
+ });
+ }
+ }
+
+ @Override
+ public int getItemCount() {
+ return mDeviceEntityArrayList.size();
+ }
+
+ public static class PhoneViewHolder extends RecyclerView.ViewHolder {
+ protected ImageView phoneImageView;
+ protected TextView phoneNameTextView;
+ protected TextView carrierTextView;
+ protected TextView snippetTextView;
+
+ public PhoneViewHolder(View v) {
+ super(v);
+ phoneImageView = (ImageView) v.findViewById(R.id.iv_phone_img);
+ phoneNameTextView = (TextView) v.findViewById(R.id.tv_phone_title);
+ carrierTextView = (TextView) v.findViewById(R.id.tv_carrier);
+ snippetTextView = (TextView) v.findViewById(R.id.tv_snippet);
+ }
+ }
+
+ public void selectItem(Fragment fragment) {
+ FragmentManager fragmentManager = mContext.getSupportFragmentManager();
+ fragmentManager.beginTransaction().addToBackStack(null).replace(R.id.fl_content_frame, fragment).commit();
+ }
+
+ private AndroidEntity filterArrayByID(DeviceEntity mDeviceEntity) {
+ int androidId = mDeviceEntity.getAndroidId();
+ for (AndroidEntity mAndroidEntity : mPhoneDetailEntity.getAndroid()) {
+ if (mAndroidEntity.getId() == androidId) {
+ return mAndroidEntity;
+ }
+
+ }
+
+ return null;
+ }
+}
diff --git a/app/src/main/java/com/sharad/demoapp/component/AlertManager.java b/app/src/main/java/com/sharad/demoapp/component/AlertManager.java
new file mode 100644
index 0000000..05861f9
--- /dev/null
+++ b/app/src/main/java/com/sharad/demoapp/component/AlertManager.java
@@ -0,0 +1,97 @@
+package com.sharad.demoapp.component;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.Context;
+/**
+ * This call is used to provide custom Alerts.
+ * @author Sharad waghchaure
+ *
+ */
+
+public class AlertManager {
+
+ public static void showAlert(Context context, String title, String message,
+ String okButtonName,
+ android.content.DialogInterface.OnClickListener onClickListener) {
+ if (context != null) {
+ final AlertDialog.Builder mAlert = new AlertDialog.Builder(context);
+ mAlert.setTitle(title);
+ mAlert.setMessage(message);
+ mAlert.setPositiveButton(okButtonName, onClickListener);
+ Activity activity = (Activity) context;
+ activity.runOnUiThread(new Runnable() {
+ public void run() {
+
+ try {
+ mAlert.show();
+ } catch (Exception e) {
+ // TODO: handle exception
+ }
+
+ }
+ });
+ }
+
+ }
+
+ public static void showNonCancelableAlert(Context context, String title,
+ String message, String okButtonName,
+ android.content.DialogInterface.OnClickListener retryClickListener,
+ String exitButtonName,
+ android.content.DialogInterface.OnClickListener exitClickListener) {
+ if (context != null) {
+
+ final AlertDialog.Builder mAlert = new AlertDialog.Builder(context);
+ mAlert.setTitle(title);
+ mAlert.setCancelable(false);
+ mAlert.setMessage(message);
+ mAlert.setPositiveButton(okButtonName, retryClickListener);
+ mAlert.setNegativeButton(exitButtonName, exitClickListener);
+
+ Activity activity = (Activity) context;
+ activity.runOnUiThread(new Runnable() {
+ public void run() {
+
+ try {
+ mAlert.show();
+ } catch (Exception e) {
+ // TODO: handle exception
+ }
+ }
+ });
+
+
+ }
+ }
+
+ public static void showCancelableAlert(Context context, String title,
+ String message, String positiveButton,
+ android.content.DialogInterface.OnClickListener positiveButtonClickListener,
+ String negativeButton,
+ android.content.DialogInterface.OnClickListener negativeButtonClickListener) {
+ if (context != null) {
+
+ final AlertDialog.Builder mAlert = new AlertDialog.Builder(context);
+ mAlert.setTitle(title);
+ mAlert.setCancelable(false);
+ mAlert.setMessage(message);
+ mAlert.setPositiveButton(positiveButton, positiveButtonClickListener);
+ mAlert.setNegativeButton(negativeButton, negativeButtonClickListener);
+
+ Activity activity = (Activity) context;
+ activity.runOnUiThread(new Runnable() {
+ public void run() {
+
+ try {
+ mAlert.show();
+ } catch (Exception e) {
+ // TODO: handle exception
+ }
+ }
+ });
+
+
+ }
+ }
+}
diff --git a/app/src/main/java/com/sharad/demoapp/constant/URLConstants.java b/app/src/main/java/com/sharad/demoapp/constant/URLConstants.java
new file mode 100644
index 0000000..4bc55b8
--- /dev/null
+++ b/app/src/main/java/com/sharad/demoapp/constant/URLConstants.java
@@ -0,0 +1,16 @@
+package com.sharad.demoapp.constant;
+
+
+
+public interface URLConstants {
+
+ public static String BASE_URL = "http://192.168.0.138:3000/";//----Production URL
+ //------------------------------------------------------------------------------------------------
+ public String URL_LOGIN = BASE_URL + "/login.php";
+
+ public String URL_REGISTRATION = BASE_URL+"/register.php";
+
+ public String URL_GET_PHONE_DETAILS = BASE_URL+"db";
+
+
+}
diff --git a/app/src/main/java/com/sharad/demoapp/database/ColumnCreator.java b/app/src/main/java/com/sharad/demoapp/database/ColumnCreator.java
new file mode 100644
index 0000000..ef3bfe8
--- /dev/null
+++ b/app/src/main/java/com/sharad/demoapp/database/ColumnCreator.java
@@ -0,0 +1,61 @@
+package com.winjit.database;
+
+public class ColumnCreator
+ {
+ private String ColumnName;
+ private ColumnDataType ColumnDataType;
+ private String ColumnDefaultValue;
+ private boolean NotNull;
+ private boolean PrimaryKey;
+
+ public String getColumnName()
+ {
+ return ColumnName;
+ }
+
+ public void setColumnName(String columnName)
+ {
+ ColumnName = columnName;
+ }
+
+ public ColumnDataType getColumnDataType()
+ {
+ return ColumnDataType;
+ }
+
+ public void setColumnDataType(ColumnDataType columnDataType)
+ {
+ ColumnDataType = columnDataType;
+ }
+
+ public String getColumnDefaultValue()
+ {
+ return ColumnDefaultValue;
+ }
+
+ public void setColumnDefaultValue(String columnDefaultValue)
+ {
+ ColumnDefaultValue = columnDefaultValue;
+ }
+
+ public boolean isNotNull()
+ {
+ return NotNull;
+ }
+
+ public void setNotNull(boolean notNull)
+ {
+ NotNull = notNull;
+ }
+
+ public boolean isPrimaryKey()
+ {
+ return PrimaryKey;
+ }
+
+ public void setPrimaryKey(boolean primaryKey)
+ {
+ PrimaryKey = primaryKey;
+ }
+
+ }
diff --git a/app/src/main/java/com/sharad/demoapp/database/ColumnDataType.java b/app/src/main/java/com/sharad/demoapp/database/ColumnDataType.java
new file mode 100644
index 0000000..c8c77a1
--- /dev/null
+++ b/app/src/main/java/com/sharad/demoapp/database/ColumnDataType.java
@@ -0,0 +1,8 @@
+package com.winjit.database;
+
+public enum ColumnDataType
+ {
+ INTEGER,
+ REAL,
+ TEXT
+ }
diff --git a/app/src/main/java/com/sharad/demoapp/database/DatabaseHelper.java b/app/src/main/java/com/sharad/demoapp/database/DatabaseHelper.java
new file mode 100644
index 0000000..385dd6b
--- /dev/null
+++ b/app/src/main/java/com/sharad/demoapp/database/DatabaseHelper.java
@@ -0,0 +1,402 @@
+package com.winjit.database;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.channels.FileChannel;
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.database.SQLException;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.os.Environment;
+import android.util.Log;
+
+public class DatabaseHelper extends SQLiteOpenHelper
+ {
+
+ private static DatabaseHelper sInstance;
+ private SQLiteDatabase sqLiteDatabase;
+ private static final String DATABASE_NAME = "database_name";
+ private static final int DATABASE_VERSION = 1;
+ private String tag = DatabaseHelper.class.getName();
+ Context context;
+
+ public static synchronized DatabaseHelper getInstance(Context context)
+ {
+
+ if (sInstance == null)
+ {
+ sInstance = new DatabaseHelper(context.getApplicationContext());
+ }
+ return sInstance;
+ }
+
+ /****
+ * Clear singleton database instance
+ */
+ public static void clearInstance()
+ {
+ if (sInstance != null)
+ {
+ sInstance = null;
+ }
+ }
+
+ /**
+ * Conuctor should be private to prevent direct instantiation.
+ * make call to static method "getInstance()" instead.
+ */
+ private DatabaseHelper(Context context)
+ {
+ super(context, DATABASE_NAME, null, DATABASE_VERSION);
+ }
+
+ @Override
+ public void onCreate(SQLiteDatabase db)
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ /**
+ * Drop existing table(if present with same name) and create new table.
+ * @param tableCreator
+ * @throws Exception
+ */
+ public void createTable(TableCreator tableCreator) throws Exception
+ {
+ openDatabaseForWrite();
+ try
+ {
+ if (tableCreator.getTableName() != null && !tableCreator.getTableName().isEmpty())
+ {
+ sqLiteDatabase.execSQL("DROP TABLE IF EXISTS " + tableCreator.getTableName());
+
+ StringBuilder ingBuilder = new StringBuilder();
+ ingBuilder.append("CREATE TABLE " + tableCreator.getTableName());
+ ingBuilder.append("(");
+ if (tableCreator.getColumnCreatorArrayList() != null && tableCreator.getColumnCreatorArrayList().size() > 0)
+ {
+ //traverse through is each column
+ for (ColumnCreator columnCreator : tableCreator.getColumnCreatorArrayList())
+ {
+ if (columnCreator.getColumnName() != null && !columnCreator.getColumnName().isEmpty())
+ {
+
+ ingBuilder.append(columnCreator.getColumnName());
+ ingBuilder.append(" ");
+
+ if (columnCreator.getColumnDataType() == ColumnDataType.INTEGER)
+ {
+ ingBuilder.append("INTEGER");
+ }
+ else if (columnCreator.getColumnDataType() == ColumnDataType.REAL)
+ {
+ ingBuilder.append("REAL");
+ }
+ else if (columnCreator.getColumnDataType() == ColumnDataType.TEXT)
+ {
+ ingBuilder.append("TEXT");
+ }
+ else
+ {
+ throw new DatabaseHelperException("DataType for column \'"
+ + columnCreator.getColumnName() + "\' is not specified");
+ }
+ ingBuilder.append(" ");
+
+ if (columnCreator.isPrimaryKey())
+ {
+ ingBuilder.append("PRIMARY KEY");
+ }
+ ingBuilder.append(" ");
+
+ if (columnCreator.isNotNull())
+ {
+ ingBuilder.append("NOT NULL");
+ }
+
+ ingBuilder.append(" ");
+ ingBuilder.append(",");
+ }
+ else
+ {
+ throw new DatabaseHelperException(
+ "Column name cannot be NULL or Empty.Please use valid column name");
+ }
+
+ }
+
+ }
+ else
+ {
+ throw new DatabaseHelperException("Cannot create empty table \'" + tableCreator.getTableName()
+ + "\', you should specify atleast one column");
+
+ }
+
+ ingBuilder.append(")");
+ String queryString = ingBuilder.toString();
+ queryString = queryString.replaceAll(" ,", ",");
+ queryString = queryString.replaceAll(",\\)", ")");
+ Log.d(tag, "" + queryString);
+
+ sqLiteDatabase.execSQL(queryString);
+
+ }
+ else
+ {
+ throw new DatabaseHelperException("Table name cannot be NULL or Empty.Please use valid table name");
+ }
+
+ }
+ finally
+ {
+ closeDatabase();
+ }
+ }
+
+ public void replaceAll(StringBuilder builder, String from, String to)
+ {
+ int index = builder.indexOf(from);
+ while (index != -1)
+ {
+ builder.replace(index, index + from.length(), to);
+ index += to.length(); // Move to the end of the replacement
+ index = builder.indexOf(from, index);
+ }
+ }
+
+ /**
+ * get Readable instance of sqLiteDatabase
+ *
+ * @throws SQLException
+ */
+ public synchronized void openDatabaseForRead()
+ {
+ // Open the sqLiteDatabase
+ try
+ {
+ if (sqLiteDatabase == null || !sqLiteDatabase.isOpen())
+ {
+
+ sqLiteDatabase = this.getReadableDatabase();
+
+ }
+ else
+ {
+ }
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * get Writable instance of sqLiteDatabase
+ *
+ * @throws SQLException
+ */
+ public synchronized void openDatabaseForWrite()
+ {
+ // Open the sqLiteDatabase
+ try
+ {
+ if (sqLiteDatabase == null || !sqLiteDatabase.isOpen())
+ {
+ sqLiteDatabase = this.getWritableDatabase();
+ }
+ else
+ {
+ // if the current mode is read only;open db in write mode
+ if (sqLiteDatabase.isReadOnly())
+ {
+ sqLiteDatabase = this.getWritableDatabase();
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ public synchronized void closeDatabase()
+ {
+ super.close();
+ try
+ {
+ if (sqLiteDatabase != null)
+ sqLiteDatabase.close();
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Insert single record in table.
+ *
+ * @param TableName
+ * table name in which record to be inserted
+ * @param values
+ * column values
+ * @return true if record is inserted
+ */
+ public boolean InsertRecord(String TableName, ContentValues values)
+ {
+ long lid = -1;
+
+ try
+ {
+ openDatabaseForWrite();
+ lid = sqLiteDatabase.insert(TableName, null, values);
+
+ }
+ catch (Exception e)
+ {
+ lid = -1;
+ e.printStackTrace();
+ }
+
+ return lid == -1 ? false : true;
+
+ }
+
+ /**
+ * update single record in table
+ *
+ * @param TableName
+ * table name in which record to be inserted
+ * @param values
+ * column values
+ * @param WhereClause
+ * where clause for primary key
+ * @return true if record is updated
+ */
+ public boolean UpdateRecord(String TableName, ContentValues values, String WhereClause, String[] args)
+ {
+ long lid = -1;
+ try
+ {
+ openDatabaseForWrite();
+ lid = sqLiteDatabase.update(TableName, values, WhereClause, args);
+
+ }
+ catch (Exception e)
+ {
+ lid = -1;
+ e.printStackTrace();
+ }
+ finally
+ {
+ closeDatabase();
+ }
+ return lid == -1 ? false : true;
+ }
+
+ /**
+ * Delete a single record
+ *
+ * @param TableName
+ * table name from which record to delete
+ * @param WhereClause
+ * primary key which record to delete
+ */
+ public boolean deleteRecord(String TableName, String WhereClause, String[] args)
+ {
+
+ int affectedRows = 0;
+ try
+ {
+ openDatabaseForWrite();
+ affectedRows = sqLiteDatabase.delete(TableName, WhereClause, args);
+
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+
+ }
+ finally
+ {
+ closeDatabase();
+ }
+ return affectedRows == 0 ? false : true;
+ }
+
+ /**
+ * update single record in table
+ * @param Query Query to execute
+ */
+ public void UpdateRecordByQuery(String Query, String[] args)
+ {
+ Cursor cursor;
+ try
+ {
+ openDatabaseForWrite();
+ cursor = sqLiteDatabase.rawQuery(Query, args);
+ cursor.moveToFirst();
+ cursor.close();
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+
+ }
+ finally
+ {
+ closeDatabase();
+ }
+ }
+
+
+
+
+
+ /**
+ * This method export database to SDcard
+ *
+ * @return true if exported
+ */
+ public boolean exportDBToSDcard()
+ {
+ String strDB_path = File.separator + "data" + File.separator + "data" + File.separator + "com.example.databaseutils" + File.separator + "databases"
+ + File.separator;
+ FileChannel source = null;
+ FileChannel destination = null;
+ File currentDB = new File(strDB_path + DATABASE_NAME);
+ File backupDB = new File(Environment.getExternalStorageDirectory() + File.separator + "AirtouchExportDB.sdf");
+ try
+ {
+ source = new FileInputStream(currentDB).getChannel();
+ destination = new FileOutputStream(backupDB).getChannel();
+ destination.transferFrom(source, 0, source.size());
+ source.close();
+ destination.close();
+ return true;
+ }
+ catch (IOException e)
+ {
+ e.printStackTrace();
+ }
+ return false;
+ }
+
+
+
+
+ }
diff --git a/app/src/main/java/com/sharad/demoapp/database/DatabaseHelperException.java b/app/src/main/java/com/sharad/demoapp/database/DatabaseHelperException.java
new file mode 100644
index 0000000..1d60b50
--- /dev/null
+++ b/app/src/main/java/com/sharad/demoapp/database/DatabaseHelperException.java
@@ -0,0 +1,16 @@
+package com.winjit.database;
+
+public class DatabaseHelperException extends Exception
+ {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+
+ public DatabaseHelperException(String Message)
+ {
+ super(Message);
+ }
+
+ }
diff --git a/app/src/main/java/com/sharad/demoapp/database/TableCreator.java b/app/src/main/java/com/sharad/demoapp/database/TableCreator.java
new file mode 100644
index 0000000..4068447
--- /dev/null
+++ b/app/src/main/java/com/sharad/demoapp/database/TableCreator.java
@@ -0,0 +1,30 @@
+package com.winjit.database;
+
+import java.util.ArrayList;
+
+public class TableCreator
+ {
+ private String TableName;
+ private ArrayList columnCreatorArrayList;
+
+ public String getTableName()
+ {
+ return TableName;
+ }
+
+ public void setTableName(String tableName)
+ {
+ TableName = tableName;
+ }
+
+ public ArrayList getColumnCreatorArrayList()
+ {
+ return columnCreatorArrayList;
+ }
+
+ public void setColumnCreatorArrayList(ArrayList columnCreatorArrayList)
+ {
+ this.columnCreatorArrayList = columnCreatorArrayList;
+ }
+
+ }
diff --git a/app/src/main/java/com/sharad/demoapp/entity/AndroidEntity.java b/app/src/main/java/com/sharad/demoapp/entity/AndroidEntity.java
new file mode 100644
index 0000000..a744cec
--- /dev/null
+++ b/app/src/main/java/com/sharad/demoapp/entity/AndroidEntity.java
@@ -0,0 +1,138 @@
+package com.sharad.demoapp.entity;
+
+/**
+ * Created by SharadW on 22-01-2016.
+ */
+import com.google.gson.annotations.Expose;
+import com.google.gson.annotations.SerializedName;
+
+public class AndroidEntity {
+
+ @SerializedName("id")
+ @Expose
+ private Integer id;
+ @SerializedName("name")
+ @Expose
+ private String name;
+ @SerializedName("version")
+ @Expose
+ private String version;
+ @SerializedName("codename")
+ @Expose
+ private String codename;
+ @SerializedName("target")
+ @Expose
+ private String target;
+ @SerializedName("distribution")
+ @Expose
+ private String distribution;
+
+ /**
+ *
+ * @return
+ * The id
+ */
+ public Integer getId() {
+ return id;
+ }
+
+ /**
+ *
+ * @param id
+ * The id
+ */
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ /**
+ *
+ * @return
+ * The name
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ *
+ * @param name
+ * The name
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ *
+ * @return
+ * The version
+ */
+ public String getVersion() {
+ return version;
+ }
+
+ /**
+ *
+ * @param version
+ * The version
+ */
+ public void setVersion(String version) {
+ this.version = version;
+ }
+
+ /**
+ *
+ * @return
+ * The codename
+ */
+ public String getCodename() {
+ return codename;
+ }
+
+ /**
+ *
+ * @param codename
+ * The codename
+ */
+ public void setCodename(String codename) {
+ this.codename = codename;
+ }
+
+ /**
+ *
+ * @return
+ * The target
+ */
+ public String getTarget() {
+ return target;
+ }
+
+ /**
+ *
+ * @param target
+ * The target
+ */
+ public void setTarget(String target) {
+ this.target = target;
+ }
+
+ /**
+ *
+ * @return
+ * The distribution
+ */
+ public String getDistribution() {
+ return distribution;
+ }
+
+ /**
+ *
+ * @param distribution
+ * The distribution
+ */
+ public void setDistribution(String distribution) {
+ this.distribution = distribution;
+ }
+
+}
diff --git a/app/src/main/java/com/sharad/demoapp/entity/DeviceEntity.java b/app/src/main/java/com/sharad/demoapp/entity/DeviceEntity.java
new file mode 100644
index 0000000..0c2c9f0
--- /dev/null
+++ b/app/src/main/java/com/sharad/demoapp/entity/DeviceEntity.java
@@ -0,0 +1,138 @@
+package com.sharad.demoapp.entity;
+
+/**
+ * Created by SharadW on 22-01-2016.
+ */
+import com.google.gson.annotations.Expose;
+import com.google.gson.annotations.SerializedName;
+
+public class DeviceEntity {
+
+ @SerializedName("id")
+ @Expose
+ private Integer id;
+ @SerializedName("androidId")
+ @Expose
+ private Integer androidId;
+ @SerializedName("imageUrl")
+ @Expose
+ private String imageUrl;
+ @SerializedName("name")
+ @Expose
+ private String name;
+ @SerializedName("snippet")
+ @Expose
+ private String snippet;
+ @SerializedName("carrier")
+ @Expose
+ private String carrier;
+
+ /**
+ *
+ * @return
+ * The id
+ */
+ public Integer getId() {
+ return id;
+ }
+
+ /**
+ *
+ * @param id
+ * The id
+ */
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ /**
+ *
+ * @return
+ * The androidId
+ */
+ public Integer getAndroidId() {
+ return androidId;
+ }
+
+ /**
+ *
+ * @param androidId
+ * The androidId
+ */
+ public void setAndroidId(Integer androidId) {
+ this.androidId = androidId;
+ }
+
+ /**
+ *
+ * @return
+ * The imageUrl
+ */
+ public String getImageUrl() {
+ return imageUrl;
+ }
+
+ /**
+ *
+ * @param imageUrl
+ * The imageUrl
+ */
+ public void setImageUrl(String imageUrl) {
+ this.imageUrl = imageUrl;
+ }
+
+ /**
+ *
+ * @return
+ * The name
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ *
+ * @param name
+ * The name
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ *
+ * @return
+ * The snippet
+ */
+ public String getSnippet() {
+ return snippet;
+ }
+
+ /**
+ *
+ * @param snippet
+ * The snippet
+ */
+ public void setSnippet(String snippet) {
+ this.snippet = snippet;
+ }
+
+ /**
+ *
+ * @return
+ * The carrier
+ */
+ public String getCarrier() {
+ return carrier;
+ }
+
+ /**
+ *
+ * @param carrier
+ * The carrier
+ */
+ public void setCarrier(String carrier) {
+ this.carrier = carrier;
+ }
+
+}
diff --git a/app/src/main/java/com/sharad/demoapp/entity/PhoneDetailEntity.java b/app/src/main/java/com/sharad/demoapp/entity/PhoneDetailEntity.java
new file mode 100644
index 0000000..bb54607
--- /dev/null
+++ b/app/src/main/java/com/sharad/demoapp/entity/PhoneDetailEntity.java
@@ -0,0 +1,56 @@
+package com.sharad.demoapp.entity;
+
+/**
+ * Created by SharadW on 22-01-2016.
+ */
+import java.util.ArrayList;
+import java.util.List;
+import com.google.gson.annotations.Expose;
+import com.google.gson.annotations.SerializedName;
+
+public class PhoneDetailEntity {
+
+ @SerializedName("android")
+ @Expose
+ private List android = new ArrayList();
+ @SerializedName("devices")
+ @Expose
+ private List devices = new ArrayList();
+
+ /**
+ *
+ * @return
+ * The android
+ */
+ public List getAndroid() {
+ return android;
+ }
+
+ /**
+ *
+ * @param android
+ * The android
+ */
+ public void setAndroid(List android) {
+ this.android = android;
+ }
+
+ /**
+ *
+ * @return
+ * The devices
+ */
+ public List getDevices() {
+ return devices;
+ }
+
+ /**
+ *
+ * @param devices
+ * The devices
+ */
+ public void setDevices(List devices) {
+ this.devices = devices;
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/sharad/demoapp/fragments/HomeFragment.java b/app/src/main/java/com/sharad/demoapp/fragments/HomeFragment.java
new file mode 100644
index 0000000..fa883d4
--- /dev/null
+++ b/app/src/main/java/com/sharad/demoapp/fragments/HomeFragment.java
@@ -0,0 +1,147 @@
+package com.sharad.demoapp.fragments;
+
+import android.content.Context;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.v4.app.Fragment;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Toast;
+
+import com.sharad.demoapp.R;
+import com.sharad.demoapp.adapter.PhoneDetailAdapter;
+import com.sharad.demoapp.component.AlertManager;
+import com.sharad.demoapp.entity.PhoneDetailEntity;
+import com.sharad.demoapp.sync.SyncListener;
+import com.sharad.demoapp.sync.SyncManager;
+import com.sharad.demoapp.util.AlertView;
+import com.sharad.demoapp.util.UtilityMethod;
+
+/**
+ * Created by SharadW on 22-01-2016.
+ */
+public class HomeFragment extends Fragment {
+
+ private RecyclerView mRecyclerView;
+ private RecyclerView.Adapter mAdapter;
+ private RecyclerView.LayoutManager mLayoutManager;
+ private SyncListener mSyncListener;
+ private SyncManager mSyncManager;
+ private Context mContext;
+
+ @Nullable
+ @Override
+ public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
+ View rootView = inflater.inflate(R.layout.fragment_home, container,false);
+
+ mContext = getActivity();
+ mRecyclerView = (RecyclerView) rootView.findViewById(R.id.my_recycler_view);
+
+ // use this setting to improve performance if you know that changes
+ // in content do not change the layout size of the RecyclerView
+ mRecyclerView.setHasFixedSize(true);
+ // use a linear layout manager
+ mLayoutManager = new LinearLayoutManager(getActivity());
+ mRecyclerView.setLayoutManager(mLayoutManager);
+ getPhoneDetailsFromServer();
+ return rootView;
+ }
+
+ private void getPhoneDetailsFromServer()
+ {
+
+
+
+ mSyncListener = null;
+ mSyncManager = null;
+
+ UtilityMethod.progressDialogShow(mContext);
+
+ mSyncListener = new SyncListener() {
+
+ boolean isShowingFailDialog = false;
+
+ public void onSyncFailure(final int result, final int taskId, String message) {
+ getActivity().runOnUiThread(new Runnable() {
+
+ public void run() {
+ UtilityMethod.progressDialogDismiss(getActivity());
+
+ if (result == SyncManager.SYNC_FAIL && !isShowingFailDialog) {
+ if (taskId == SyncManager.LOGIN)
+
+ {
+
+ } else {
+ DialogInterface.OnClickListener retryListener = new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialogInterface, int i) {
+ isShowingFailDialog = false;
+ }
+ };
+
+ AlertManager.showNonCancelableAlert(mContext, "Error", "Sync Failed", "Retry", retryListener, "Close", null);
+ isShowingFailDialog = true;
+ }
+ } else if (result == SyncManager.NO_INTERNET && !isShowingFailDialog) {
+
+ DialogInterface.OnClickListener retryListener = new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialogInterface, int i) {
+ isShowingFailDialog = false;
+ }
+ };
+ AlertManager.showNonCancelableAlert(mContext, "Error", "Please make sure your Network Connection is ON", "Retry", retryListener, "Close", null);
+ isShowingFailDialog = true;
+
+ } else if (result == SyncManager.SERVER_DOWN && !isShowingFailDialog) {// @
+ AlertManager.showAlert(mContext, "Error", "No Response from Server!", "OK", null);
+ isShowingFailDialog = true;
+ }
+ }
+ });
+ }
+
+ public void onSyncProgressUpdate(int progressPercent, String message) {
+
+ }
+
+ @Override
+ public void onSyncSuccess(final int result,int taskId, final Object mObject) {
+
+ getActivity().runOnUiThread(new Runnable() {
+ public void run() {
+
+ try {
+
+ UtilityMethod.progressDialogDismiss(getActivity());
+ if (result == SyncManager.SYNC_SUCCESS) {
+ if (mObject != null) {
+ PhoneDetailEntity mPhoneDetailEntity = (PhoneDetailEntity) mObject;
+ // specify an adapter
+ mAdapter = new PhoneDetailAdapter(getActivity(),mPhoneDetailEntity);
+ mRecyclerView.setAdapter(mAdapter);
+
+ } else {
+ AlertView.showLongToast(mContext, (String) mObject.toString());
+ }
+
+ }
+ } catch (Exception e) {
+ Toast.makeText(mContext,"failed to download ,Please try again!!!",
+ Toast.LENGTH_SHORT).show();
+ e.printStackTrace();
+ }
+
+ }
+ });
+
+ }
+ };
+
+ mSyncManager = new SyncManager(mContext, SyncManager.GET_PHONE_DETAILS, mSyncListener);
+ mSyncManager.getPhoneDetaills();
+ }
+}
diff --git a/app/src/main/java/com/sharad/demoapp/fragments/PhoneDetailsFragment.java b/app/src/main/java/com/sharad/demoapp/fragments/PhoneDetailsFragment.java
new file mode 100644
index 0000000..df57d07
--- /dev/null
+++ b/app/src/main/java/com/sharad/demoapp/fragments/PhoneDetailsFragment.java
@@ -0,0 +1,59 @@
+package com.sharad.demoapp.fragments;
+
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.sharad.demoapp.R;
+import com.sharad.demoapp.entity.AndroidEntity;
+import com.sharad.demoapp.entity.DeviceEntity;
+import com.squareup.picasso.Picasso;
+
+/**
+ * Created by SharadW on 25-01-2016.
+ */
+public class PhoneDetailsFragment extends Fragment {
+
+ private TextView titleTextView,androidNameTextView,distributionTextView,targetTextView,versionTextView,detailTextView;
+ private ImageView mImageView;
+ private AndroidEntity mAndroidEntity;
+ private DeviceEntity mDeviceEntity;
+
+ public PhoneDetailsFragment(AndroidEntity mAndroidEntity,DeviceEntity mDeviceEntity)
+ {
+ this.mAndroidEntity = mAndroidEntity;
+ this.mDeviceEntity = mDeviceEntity;
+ }
+ @Nullable
+ @Override
+ public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
+ View rootView = inflater.inflate(R.layout.fragment_phone_details, container,false);
+ titleTextView = (TextView)rootView.findViewById(R.id.tv_name);
+ androidNameTextView = (TextView)rootView.findViewById(R.id.tv_name_android);
+ distributionTextView = (TextView)rootView.findViewById(R.id.tv_distribution);
+ targetTextView = (TextView)rootView.findViewById(R.id.tv_target);
+ versionTextView = (TextView)rootView.findViewById(R.id.tv_version);
+ detailTextView = (TextView)rootView.findViewById(R.id.tv_details);
+ mImageView = (ImageView)rootView.findViewById(R.id.iv_detail);
+
+ String url = mDeviceEntity.getImageUrl();
+ if (url != null && url.length() > 0) {
+ Picasso.with(getContext()).load(url).into(mImageView);
+ } else {
+ mImageView.setBackgroundResource(R.drawable.motorolaxoom);
+ }
+
+ titleTextView.setText(mDeviceEntity.getName());
+ androidNameTextView.setText(mAndroidEntity.getName());
+ distributionTextView.setText("Distribution "+mAndroidEntity.getDistribution());
+ targetTextView.setText("Target "+mAndroidEntity.getTarget());
+ versionTextView.setText("Version "+mAndroidEntity.getVersion());
+ detailTextView.setText(mDeviceEntity.getSnippet());
+ return rootView;
+ }
+}
diff --git a/app/src/main/java/com/sharad/demoapp/network/DownloadHandler.java b/app/src/main/java/com/sharad/demoapp/network/DownloadHandler.java
new file mode 100644
index 0000000..9dbb842
--- /dev/null
+++ b/app/src/main/java/com/sharad/demoapp/network/DownloadHandler.java
@@ -0,0 +1,65 @@
+package com.sharad.demoapp.network;
+
+
+import java.io.UnsupportedEncodingException;
+
+
+import com.loopj.android.http.AsyncHttpResponseHandler;
+
+import cz.msebera.android.httpclient.Header;
+
+public class DownloadHandler extends AsyncHttpResponseHandler {
+ private int taskID;
+
+ private DownloadListener downloadListener;
+
+ public DownloadHandler(int taskID, DownloadListener downloadListener) {
+
+ this.taskID = taskID;
+ this.downloadListener = downloadListener;
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ // Constants.showLog("SyncManager", "download task with id " + taskID +
+ // " started ");
+ }
+
+ @Override
+ public void onFailure(int arg0, Header[] arg1, byte[] response, Throwable throwable) {
+ try {
+ String res = null;
+ if(response != null)
+ {
+ res = new String(response,"utf-8");
+ }
+ downloadListener.onDownloadFailure(taskID, throwable,res);
+ } catch (UnsupportedEncodingException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+
+ }
+
+ @Override
+ public void onSuccess(int statusCode, Header[] arg1, byte[] response) {
+ try {
+ if (statusCode != 200) {
+ String res = new String(response, "utf-8");
+ downloadListener.onDownloadFailure(taskID, new Throwable("statusCode " + statusCode),res);
+ } else {
+
+ String res = new String(response, "utf-8");
+ downloadListener.onDownloadSuccess(taskID, res);
+ }
+ } catch (UnsupportedEncodingException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ }
+
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/sharad/demoapp/network/DownloadListener.java b/app/src/main/java/com/sharad/demoapp/network/DownloadListener.java
new file mode 100644
index 0000000..f062015
--- /dev/null
+++ b/app/src/main/java/com/sharad/demoapp/network/DownloadListener.java
@@ -0,0 +1,14 @@
+package com.sharad.demoapp.network;
+
+/**
+ * This Interface provide call back on success or failure of download task.
+ * @author Sharad waghchaure
+ *
+ */
+
+public interface DownloadListener{
+
+ void onDownloadSuccess(int taskID, String response);
+
+ void onDownloadFailure(int taskID, Throwable throwable, String response);
+}
diff --git a/app/src/main/java/com/sharad/demoapp/parser/ParseUtil.java b/app/src/main/java/com/sharad/demoapp/parser/ParseUtil.java
new file mode 100644
index 0000000..8cfd3ef
--- /dev/null
+++ b/app/src/main/java/com/sharad/demoapp/parser/ParseUtil.java
@@ -0,0 +1,34 @@
+package com.sharad.demoapp.parser;
+
+import java.io.IOException;
+
+
+
+import com.google.gson.Gson;
+import com.google.gson.JsonSyntaxException;
+
+public class ParseUtil {
+
+ /*
+ * Method used to get Object from JSON String response
+ */
+ public static Object getObject(String data, Class clazz) {
+ return parseUsingGson(data, clazz);
+// return parseUsingJackson(data, clazz);
+ }
+
+ /*
+ * Parse data using GSON Lib
+ */
+ private static Object parseUsingGson(String data, Class clazz) {
+ try {
+ Gson gson = new Gson();
+ return gson.fromJson(data, clazz);
+ } catch (JsonSyntaxException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/sharad/demoapp/sync/AsyncParsingTask.java b/app/src/main/java/com/sharad/demoapp/sync/AsyncParsingTask.java
new file mode 100644
index 0000000..063fecf
--- /dev/null
+++ b/app/src/main/java/com/sharad/demoapp/sync/AsyncParsingTask.java
@@ -0,0 +1,67 @@
+package com.sharad.demoapp.sync;
+
+import android.content.Context;
+import android.os.AsyncTask;
+import android.util.Log;
+
+import com.sharad.demoapp.entity.PhoneDetailEntity;
+import com.sharad.demoapp.parser.ParseUtil;
+import com.sharad.demoapp.sync.ParseListener;
+
+
+/**
+ * This class is used to Parse the data in background.
+ * Extention of parsing is also there for Json data
+ *
+ * @author Sharad Waghchaure
+ */
+public class AsyncParsingTask extends AsyncTask {
+ private final String TAG = "AsyncParsingTask";
+ private int taskID;
+ private ParseListener parseListener;
+ private Object mObject;
+ // private Singleton singleton;
+
+ private Context mContext;
+
+ public AsyncParsingTask(int taskID, ParseListener parseListener, Context context) {
+ this.taskID = taskID;
+ this.parseListener = parseListener;
+ mContext = context;
+ }
+
+ @Override
+ protected Integer doInBackground(String... params) {
+ String response = params[0];
+ switch (taskID) {
+ case SyncManager.GET_PHONE_DETAILS :
+ PhoneDetailEntity mPhoneDetailEntity = (PhoneDetailEntity) ParseUtil.getObject(response,PhoneDetailEntity.class);
+ mObject = mPhoneDetailEntity;
+ }
+ return null;
+ }
+
+ @Override
+ protected void onPreExecute() {
+ super.onPreExecute();
+
+ }
+
+ @Override
+ protected void onPostExecute(Integer result) {
+ super.onPostExecute(result);
+
+ parseListener.onParseSuccess(taskID, mObject);
+
+ }
+
+ @Override
+ protected void onProgressUpdate(Void... values) {
+ super.onProgressUpdate(values);
+ }
+
+ @Override
+ protected void onCancelled() {
+ super.onCancelled();
+ }
+}
diff --git a/app/src/main/java/com/sharad/demoapp/sync/ParseListener.java b/app/src/main/java/com/sharad/demoapp/sync/ParseListener.java
new file mode 100644
index 0000000..cda2eab
--- /dev/null
+++ b/app/src/main/java/com/sharad/demoapp/sync/ParseListener.java
@@ -0,0 +1,15 @@
+package com.sharad.demoapp.sync;
+
+/**
+ * This Interface provide call back on Parse success or failure.
+ * @author Sharad waghchaure
+ *
+ */
+public interface ParseListener{
+
+ void onNewParseJob(int taskID, String response);
+
+ void onParseSuccess(int taskID, Object object);
+
+ void onParseFailed(int taskID);
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/sharad/demoapp/sync/SyncListener.java b/app/src/main/java/com/sharad/demoapp/sync/SyncListener.java
new file mode 100644
index 0000000..0e6a88c
--- /dev/null
+++ b/app/src/main/java/com/sharad/demoapp/sync/SyncListener.java
@@ -0,0 +1,16 @@
+package com.sharad.demoapp.sync;
+
+/**
+ * This Interface provide call back on success or failure of Data sync.
+ * @author Sharad waghchaure
+ *
+ */
+public interface SyncListener{
+
+ void onSyncSuccess(int result, int taskId, Object object);
+
+ void onSyncFailure(int result, int taskId, String message);
+
+ void onSyncProgressUpdate(int progressPercent, String message);
+
+}
diff --git a/app/src/main/java/com/sharad/demoapp/sync/SyncManager.java b/app/src/main/java/com/sharad/demoapp/sync/SyncManager.java
new file mode 100644
index 0000000..3744898
--- /dev/null
+++ b/app/src/main/java/com/sharad/demoapp/sync/SyncManager.java
@@ -0,0 +1,104 @@
+package com.sharad.demoapp.sync;
+
+
+import android.app.Activity;
+import android.content.Context;
+
+import com.loopj.android.http.AsyncHttpClient;
+import com.loopj.android.http.AsyncHttpResponseHandler;
+import com.loopj.android.http.RequestParams;
+import com.sharad.demoapp.constant.URLConstants;
+import com.sharad.demoapp.network.DownloadHandler;
+import com.sharad.demoapp.network.DownloadListener;
+
+import cz.msebera.android.httpclient.message.BasicHeader;
+
+
+/**
+ * This class is responsible for request and handle response.
+ * This is the single point of controller where all events meets.
+ *
+ * @author Sharad waghchaure
+ */
+
+public class SyncManager implements ParseListener, DownloadListener {
+
+ private SyncListener syncListener;
+ private BasicHeader[] headers;
+ private int type;
+ private static AsyncHttpClient asyncHttpClient = new AsyncHttpClient();
+ //task ID8
+ public static final int LOGIN = 0, REGISTRATION = 2, GET_PHONE_DETAILS = 3;
+
+ public static final int TYPE_AUTO_SYNC = 0, TYPE_MANUAL_SYNC = 1;
+ public static final int SYNC_SUCCESS = 0, SYNC_FAIL = 1, NO_INTERNET = 2, SERVER_DOWN = 3;
+ private Context ctx;
+
+
+ public SyncManager(Context context, int type, SyncListener jobListener) {
+ this.ctx = context;
+ this.type = type;
+ this.syncListener = jobListener;
+ }
+
+ public SyncManager(Activity context, int type, SyncListener jobListener) {
+ this.ctx = context;
+ this.type = type;
+ this.syncListener = jobListener;
+
+ }
+
+ public void onNewParseJob(int taskID, String response) {
+
+ }
+
+ public void onParseSuccess(int taskID, Object mObject) {
+ syncListener.onSyncSuccess(SYNC_SUCCESS, taskID, mObject);
+
+ }
+
+ public void onParseFailed(int taskID) {
+
+ }
+
+
+ public void onDownloadFailure(int taskID, Throwable throwable, String response) {
+
+ syncListener.onSyncFailure(SERVER_DOWN, taskID, "Server time out");
+ }
+
+ @Override
+ public void onDownloadSuccess(int taskID, String response) {
+ AsyncParsingTask asyncParsingTask = new AsyncParsingTask(taskID, SyncManager.this, ctx);
+ asyncParsingTask.execute(response);
+
+ }
+
+
+ public void get(String url, RequestParams params, AsyncHttpResponseHandler responseHandler) {
+ asyncHttpClient.setTimeout(30000);
+ asyncHttpClient.get(url, params, responseHandler);
+ }
+
+ public void post(String url, RequestParams params, AsyncHttpResponseHandler responseHandler) {
+ asyncHttpClient.setTimeout(30000);
+ asyncHttpClient.post(url, params, responseHandler);
+ }
+
+ /**
+ * example : how to request and create params in your Activity or SyncManager
+ * This function is used to register with server.
+ */
+ public void doRegistration(String username, String email, String password) {
+ RequestParams params = new RequestParams();
+ params.put("email", email);
+ params.put("password", password);
+ params.put("username", username);
+ get(URLConstants.URL_REGISTRATION, params, new DownloadHandler(REGISTRATION, SyncManager.this));
+ }
+
+ public void getPhoneDetaills() {
+
+ get(URLConstants.URL_GET_PHONE_DETAILS, null, new DownloadHandler(GET_PHONE_DETAILS, SyncManager.this));
+ }
+}
diff --git a/app/src/main/java/com/sharad/demoapp/util/AlertView.java b/app/src/main/java/com/sharad/demoapp/util/AlertView.java
new file mode 100644
index 0000000..313b608
--- /dev/null
+++ b/app/src/main/java/com/sharad/demoapp/util/AlertView.java
@@ -0,0 +1,53 @@
+package com.sharad.demoapp.util;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.widget.Toast;
+
+public class AlertView
+{
+ public static void showError(String message, Context ctx)
+ {
+ showAlert("Error", message, ctx);
+ }
+
+ public static void showAlert(String message, Context ctx)
+ {
+ showAlert("Alert", message, ctx);
+ }
+
+ public static void showAlert(String title, String message, Context ctx)
+ {
+ //Create a builder
+ AlertDialog.Builder builder = new AlertDialog.Builder(ctx);
+ builder.setTitle(title);
+ builder.setMessage(message);
+ //add buttons and listener
+ EmptyListener pl = new EmptyListener();
+ builder.setPositiveButton("OK", pl);
+ //Create the dialog
+ AlertDialog ad = builder.create();
+ //show
+ ad.show();
+ }
+
+ public static void showShortToast(Context mContext,String msg)
+ {
+ Toast toast = Toast.makeText(mContext, msg, Toast.LENGTH_SHORT);
+ toast.show();
+ }
+ public static void showLongToast(Context mContext,String msg)
+ {
+ Toast toast = Toast.makeText(mContext, msg, Toast.LENGTH_LONG);
+ toast.show();
+ }
+}
+
+class EmptyListener implements DialogInterface.OnClickListener
+{
+ @Override
+ public void onClick(DialogInterface dialog, int which)
+ {
+ }
+}
diff --git a/app/src/main/java/com/sharad/demoapp/util/DataHelper.java b/app/src/main/java/com/sharad/demoapp/util/DataHelper.java
new file mode 100644
index 0000000..64bd3d5
--- /dev/null
+++ b/app/src/main/java/com/sharad/demoapp/util/DataHelper.java
@@ -0,0 +1,41 @@
+package com.sharad.demoapp.util;
+
+
+import android.app.Activity;
+import android.content.Context;
+
+public class DataHelper {
+
+ private Context mContext;
+ private Activity mActivity;
+ public static final String APP_TITLE = "Massive Infinity";
+
+ public Activity getActivity() {
+ return mActivity;
+ }
+
+ public void setActivity(Activity mActivity) {
+ this.mActivity = mActivity;
+ }
+
+ static DataHelper mDataHelper = new DataHelper();
+
+ public static DataHelper getInstance() {
+ if (mDataHelper != null)
+ return mDataHelper;
+ else {
+ mDataHelper = new DataHelper();
+ }
+ return mDataHelper;
+ }
+
+ public Context getContext() {
+ return mContext;
+ }
+
+ public void setContext(Context mContext) {
+ this.mContext = mContext;
+ }
+
+
+}
diff --git a/app/src/main/java/com/sharad/demoapp/util/GPSTracker.java b/app/src/main/java/com/sharad/demoapp/util/GPSTracker.java
new file mode 100644
index 0000000..1ae125f
--- /dev/null
+++ b/app/src/main/java/com/sharad/demoapp/util/GPSTracker.java
@@ -0,0 +1,136 @@
+package com.winjit.util;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.location.Location;
+import android.location.LocationListener;
+import android.location.LocationManager;
+import android.os.Bundle;
+import android.util.Log;
+import android.provider.Settings;
+
+public class GPSTracker implements LocationListener {
+
+ // flag for GPS status
+ boolean isGPSEnabled = false;
+
+ // flag for network status
+ boolean isNetworkEnabled = false;
+
+ boolean canGetLocation = false;
+
+ Location location; // location
+ double latitude; // latitude
+ double longitude; // longitude
+
+ // Declaring a Location Manager
+ protected LocationManager locationManager;
+ Context mContext;
+
+ public GPSTracker(Context context) {
+ this.mContext = context;
+ getLocation();
+ }
+
+ public Location getLocation() {
+ try {
+ locationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
+
+ // getting GPS status
+ isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
+
+ // getting network status
+ isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
+
+ if (!isGPSEnabled) {
+ showSettingsAlert();
+ } else{
+ // if GPS Enabled get lat/long using GPS Services
+ if (isGPSEnabled) {
+ if (location == null) {
+ Log.d("GPS Enabled", "GPS Enabled");
+ if (locationManager != null) {
+ location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
+
+ }
+ }
+ }
+ }
+ if(!isNetworkEnabled && !isGPSEnabled)
+ {
+ showSettingsAlert();
+ }else{
+ // First get location from Network Provider
+ if (isNetworkEnabled) {
+ Log.d("Network", "Network");
+ if (locationManager != null) {
+ location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
+
+ }
+ }
+
+ }
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ return location;
+ }
+
+ public void onLocationChanged(Location location) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void onStatusChanged(String provider, int status, Bundle extras) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void onProviderEnabled(String provider) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void onProviderDisabled(String provider) {
+ // TODO Auto-generated method stub
+
+ }
+
+ /**
+ * Function to show settings alert dialog
+ * */
+ public void showSettingsAlert() {
+ AlertDialog.Builder alertDialog = new AlertDialog.Builder(mContext);
+
+ // Setting Dialog Title
+ alertDialog.setTitle("GPS settings");
+
+ // Setting Dialog Message
+ alertDialog.setMessage("GPS is not enabled. Do you want to go to settings menu?");
+
+ // Setting Icon to Dialog
+ // alertDialog.setIcon(R.drawable.delete);
+
+ // On pressing Settings button
+ alertDialog.setPositiveButton("Settings", new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
+ mContext.startActivity(intent);
+ }
+ });
+
+ // on pressing cancel button
+ alertDialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ dialog.cancel();
+ }
+ });
+
+ // Showing Alert Message
+ alertDialog.show();
+ }
+}
diff --git a/app/src/main/java/com/sharad/demoapp/util/GestureListener.java b/app/src/main/java/com/sharad/demoapp/util/GestureListener.java
new file mode 100644
index 0000000..6f67dfe
--- /dev/null
+++ b/app/src/main/java/com/sharad/demoapp/util/GestureListener.java
@@ -0,0 +1,42 @@
+package com.winjit.util;
+
+import android.view.GestureDetector.SimpleOnGestureListener;
+import android.view.MotionEvent;
+
+public class GestureListener extends SimpleOnGestureListener{
+
+ private static final int SWIPE_MIN_DISTANCE = 120;
+ private static final int SWIPE_THRESHOLD_VELOCITY = 200;
+
+ @Override
+ public boolean onFling(MotionEvent e1, MotionEvent e2,
+ float velocityX, float velocityY) {
+
+ if(e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE &&
+ Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
+ //From Right to Left
+ return true;
+ } else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE &&
+ Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
+ //From Left to Right
+ return true;
+ }
+
+ if(e1.getY() - e2.getY() > SWIPE_MIN_DISTANCE &&
+ Math.abs(velocityY) > SWIPE_THRESHOLD_VELOCITY) {
+ //From Bottom to Top
+ return true;
+ } else if (e2.getY() - e1.getY() > SWIPE_MIN_DISTANCE &&
+ Math.abs(velocityY) > SWIPE_THRESHOLD_VELOCITY) {
+ //From Top to Bottom
+ return true;
+ }
+ return false;
+ }
+ @Override
+ public boolean onDown(MotionEvent e) {
+ //always return true since all gestures always begin with onDown and
+ //if this returns false, the framework won't try to pick up onFling for example.
+ return true;
+ }
+}
diff --git a/app/src/main/java/com/sharad/demoapp/util/PreferenceHandler.java b/app/src/main/java/com/sharad/demoapp/util/PreferenceHandler.java
new file mode 100644
index 0000000..a2029cf
--- /dev/null
+++ b/app/src/main/java/com/sharad/demoapp/util/PreferenceHandler.java
@@ -0,0 +1,69 @@
+package com.winjit.util;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.Editor;
+
+/**
+ * Common PrefrenceConnector class for storing preference values.
+ *
+ * @author Prakash G
+ */
+public class PreferenceHandler {
+
+ public static final String PREF_NAME = "YOUR_PREFERENCES_NAME";
+ public static final int MODE = Context.MODE_PRIVATE;
+
+ public static void writeBoolean(Context context, String key, boolean value) {
+ getEditor(context).putBoolean(key, value).commit();
+ }
+
+ public static boolean readBoolean(Context context, String key,
+ boolean defValue) {
+ return getPreferences(context).getBoolean(key, defValue);
+ }
+
+ public static void writeInteger(Context context, String key, int value) {
+ getEditor(context).putInt(key, value).commit();
+ }
+
+ public static int readInteger(Context context, String key, int defValue) {
+ return getPreferences(context).getInt(key, defValue);
+ }
+
+ public static void writeString(Context context, String key, String value) {
+ getEditor(context).putString(key, value).commit();
+ }
+
+ public static String readString(Context context, String key, String defValue) {
+ return getPreferences(context).getString(key, defValue);
+ }
+
+ public static void writeFloat(Context context, String key, float value) {
+ getEditor(context).putFloat(key, value).commit();
+ }
+
+ public static float readFloat(Context context, String key, float defValue) {
+ return getPreferences(context).getFloat(key, defValue);
+ }
+
+ public static void writeLong(Context context, String key, long value) {
+ getEditor(context).putLong(key, value).commit();
+ }
+
+ public static long readLong(Context context, String key, long defValue) {
+ return getPreferences(context).getLong(key, defValue);
+ }
+
+ public static String readList(Context context, String key, String defValue) {
+ return getPreferences(context).getString(key, defValue);
+ }
+
+ public static SharedPreferences getPreferences(Context context) {
+ return context.getSharedPreferences(PREF_NAME, MODE);
+ }
+
+ public static Editor getEditor(Context context) {
+ return getPreferences(context).edit();
+ }
+}
diff --git a/app/src/main/java/com/sharad/demoapp/util/UtilityMethod.java b/app/src/main/java/com/sharad/demoapp/util/UtilityMethod.java
new file mode 100644
index 0000000..60dcae3
--- /dev/null
+++ b/app/src/main/java/com/sharad/demoapp/util/UtilityMethod.java
@@ -0,0 +1,112 @@
+package com.sharad.demoapp.util;
+
+import java.io.ByteArrayOutputStream;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+import android.app.Activity;
+import android.app.ProgressDialog;
+import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.Signature;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.util.Base64;
+import android.util.Log;
+
+
+public class UtilityMethod {
+ static ProgressDialog progressDialog;
+
+ // method for bitmap to base64
+ public static String encodeTobase64(Bitmap image) {
+ Bitmap immage = image;
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ immage.compress(Bitmap.CompressFormat.PNG, 100, baos);
+ byte[] b = baos.toByteArray();
+ String imageEncoded = Base64.encodeToString(b, Base64.DEFAULT);
+
+ Log.d("Image Log:", imageEncoded);
+ return imageEncoded;
+ }
+
+ // method for base64 to bitmap
+ public static Bitmap decodeBase64(String input) {
+ byte[] decodedByte = Base64.decode(input, 0);
+ return BitmapFactory.decodeByteArray(decodedByte, 0, decodedByte.length);
+ }
+
+ public static void showHashKey(Context context) {
+ try {
+ PackageInfo info = context.getPackageManager().getPackageInfo("com.recipe.activities", PackageManager.GET_SIGNATURES); // Your
+ // package
+ // name
+ // here
+ for (Signature signature : info.signatures) {
+ MessageDigest md = MessageDigest.getInstance("SHA");
+ md.update(signature.toByteArray());
+ Log.i("KeyHash:", Base64.encodeToString(md.digest(), Base64.DEFAULT));
+ }
+ } catch (NameNotFoundException e) {
+ } catch (NoSuchAlgorithmException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public static void progressDialogShow(Context mContext) {
+
+ progressDialog = new ProgressDialog(mContext);
+
+ progressDialog.setTitle(DataHelper.APP_TITLE);
+ progressDialog.setMessage("Please wait...");
+ progressDialog.setCancelable(false);
+
+ //progressDialog.setIndeterminate(true);
+ //progressDialog.setIndeterminateDrawable(mContext.getResources().getDrawable(R.anim.progressbar_animation));
+
+ // progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
+ progressDialog.show();
+ }
+
+ public static void progressDialogDismiss(Activity mContext) {
+
+ mContext.runOnUiThread(new Runnable() {
+ public void run() {
+
+ try {
+
+ if (progressDialog != null) {
+ progressDialog.dismiss();
+ }
+
+ progressDialog = null;
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ }
+ });
+
+ }
+ public static boolean isNumber(String string) {
+ if (string == null || string.isEmpty()) {
+ return false;
+ }
+ int i = 0;
+ if (string.charAt(0) == '-') {
+ if (string.length() > 1) {
+ i++;
+ } else {
+ return false;
+ }
+ }
+ for (; i < string.length(); i++) {
+ if (!Character.isDigit(string.charAt(i))) {
+ return false;
+ }
+ }
+ return true;
+ }
+}
diff --git a/app/src/main/res/drawable/ic_add_circle_outline_white_24dp.png b/app/src/main/res/drawable/ic_add_circle_outline_white_24dp.png
new file mode 100644
index 0000000..ac94274
Binary files /dev/null and b/app/src/main/res/drawable/ic_add_circle_outline_white_24dp.png differ
diff --git a/app/src/main/res/drawable/motorolaxoom.jpg b/app/src/main/res/drawable/motorolaxoom.jpg
new file mode 100644
index 0000000..8f89555
Binary files /dev/null and b/app/src/main/res/drawable/motorolaxoom.jpg differ
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
new file mode 100644
index 0000000..b45fc70
--- /dev/null
+++ b/app/src/main/res/layout/activity_main.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/content_main.xml b/app/src/main/res/layout/content_main.xml
new file mode 100644
index 0000000..8285df6
--- /dev/null
+++ b/app/src/main/res/layout/content_main.xml
@@ -0,0 +1,9 @@
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/custom_cardview_row.xml b/app/src/main/res/layout/custom_cardview_row.xml
new file mode 100644
index 0000000..7194aa6
--- /dev/null
+++ b/app/src/main/res/layout/custom_cardview_row.xml
@@ -0,0 +1,59 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_home.xml b/app/src/main/res/layout/fragment_home.xml
new file mode 100644
index 0000000..ca769cc
--- /dev/null
+++ b/app/src/main/res/layout/fragment_home.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_phone_details.xml b/app/src/main/res/layout/fragment_phone_details.xml
new file mode 100644
index 0000000..6d03738
--- /dev/null
+++ b/app/src/main/res/layout/fragment_phone_details.xml
@@ -0,0 +1,78 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/menu/menu_main.xml b/app/src/main/res/menu/menu_main.xml
new file mode 100644
index 0000000..b1cb908
--- /dev/null
+++ b/app/src/main/res/menu/menu_main.xml
@@ -0,0 +1,6 @@
+
+
+
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..cde69bc
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..c133a0c
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..bfa42f0
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..324e72c
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..aee44e1
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/values-v21/styles.xml b/app/src/main/res/values-v21/styles.xml
new file mode 100644
index 0000000..65d0c39
--- /dev/null
+++ b/app/src/main/res/values-v21/styles.xml
@@ -0,0 +1,8 @@
+>
+
+
diff --git a/app/src/main/res/values-w820dp/dimens.xml b/app/src/main/res/values-w820dp/dimens.xml
new file mode 100644
index 0000000..63fc816
--- /dev/null
+++ b/app/src/main/res/values-w820dp/dimens.xml
@@ -0,0 +1,6 @@
+
+
+ 64dp
+
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
new file mode 100644
index 0000000..3ab3e9c
--- /dev/null
+++ b/app/src/main/res/values/colors.xml
@@ -0,0 +1,6 @@
+
+
+ #3F51B5
+ #303F9F
+ #FF4081
+
diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml
new file mode 100644
index 0000000..812cb7b
--- /dev/null
+++ b/app/src/main/res/values/dimens.xml
@@ -0,0 +1,6 @@
+
+
+ 16dp
+ 16dp
+ 16dp
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..b2e3a19
--- /dev/null
+++ b/app/src/main/res/values/strings.xml
@@ -0,0 +1,7 @@
+
+ Infinity
+ Settings
+ xPhone
+ snippet
+
+
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000..d1d882e
--- /dev/null
+++ b/app/src/main/res/values/styles.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/test/java/com/sharad/demoapp/ExampleUnitTest.java b/app/src/test/java/com/sharad/demoapp/ExampleUnitTest.java
new file mode 100644
index 0000000..34f8a0c
--- /dev/null
+++ b/app/src/test/java/com/sharad/demoapp/ExampleUnitTest.java
@@ -0,0 +1,15 @@
+package com.sharad.demoapp;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * To work on unit tests, switch the Test Artifact in the Build Variants view.
+ */
+public class ExampleUnitTest {
+ @Test
+ public void addition_isCorrect() throws Exception {
+ assertEquals(4, 2 + 2);
+ }
+}
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 0000000..be515a8
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,23 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+
+buildscript {
+ repositories {
+ jcenter()
+ }
+ dependencies {
+ classpath 'com.android.tools.build:gradle:1.3.0'
+
+ // NOTE: Do not place your application dependencies here; they belong
+ // in the individual module build.gradle files
+ }
+}
+
+allprojects {
+ repositories {
+ jcenter()
+ }
+}
+
+task clean(type: Delete) {
+ delete rootProject.buildDir
+}
diff --git a/gradle.properties b/gradle.properties
new file mode 100644
index 0000000..1d3591c
--- /dev/null
+++ b/gradle.properties
@@ -0,0 +1,18 @@
+# Project-wide Gradle settings.
+
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+# Default value: -Xmx10248m -XX:MaxPermSize=256m
+# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
+
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
\ No newline at end of file
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..8c0fb64
Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..4090389
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Fri Jan 22 15:15:39 IST 2016
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-2.4-all.zip
diff --git a/gradlew b/gradlew
new file mode 100644
index 0000000..91a7e26
--- /dev/null
+++ b/gradlew
@@ -0,0 +1,164 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+ echo "$*"
+}
+
+die ( ) {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+esac
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched.
+if $cygwin ; then
+ [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+fi
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >&-
+APP_HOME="`pwd -P`"
+cd "$SAVED" >&-
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+ JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
diff --git a/gradlew.bat b/gradlew.bat
new file mode 100644
index 0000000..8a0b282
--- /dev/null
+++ b/gradlew.bat
@@ -0,0 +1,90 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windowz variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+if "%@eval[2+2]" == "4" goto 4NT_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+goto execute
+
+:4NT_args
+@rem Get arguments from the 4NT Shell from JP Software
+set CMD_LINE_ARGS=%$
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 0000000..e7b4def
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1 @@
+include ':app'