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/gradle.xml b/.idea/gradle.xml new file mode 100644 index 0000000..00cf481 --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/README_ABT_APP.md b/README_ABT_APP.md new file mode 100644 index 0000000..32a4aca --- /dev/null +++ b/README_ABT_APP.md @@ -0,0 +1,35 @@ +# ShowCaseAndroidApp # + +This application gets a list of devices and the android versions and displays them accordingly. +It allows users to be able to add new android versions to the list and also add new devices with a limitation to not being able to add images to the devices. + +It has the following features: +- Add a device +- Add an android version +- Delete a device +- Delete an android version +- Get a list of devices and android versions +- View device details + +Pull to refresh allows new data to get synced with the existing data. There is a database storage that allows data to be fetched from it with the capability of syncing only the latest entries using pull to refresh + +# How to get setup # + +Android Studio v2.0 Preview 4 has been used for this application, however, you can use any earlier version of Android Studio. JDK 1.8 and JDK 1.7 can be used. +- Install JDK and any version of Android Studio +- Clone this repository or else download the application by Selecting import from VCS (GitHub being an option) +- Build the project +- You will find the apk in the folder /app/build/outputs/apk/ + +# Libraries used # +The following libraries have been used in this application +- AppCompat v7:23.1.1 +- GSON +- Squareup OK HTTP +- Retrofit v2.0.0-beta2 +- Retrofit GSON Converter +- MaterialEditText +- SwipeLayout +- Android Support v4 +- FloatingActionButton +- CardView \ No newline at end of file diff --git a/ShowCaseAndroidApp.iml b/ShowCaseAndroidApp.iml new file mode 100644 index 0000000..d141a98 --- /dev/null +++ b/ShowCaseAndroidApp.iml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..6933e19 --- /dev/null +++ b/app/.gitignore @@ -0,0 +1,3 @@ +/build/generated +/build/intermediates +/build/tmp diff --git a/app/app.iml b/app/app.iml new file mode 100644 index 0000000..3fc4f6f --- /dev/null +++ b/app/app.iml @@ -0,0 +1,112 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..db02160 --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,39 @@ +apply plugin: 'com.android.application' + +android { + compileSdkVersion 23 + buildToolsVersion "23.0.1" + + defaultConfig { + applicationId "com.dharashah.showcaseandroidapp" + minSdkVersion 14 + targetSdkVersion 23 + versionCode 1 + versionName "1.0" + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_7 + targetCompatibility JavaVersion.VERSION_1_7 + } +} + +dependencies { + compile fileTree(include: ['*.jar'], dir: 'libs') + compile 'com.android.support:appcompat-v7:23.1.1' + compile 'com.google.code.gson:gson:2.2.4' + compile 'com.squareup.okhttp:okhttp:2.0.0' + compile 'com.squareup.retrofit:retrofit:2.0.0-beta2' + compile 'com.squareup.retrofit:converter-gson:2.0.0-beta2' + compile 'com.rengwuxian.materialedittext:library:2.1.4' + compile 'com.mcxiaoke.volley:library:1.0.19' + compile 'com.daimajia.swipelayout:library:1.2.0' + compile 'com.android.support:support-v4:23.1.1' + compile 'com.getbase:floatingactionbutton:1.10.1' + compile 'com.android.support:cardview-v7:23.1.1' +} diff --git a/app/build/outputs/apk/app-debug-unaligned.apk b/app/build/outputs/apk/app-debug-unaligned.apk new file mode 100644 index 0000000..bc554ad Binary files /dev/null and b/app/build/outputs/apk/app-debug-unaligned.apk differ diff --git a/app/build/outputs/apk/app-debug.apk b/app/build/outputs/apk/app-debug.apk new file mode 100644 index 0000000..2474897 Binary files /dev/null and b/app/build/outputs/apk/app-debug.apk differ diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..932d9f6 --- /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:\Dhara\Android Sdks/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/androidTest/java/com/dharashah/showcaseandroidapp/ApplicationTest.java b/app/src/androidTest/java/com/dharashah/showcaseandroidapp/ApplicationTest.java new file mode 100644 index 0000000..df8a593 --- /dev/null +++ b/app/src/androidTest/java/com/dharashah/showcaseandroidapp/ApplicationTest.java @@ -0,0 +1,13 @@ +package com.dharashah.showcaseandroidapp; + +import android.app.Application; +import android.test.ApplicationTestCase; + +/** + * Testing Fundamentals + */ +public class ApplicationTest extends ApplicationTestCase { + public ApplicationTest() { + super(Application.class); + } +} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..d2f6ac0 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/java/com/dharashah/showcaseandroidapp/ShowCaseApp.java b/app/src/main/java/com/dharashah/showcaseandroidapp/ShowCaseApp.java new file mode 100644 index 0000000..65c9343 --- /dev/null +++ b/app/src/main/java/com/dharashah/showcaseandroidapp/ShowCaseApp.java @@ -0,0 +1,26 @@ +package com.dharashah.showcaseandroidapp; + +import android.app.Application; +import android.content.Context; + +/** + * Created by USER on 21-01-2016. + */ +public class ShowCaseApp extends Application { + private static ShowCaseApp mApp; + private static Context mContext; + + @Override + public void onCreate() { + super.onCreate(); + mApp= this; + mContext = this; + } + + public static ShowCaseApp getAppContext(){ + if(mApp == null) { + mApp = (ShowCaseApp)mContext; + } + return mApp; + } +} diff --git a/app/src/main/java/com/dharashah/showcaseandroidapp/activity/AddDeviceActivity.java b/app/src/main/java/com/dharashah/showcaseandroidapp/activity/AddDeviceActivity.java new file mode 100644 index 0000000..5cda7e6 --- /dev/null +++ b/app/src/main/java/com/dharashah/showcaseandroidapp/activity/AddDeviceActivity.java @@ -0,0 +1,233 @@ +package com.dharashah.showcaseandroidapp.activity; + +import android.app.Dialog; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v7.widget.Toolbar; +import android.text.InputFilter; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; +import android.widget.AdapterView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.TextView; +import android.widget.Toast; + +import com.dharashah.showcaseandroidapp.R; +import com.dharashah.showcaseandroidapp.ShowCaseApp; +import com.dharashah.showcaseandroidapp.adapter.AndroidVersionsAdapter; +import com.dharashah.showcaseandroidapp.db.DBHelper; +import com.dharashah.showcaseandroidapp.model.AndroidHistory; +import com.dharashah.showcaseandroidapp.model.Devices; +import com.dharashah.showcaseandroidapp.network.RestClient; +import com.dharashah.showcaseandroidapp.utility.CustomInputValidator; +import com.rengwuxian.materialedittext.MaterialEditText; + +import java.util.List; + +import retrofit.Call; +import retrofit.Callback; +import retrofit.Response; +import retrofit.Retrofit; + +/** + * Created by Dhara Shah on 22/01/2016. + */ +public class AddDeviceActivity extends BaseActivity implements View.OnClickListener, View.OnFocusChangeListener { + private MaterialEditText mEtDeviceName; + private MaterialEditText mEtDeviceDesc; + private MaterialEditText mEtAndroidVersion; + private LinearLayout mLinDeviceName; + private LinearLayout mLinDeviceDesc; + private LinearLayout mLinAndroidVersion; + private DBHelper mDbHelper; + private int mAndroidVersionId; + private Toolbar mToolbar; + private TextView mTxtTitle; + + @Override + public void onBackPressed() { + super.onBackPressed(); + overridePendingTransition(R.anim.slide_in_down, R.anim.slide_out_down); + } + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_add_device); + initToolbar(); + initView(); + } + + private void initToolbar() { + mToolbar = (Toolbar)findViewById(R.id.toolbar); + setSupportActionBar(mToolbar); + mTxtTitle = (TextView)findViewById(R.id.txtTitle); + mToolbar.setNavigationIcon(R.drawable.abc_ic_clear_mtrl_alpha); + mTxtTitle.setText("Add Device"); + mToolbar.setNavigationOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + onBackPressed(); + } + }); + } + + private void initView() { + mEtDeviceName = (MaterialEditText)findViewById(R.id.etDeviceName); + mEtDeviceDesc = (MaterialEditText)findViewById(R.id.etDeviceDescription); + mEtAndroidVersion = (MaterialEditText)findViewById(R.id.etAndroidVersion); + mLinDeviceName = (LinearLayout)findViewById(R.id.linDeviceName); + mLinDeviceDesc = (LinearLayout)findViewById(R.id.linDeviceDescription); + mLinAndroidVersion = (LinearLayout)findViewById(R.id.linAndroidVersion); + + mEtAndroidVersion.setOnClickListener(this); + + mEtDeviceName.addTextChangedListener(new CustomInputValidator(mEtDeviceName)); + mEtDeviceName.setOnFocusChangeListener(AddDeviceActivity.this); + + mEtDeviceDesc.setFilters(new InputFilter[]{new InputFilter.LengthFilter(256)}); + mEtDeviceDesc.addTextChangedListener(new CustomInputValidator(mEtDeviceDesc)); + mEtDeviceDesc.setOnFocusChangeListener(AddDeviceActivity.this); + + mDbHelper = DBHelper.getInstance(ShowCaseApp.getAppContext()); + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.etAndroidVersion: + bindAndroidVersions(); + break; + } + } + + /** + * Binds the android versions to the dropdrown pop up view + */ + private void bindAndroidVersions() { + hideToolTip(); + final Dialog dialog = new Dialog(AddDeviceActivity.this); + dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); + dialog.setContentView(R.layout.pop_up_android_versions); + final ListView list = (ListView) dialog.findViewById(R.id.list); + list.setChoiceMode(ListView.CHOICE_MODE_SINGLE); + + final List androidVersionList = mDbHelper.getAndroidVersions(" ASC "); + AndroidVersionsAdapter adapter = + new AndroidVersionsAdapter(ShowCaseApp.getAppContext(), + R.layout.individual_row_android_versions, androidVersionList); + list.setAdapter(adapter); + list.setOnItemClickListener(new AdapterView.OnItemClickListener() { + + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + list.setPressed(true); + dialog.dismiss(); + mAndroidVersionId = androidVersionList.get(position).getAndroidId(); + mEtAndroidVersion.setText(androidVersionList.get(position).getName()); + getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN); + } + }); + dialog.setCancelable(true); + dialog.show(); + } + + private void hideToolTip() { + mLinAndroidVersion.setVisibility(View.GONE); + mLinDeviceDesc.setVisibility(View.GONE); + mLinDeviceName.setVisibility(View.GONE); + } + + @Override + public void onFocusChange(View v, boolean hasFocus) { + switch (v.getId()) { + case R.id.etDeviceName: + if(hasFocus) { + mLinDeviceName.setVisibility(View.VISIBLE); + }else { + mLinDeviceName.setVisibility(View.GONE); + } + break; + + case R.id.etDeviceDescription: + if(hasFocus) { + mLinDeviceDesc.setVisibility(View.VISIBLE); + }else { + mLinDeviceDesc.setVisibility(View.GONE); + } + break; + } + } + + @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_add_device, 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_done) { + // save to the db and also save to the server + validateSubmit(); + return true; + } + + return super.onOptionsItemSelected(item); + } + + private void validateSubmit() { + hideToolTip(); + + if(CustomInputValidator.checkError(mEtDeviceName)) + return; + if(CustomInputValidator.checkError(mEtDeviceDesc)) + return; + if(CustomInputValidator.checkError(mEtAndroidVersion)) + return; + + Devices device = new Devices(); + device.setAndroidId(mAndroidVersionId); + device.setDeviceDesc(mEtDeviceDesc.getText().toString().trim()); + device.setDeviceName(mEtDeviceName.getText().toString().trim()); + device.setImageURL(""); + + if(RestClient.isNetworkAvailable()) { + mDbHelper.insertNewDevice(device); + + Call call = new RestClient().getApiService().addDevice(device); + call.enqueue(new Callback() { + @Override + public void onResponse(Response response, Retrofit retrofit) { + if(response.errorBody()==null){ + Toast.makeText(ShowCaseApp.getAppContext(), + "Device added successfully!",Toast.LENGTH_LONG).show(); + onBackPressed(); + } + + } + + @Override + public void onFailure(Throwable t) { + + } + }); + }else { + Toast.makeText(ShowCaseApp.getAppContext(), + ShowCaseApp.getAppContext().getResources().getString(R.string.no_internet), + Toast.LENGTH_LONG).show(); + + } + } +} diff --git a/app/src/main/java/com/dharashah/showcaseandroidapp/activity/AddVersionActivity.java b/app/src/main/java/com/dharashah/showcaseandroidapp/activity/AddVersionActivity.java new file mode 100644 index 0000000..4a51d02 --- /dev/null +++ b/app/src/main/java/com/dharashah/showcaseandroidapp/activity/AddVersionActivity.java @@ -0,0 +1,226 @@ +package com.dharashah.showcaseandroidapp.activity; + +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v7.widget.Toolbar; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.widget.LinearLayout; +import android.widget.TextView; +import android.widget.Toast; + +import com.dharashah.showcaseandroidapp.R; +import com.dharashah.showcaseandroidapp.ShowCaseApp; +import com.dharashah.showcaseandroidapp.db.DBHelper; +import com.dharashah.showcaseandroidapp.model.AndroidHistory; +import com.dharashah.showcaseandroidapp.network.RestClient; +import com.dharashah.showcaseandroidapp.utility.CustomInputValidator; +import com.rengwuxian.materialedittext.MaterialEditText; + +import retrofit.Call; +import retrofit.Callback; +import retrofit.Response; +import retrofit.Retrofit; + +/** + * Created by user on 22/01/2016. + */ +public class AddVersionActivity extends BaseActivity implements View.OnFocusChangeListener { + private MaterialEditText mEtAndroidName; + private MaterialEditText mEtAndroidCodeName; + private MaterialEditText mEtAndroidVersion; + private MaterialEditText mEtDistribution; + private MaterialEditText mEtTarget; + private LinearLayout mLinAndroidName; + private LinearLayout mLinAndroidCodeName; + private LinearLayout mLinAndroidVersion; + private LinearLayout mLinTarget; + private LinearLayout mLinDistribution; + private DBHelper mDbHelper; + private Toolbar mToolbar; + private TextView mTxtTitle; + + @Override + public void onBackPressed() { + super.onBackPressed(); + overridePendingTransition(R.anim.slide_in_down, R.anim.slide_out_down); + } + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_add_history); + initToolbar(); + initView(); + } + + private void initToolbar() { + mToolbar = (Toolbar)findViewById(R.id.toolbar); + setSupportActionBar(mToolbar); + mTxtTitle = (TextView)findViewById(R.id.txtTitle); + mTxtTitle.setText("Add Android Version"); + mToolbar.setNavigationIcon(R.drawable.abc_ic_clear_mtrl_alpha); + mToolbar.setNavigationOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + onBackPressed(); + } + }); + } + + private void initView() { + mEtAndroidName = (MaterialEditText)findViewById(R.id.etAndroidName); + mEtAndroidCodeName = (MaterialEditText)findViewById(R.id.etAndroidCodeName); + mEtAndroidVersion = (MaterialEditText)findViewById(R.id.etAndroidVersion); + mEtDistribution = (MaterialEditText)findViewById(R.id.etDistribution); + mEtTarget = (MaterialEditText)findViewById(R.id.etAndroidTarget); + + mLinAndroidName = (LinearLayout)findViewById(R.id.linAndroidName); + mLinAndroidCodeName = (LinearLayout)findViewById(R.id.linAndroidCodeName); + mLinAndroidVersion = (LinearLayout)findViewById(R.id.linAndroidVersion); + mLinTarget = (LinearLayout)findViewById(R.id.linAndroidTarget); + mLinDistribution = (LinearLayout)findViewById(R.id.linDistribution); + + mEtAndroidName.addTextChangedListener(new CustomInputValidator(mEtAndroidName)); + mEtAndroidName.setOnFocusChangeListener(AddVersionActivity.this); + + mEtAndroidCodeName.addTextChangedListener(new CustomInputValidator(mEtAndroidCodeName)); + mEtAndroidCodeName.setOnFocusChangeListener(AddVersionActivity.this); + + mEtAndroidVersion.addTextChangedListener(new CustomInputValidator(mEtAndroidVersion)); + mEtAndroidVersion.setOnFocusChangeListener(AddVersionActivity.this); + + mEtTarget.addTextChangedListener(new CustomInputValidator(mEtTarget)); + mEtTarget.setOnFocusChangeListener(AddVersionActivity.this); + + mEtDistribution.addTextChangedListener(new CustomInputValidator(mEtDistribution)); + mEtDistribution.setOnFocusChangeListener(AddVersionActivity.this); + + mDbHelper = DBHelper.getInstance(ShowCaseApp.getAppContext()); + } + + private void hideToolTip() { + mLinAndroidVersion.setVisibility(View.GONE); + mLinAndroidCodeName.setVisibility(View.GONE); + mLinAndroidName.setVisibility(View.GONE); + mLinTarget.setVisibility(View.GONE); + mLinDistribution.setVisibility(View.GONE); + } + + @Override + public void onFocusChange(View v, boolean hasFocus) { + switch (v.getId()) { + case R.id.etAndroidName: + if(hasFocus) { + mLinAndroidName.setVisibility(View.VISIBLE); + }else { + mLinAndroidName.setVisibility(View.GONE); + } + break; + + case R.id.etAndroidCodeName: + if(hasFocus) { + mLinAndroidCodeName.setVisibility(View.VISIBLE); + }else { + mLinAndroidCodeName.setVisibility(View.GONE); + } + break; + + case R.id.etAndroidVersion: + if(hasFocus) { + mLinAndroidVersion.setVisibility(View.VISIBLE); + }else { + mLinAndroidVersion.setVisibility(View.GONE); + } + break; + + case R.id.etAndroidTarget: + if(hasFocus) { + mLinTarget.setVisibility(View.VISIBLE); + }else { + mLinTarget.setVisibility(View.GONE); + } + break; + + case R.id.etDistribution: + if(hasFocus) { + mLinDistribution.setVisibility(View.VISIBLE); + }else { + mLinDistribution.setVisibility(View.GONE); + } + break; + } + } + + @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_add_device, 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_done) { + // save to the db and also save to the server + validateSubmit(); + return true; + } + + return super.onOptionsItemSelected(item); + } + + private void validateSubmit() { + hideToolTip(); + + if(CustomInputValidator.checkError(mEtAndroidName)) + return; + if(CustomInputValidator.checkError(mEtAndroidCodeName)) + return; + if(CustomInputValidator.checkError(mEtAndroidVersion)) + return; + if(CustomInputValidator.checkError(mEtTarget)) + return; + if(CustomInputValidator.checkError(mEtDistribution)) + return; + + AndroidHistory history = new AndroidHistory(); + history.setCodeName(mEtAndroidCodeName.getText().toString().trim()); + history.setTarget(mEtTarget.getText().toString().trim()); + history.setDistribution(mEtDistribution.getText().toString().trim() + "%"); + history.setVersion(mEtAndroidVersion.getText().toString().trim()); + + if(RestClient.isNetworkAvailable()) { + Call call = new RestClient().getApiService().addAndroidVersion(history); + call.enqueue(new Callback() { + @Override + public void onResponse(Response response, Retrofit retrofit) { + if(response.errorBody()==null){ + Toast.makeText(ShowCaseApp.getAppContext(), + "Android version added successfully!",Toast.LENGTH_LONG).show(); + onBackPressed(); + } + + } + + @Override + public void onFailure(Throwable t) { + + } + }); + + mDbHelper.insertAndroidVersion(history); + }else { + Toast.makeText(ShowCaseApp.getAppContext(), + ShowCaseApp.getAppContext().getResources().getString(R.string.no_internet), + Toast.LENGTH_LONG).show(); + } + } +} diff --git a/app/src/main/java/com/dharashah/showcaseandroidapp/activity/BaseActivity.java b/app/src/main/java/com/dharashah/showcaseandroidapp/activity/BaseActivity.java new file mode 100644 index 0000000..da94941 --- /dev/null +++ b/app/src/main/java/com/dharashah/showcaseandroidapp/activity/BaseActivity.java @@ -0,0 +1,20 @@ +package com.dharashah.showcaseandroidapp.activity; + +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v7.app.AppCompatActivity; + +import com.dharashah.showcaseandroidapp.utility.CustomExceptionHandler; + +/** + * Created by user on 22/01/2016. + */ +public class BaseActivity extends AppCompatActivity { + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if(!(Thread.getDefaultUncaughtExceptionHandler() instanceof CustomExceptionHandler)) { + Thread.setDefaultUncaughtExceptionHandler(new CustomExceptionHandler(this)); + } + } +} diff --git a/app/src/main/java/com/dharashah/showcaseandroidapp/activity/MainActivity.java b/app/src/main/java/com/dharashah/showcaseandroidapp/activity/MainActivity.java new file mode 100644 index 0000000..0db3366 --- /dev/null +++ b/app/src/main/java/com/dharashah/showcaseandroidapp/activity/MainActivity.java @@ -0,0 +1,191 @@ +package com.dharashah.showcaseandroidapp.activity; + +import android.content.Intent; +import android.os.Bundle; +import android.support.v4.app.FragmentTransaction; +import android.support.v7.widget.Toolbar; +import android.view.View; +import android.widget.Button; +import android.widget.TextView; +import android.widget.Toast; + +import com.dharashah.showcaseandroidapp.R; +import com.dharashah.showcaseandroidapp.ShowCaseApp; +import com.dharashah.showcaseandroidapp.callback.ILoadListener; +import com.dharashah.showcaseandroidapp.db.DBHelper; +import com.dharashah.showcaseandroidapp.fragment.AndroidHistoryFragment; +import com.dharashah.showcaseandroidapp.fragment.DeviceFragment; +import com.dharashah.showcaseandroidapp.model.AllData; +import com.dharashah.showcaseandroidapp.network.RestClient; +import com.getbase.floatingactionbutton.FloatingActionButton; +import com.getbase.floatingactionbutton.FloatingActionsMenu; + +import retrofit.Call; +import retrofit.Callback; +import retrofit.Response; +import retrofit.Retrofit; + + +public class MainActivity extends BaseActivity implements View.OnClickListener, Callback{ + private Button mBtnDevices; + private Button mBtnHistory; + private AndroidHistoryFragment mHistoryFragment; + private DBHelper mDBHelper; + private DeviceFragment mDeviceFragment; + private Callback mCallback; + private FloatingActionButton fabAddDevice; + private FloatingActionButton fabAddVersion; + private FloatingActionsMenu fabMenu; + private ILoadListener mLoadListener; + private Toolbar mToolbar; + private TextView mTxtTitle; + + public void setLoadListener(ILoadListener loadListener) { + this.mLoadListener = loadListener; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + initToolbar(); + initView(); + initFragment(); + initServiceCalls(); + } + + private void initToolbar() { + mTxtTitle = (TextView)findViewById(R.id.txtTitle); + mToolbar=(Toolbar)findViewById(R.id.toolbar); + mTxtTitle.setText("Dashboard"); + setSupportActionBar(mToolbar); + } + + private void initView() { + mCallback = this; + mBtnHistory = (Button)findViewById(R.id.btnAndroidVersions); + mBtnDevices = (Button)findViewById(R.id.btnAndroidDevices); + fabAddDevice = (FloatingActionButton)findViewById(R.id.fabAndroidDevice); + fabAddVersion = (FloatingActionButton)findViewById(R.id.fabAndroidHistory); + fabMenu =(FloatingActionsMenu)findViewById(R.id.fabMenu); + + mBtnDevices.setOnClickListener(this); + mBtnHistory.setOnClickListener(this); + fabAddVersion.setOnClickListener(this); + fabAddDevice.setOnClickListener(this); + + mDBHelper = DBHelper.getInstance(ShowCaseApp.getAppContext()); + + } + + @Override + public void onClick(View v) { + FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); + switch (v.getId()) { + case R.id.btnAndroidDevices: + if(mHistoryFragment != null) { + mHistoryFragment.onPause(); + } + + if(mDeviceFragment == null) { + mDeviceFragment = DeviceFragment.newInstance(); + } + + ft.replace(R.id.content_frame, mDeviceFragment); + break; + + case R.id.btnAndroidVersions: + if(mDeviceFragment != null) { + mDeviceFragment.onPause(); + } + + if(mHistoryFragment == null) { + mHistoryFragment = AndroidHistoryFragment.newInstance(); + } + + ft.replace(R.id.content_frame, mHistoryFragment); + break; + + case R.id.fabAndroidDevice: + fabMenu.collapse(); + Intent intent = new Intent(ShowCaseApp.getAppContext(), AddDeviceActivity.class); + startActivity(intent); + overridePendingTransition(R.anim.slide_in_up, R.anim.slide_out_up); + break; + + case R.id.fabAndroidHistory: + fabMenu.collapse(); + intent = new Intent(ShowCaseApp.getAppContext(), AddVersionActivity.class); + startActivity(intent); + overridePendingTransition(R.anim.slide_in_up, R.anim.slide_out_up); + break; + } + ft.commit(); + } + + private void initFragment() { + FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); + mDeviceFragment = DeviceFragment.newInstance(); + ft.replace(R.id.content_frame, mDeviceFragment); + ft.commit(); + } + + private void initServiceCalls() { + boolean hasData = mDBHelper.hasData(); + + // we have data here + if(hasData) { + if(mLoadListener != null) { + // do not do anything + // load the data into the fragment first selected + mLoadListener.onLoadData(); + } + }else { + if(RestClient.isNetworkAvailable()) { + Call call = new RestClient().getApiService().getAllData(); + call.enqueue(mCallback); + }else { + Toast.makeText(ShowCaseApp.getAppContext(), + ShowCaseApp.getAppContext().getResources().getString(R.string.no_internet),Toast.LENGTH_LONG).show(); + } + } + } + + @Override + public void onResponse(Response response, Retrofit retrofit) { + if(response.body() != null) { + addDataToDatabase(response.body()); + } + + if(mLoadListener != null) { + mLoadListener.onRefreshData(response.body()); + } + } + + @Override + public void onFailure(Throwable t) { + + } + + /** + * Start threads to add data to the database + * @param response + */ + private void addDataToDatabase(final AllData response) { + new Thread(new Runnable() { + @Override + public void run() { + mDBHelper.addDevices(response.getDeviceList()); + mLoadListener.onLoadData(); + } + }).start(); + + new Thread(new Runnable() { + @Override + public void run() { + mDBHelper.addVersions(response.getAndroidHistoryList()); + mLoadListener.onLoadData(); + } + }).start(); + } +} diff --git a/app/src/main/java/com/dharashah/showcaseandroidapp/adapter/AndroidVersionsAdapter.java b/app/src/main/java/com/dharashah/showcaseandroidapp/adapter/AndroidVersionsAdapter.java new file mode 100644 index 0000000..8fba059 --- /dev/null +++ b/app/src/main/java/com/dharashah/showcaseandroidapp/adapter/AndroidVersionsAdapter.java @@ -0,0 +1,68 @@ +package com.dharashah.showcaseandroidapp.adapter; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.TextView; + +import com.dharashah.showcaseandroidapp.R; +import com.dharashah.showcaseandroidapp.model.AndroidHistory; + +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +/** + * Created by Dhara Shah on 22/01/2016. + */ +public class AndroidVersionsAdapter extends ArrayAdapter { + private Context mContext; + private List mList; + private int RESOURCE; + + public AndroidVersionsAdapter(Context context, int resource, List objects) { + super(context, resource, objects); + mContext = context; + mList = objects; + RESOURCE = resource; + + Collections.sort(mList, new Comparator() { + @Override + public int compare(AndroidHistory lhs, AndroidHistory rhs) { + if (rhs.getAndroidId() > lhs.getAndroidId()) { + return 1; + } else { + return -1; + } + } + }); + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + View view = convertView; + ViewHolder vh = null; + if(view == null) { + view = LayoutInflater.from(mContext).inflate(RESOURCE, parent,false); + vh = new ViewHolder(); + vh.txtAndroidVersion = (TextView)view.findViewById(R.id.txtAndroidVersion); + vh.txtAndroidVersionName = (TextView)view.findViewById(R.id.txtAndroidVersionName); + view.setTag(vh); + }else { + vh = (ViewHolder)view.getTag(); + } + + AndroidHistory history = mList.get(position); + vh.txtAndroidVersion.setText(history.getVersion()); + vh.txtAndroidVersionName.setText(history.getName()); + + return view; + } + + class ViewHolder { + TextView txtAndroidVersionName; + TextView txtAndroidVersion; + } +} diff --git a/app/src/main/java/com/dharashah/showcaseandroidapp/adapter/DeviceAdapter.java b/app/src/main/java/com/dharashah/showcaseandroidapp/adapter/DeviceAdapter.java new file mode 100644 index 0000000..832b62c --- /dev/null +++ b/app/src/main/java/com/dharashah/showcaseandroidapp/adapter/DeviceAdapter.java @@ -0,0 +1,97 @@ +package com.dharashah.showcaseandroidapp.adapter; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import com.daimajia.swipe.SwipeLayout; +import com.daimajia.swipe.adapters.BaseSwipeAdapter; +import com.dharashah.showcaseandroidapp.R; +import com.dharashah.showcaseandroidapp.callback.IDataFunctionListener; +import com.dharashah.showcaseandroidapp.model.Devices; + +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +/** + * Created by USER on 22-01-2016. + */ +public class DeviceAdapter extends BaseSwipeAdapter { + private Context mContext; + private List mDeviceList; + private IDataFunctionListener mListener; + + public DeviceAdapter(Context context, List objects, IDataFunctionListener listener) { + mContext = context; + mDeviceList = objects; + mListener = listener; + + Collections.sort(mDeviceList, new Comparator() { + @Override + public int compare(Devices lhs, Devices rhs) { + if(lhs.getDeviceId() > rhs.getDeviceId()) { + return 1; + }else { + return -1; + } + } + }); + } + + @Override + public int getItemViewType(int position) { + return super.getItemViewType(position); + } + + @Override + public int getSwipeLayoutResourceId(int position) { + return R.id.swipe; + } + + @Override + public View generateView(int position, ViewGroup parent) { + return LayoutInflater.from(mContext).inflate(R.layout.individual_swipe_row, parent, false); + } + + @Override + public void fillValues(final int position, View convertView) { + final DeviceViewHolder viewHolder = new DeviceViewHolder(convertView); + viewHolder.txtDeviceName.setText(mDeviceList.get(position).getDeviceName()); + viewHolder.txtDeviceDesc.setText(mDeviceList.get(position).getDeviceDesc()); + viewHolder.swipeLayout.setShowMode(SwipeLayout.ShowMode.PullOut); + viewHolder.swipeLayout.addDrag(SwipeLayout.DragEdge.Right, viewHolder.swipeLayout.findViewById(R.id.bottom_wrapper)); + viewHolder.swipeLayout.getSurfaceView().setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + // show the details + mListener.onDisplaySelected(mDeviceList.get(position)); + } + }); + viewHolder.relDelete.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if(mListener != null) mListener.onDeleteSelected(mDeviceList.get(position).getDeviceId()); + mDeviceList.remove(position); + viewHolder.swipeLayout.close(true); + notifyDataSetChanged(); + } + }); + } + + @Override + public int getCount() { + return mDeviceList.size(); + } + + @Override + public Object getItem(int position) { + return mDeviceList.get(position); + } + + @Override + public long getItemId(int position) { + return position; + } +} diff --git a/app/src/main/java/com/dharashah/showcaseandroidapp/adapter/DeviceViewHolder.java b/app/src/main/java/com/dharashah/showcaseandroidapp/adapter/DeviceViewHolder.java new file mode 100644 index 0000000..2112ad0 --- /dev/null +++ b/app/src/main/java/com/dharashah/showcaseandroidapp/adapter/DeviceViewHolder.java @@ -0,0 +1,41 @@ +package com.dharashah.showcaseandroidapp.adapter; + +import android.view.View; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.daimajia.swipe.SwipeLayout; +import com.dharashah.showcaseandroidapp.R; + +/** + * Created by user on 23/01/2016. + */ +public class DeviceViewHolder { + public TextView txtDeviceName; + public TextView txtDeviceDesc; + public SwipeLayout swipeLayout; + public RelativeLayout relDelete; + + public DeviceViewHolder(View view) { + swipeLayout = (SwipeLayout) view.findViewById(R.id.swipe); + txtDeviceName = (TextView)view.findViewById(R.id.txtDeviceName); + txtDeviceDesc = (TextView)view.findViewById(R.id.txtDeviceDesc); + relDelete = (RelativeLayout)view.findViewById(R.id.relDelete); + } + + public TextView getTxtDeviceName() { + return txtDeviceName; + } + + public void setTxtDeviceName(TextView txtDeviceName) { + this.txtDeviceName = txtDeviceName; + } + + public TextView getTxtDeviceDesc() { + return txtDeviceDesc; + } + + public void setTxtDeviceDesc(TextView txtDeviceDesc) { + this.txtDeviceDesc = txtDeviceDesc; + } +} diff --git a/app/src/main/java/com/dharashah/showcaseandroidapp/adapter/VersionsAdapter.java b/app/src/main/java/com/dharashah/showcaseandroidapp/adapter/VersionsAdapter.java new file mode 100644 index 0000000..d620bb1 --- /dev/null +++ b/app/src/main/java/com/dharashah/showcaseandroidapp/adapter/VersionsAdapter.java @@ -0,0 +1,91 @@ +package com.dharashah.showcaseandroidapp.adapter; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import com.daimajia.swipe.SwipeLayout; +import com.daimajia.swipe.adapters.BaseSwipeAdapter; +import com.dharashah.showcaseandroidapp.R; +import com.dharashah.showcaseandroidapp.callback.IDataFunctionListener; +import com.dharashah.showcaseandroidapp.model.AndroidHistory; + +import java.util.Collections; +import java.util.Comparator; +import java.util.LinkedList; + +/** + * Created by user on 23/01/2016. + */ +public class VersionsAdapter extends BaseSwipeAdapter { + private LinkedList mHistoryList; + private Context mContext; + private IDataFunctionListener mListener; + + public VersionsAdapter(Context context, LinkedList list, IDataFunctionListener listener) { + mContext = context; + mHistoryList = list; + mListener = listener; + + Collections.sort(mHistoryList, new Comparator() { + @Override + public int compare(AndroidHistory lhs, AndroidHistory rhs) { + if(lhs.getAndroidId() > rhs.getAndroidId()) { + return 1; + }else { + return -1; + } + } + }); + } + + @Override + public int getSwipeLayoutResourceId(int position) { + return R.id.swipe; + } + + @Override + public View generateView(int position, ViewGroup parent) { + return LayoutInflater.from(mContext).inflate(R.layout.individual_swipe_versions, parent, false); + } + + @Override + public void fillValues(final int position, View convertView) { + final VersionsViewHolder viewHolder = new VersionsViewHolder(convertView); + viewHolder.txtAndroidName.setText(mHistoryList.get(position).getName()); + viewHolder.txtAndroidVersionNumber.setText(mHistoryList.get(position).getVersion()); + viewHolder.swipeLayout.setShowMode(SwipeLayout.ShowMode.PullOut); + viewHolder.swipeLayout.addDrag(SwipeLayout.DragEdge.Right, viewHolder.swipeLayout.findViewById(R.id.bottom_wrapper)); + viewHolder.swipeLayout.getSurfaceView().setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + // show the details or lead to another fragment + } + }); + viewHolder.relDelete.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + mListener.onDeleteSelected(mHistoryList.get(position).getAndroidId()); + mHistoryList.remove(position); + viewHolder.swipeLayout.close(true); + notifyDataSetChanged(); + } + }); + } + + @Override + public int getCount() { + return mHistoryList.size(); + } + + @Override + public Object getItem(int position) { + return mHistoryList.get(position); + } + + @Override + public long getItemId(int position) { + return position; + } +} diff --git a/app/src/main/java/com/dharashah/showcaseandroidapp/adapter/VersionsViewHolder.java b/app/src/main/java/com/dharashah/showcaseandroidapp/adapter/VersionsViewHolder.java new file mode 100644 index 0000000..e006f89 --- /dev/null +++ b/app/src/main/java/com/dharashah/showcaseandroidapp/adapter/VersionsViewHolder.java @@ -0,0 +1,25 @@ +package com.dharashah.showcaseandroidapp.adapter; + +import android.view.View; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.daimajia.swipe.SwipeLayout; +import com.dharashah.showcaseandroidapp.R; + +/** + * Created by user on 23/01/2016. + */ +public class VersionsViewHolder { + public TextView txtAndroidVersionNumber; + public TextView txtAndroidName; + public SwipeLayout swipeLayout; + public RelativeLayout relDelete; + + public VersionsViewHolder(View view) { + swipeLayout = (SwipeLayout) view.findViewById(R.id.swipe); + txtAndroidName = (TextView)view.findViewById(R.id.txtAndroidVersionName); + txtAndroidVersionNumber = (TextView)view.findViewById(R.id.txtAndroidVersion); + relDelete = (RelativeLayout)view.findViewById(R.id.relDelete); + } +} diff --git a/app/src/main/java/com/dharashah/showcaseandroidapp/callback/IDataFunctionListener.java b/app/src/main/java/com/dharashah/showcaseandroidapp/callback/IDataFunctionListener.java new file mode 100644 index 0000000..59d3e85 --- /dev/null +++ b/app/src/main/java/com/dharashah/showcaseandroidapp/callback/IDataFunctionListener.java @@ -0,0 +1,9 @@ +package com.dharashah.showcaseandroidapp.callback; + +/** + * Created by user on 23/01/2016. + */ +public interface IDataFunctionListener { + void onDeleteSelected(int id); + void onDisplaySelected(Object object); +} diff --git a/app/src/main/java/com/dharashah/showcaseandroidapp/callback/ILoadListener.java b/app/src/main/java/com/dharashah/showcaseandroidapp/callback/ILoadListener.java new file mode 100644 index 0000000..14d8fa4 --- /dev/null +++ b/app/src/main/java/com/dharashah/showcaseandroidapp/callback/ILoadListener.java @@ -0,0 +1,11 @@ +package com.dharashah.showcaseandroidapp.callback; + +import com.dharashah.showcaseandroidapp.model.AllData; + +/** + * Created by user on 23/01/2016. + */ +public interface ILoadListener { + void onLoadData(); + void onRefreshData(AllData data); +} diff --git a/app/src/main/java/com/dharashah/showcaseandroidapp/db/AndroidVersionContract.java b/app/src/main/java/com/dharashah/showcaseandroidapp/db/AndroidVersionContract.java new file mode 100644 index 0000000..6508c33 --- /dev/null +++ b/app/src/main/java/com/dharashah/showcaseandroidapp/db/AndroidVersionContract.java @@ -0,0 +1,19 @@ +package com.dharashah.showcaseandroidapp.db; + +import android.provider.BaseColumns; + +/** + * Created by user on 21/01/2016. + */ +public final class AndroidVersionContract { + public AndroidVersionContract(){} + + public static abstract class AndroidVersionEntry implements BaseColumns { + public static final String TABLE_NAME = "android_history_master"; + public static final String COLUMN_NAME_ANDROID_ID = "android_id"; + public static final String COLUMN_NAME_ANDROID_NAME = "android_name"; + public static final String COLUMN_NAME_ANDROID_CODE_NAME = "android_code_name"; + public static final String COLUMN_NAME_ANDROID_TARGET = "android_target"; + public static final String COLUMN_NAME_ANDROID_DISTRIBUTION = "android_distribution"; + } +} diff --git a/app/src/main/java/com/dharashah/showcaseandroidapp/db/DBHelper.java b/app/src/main/java/com/dharashah/showcaseandroidapp/db/DBHelper.java new file mode 100644 index 0000000..cf3ec4d --- /dev/null +++ b/app/src/main/java/com/dharashah/showcaseandroidapp/db/DBHelper.java @@ -0,0 +1,282 @@ +package com.dharashah.showcaseandroidapp.db; + +import android.content.ContentValues; +import android.content.Context; +import android.database.Cursor; +import android.database.DatabaseUtils; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteOpenHelper; + +import com.dharashah.showcaseandroidapp.model.AndroidHistory; +import com.dharashah.showcaseandroidapp.model.Devices; + +import java.util.LinkedList; +import java.util.List; +import java.util.Stack; + +/** + * Created by Dhara Shah on 21/01/2016. + */ +public class DBHelper extends SQLiteOpenHelper { + private static DBHelper mDbHelper; + private static final String DATABASE_NAME = "ShowCaseApp.db"; + private static final int DATABASE_VERSION = 1; + + private static final String TEXT_TYPE = " TEXT"; + private static final String INTEGER_TYPE = " INTEGER "; + private static final String INTEGER_PRIMARY_KEY = " INTEGER PRIMARY KEY "; + private static final String FLOAT_TYPE=" FLOAT "; + private static final String COMMA_SEP = ","; + + private static final String CREATE_HISTORY_TABLE = + "CREATE TABLE " + AndroidVersionContract.AndroidVersionEntry.TABLE_NAME + + "( " + AndroidVersionContract.AndroidVersionEntry._ID + INTEGER_PRIMARY_KEY + + COMMA_SEP + AndroidVersionContract.AndroidVersionEntry.COLUMN_NAME_ANDROID_ID + INTEGER_TYPE + + COMMA_SEP + AndroidVersionContract.AndroidVersionEntry.COLUMN_NAME_ANDROID_NAME + TEXT_TYPE + + COMMA_SEP + AndroidVersionContract.AndroidVersionEntry.COLUMN_NAME_ANDROID_DISTRIBUTION + TEXT_TYPE + + COMMA_SEP + AndroidVersionContract.AndroidVersionEntry.COLUMN_NAME_ANDROID_CODE_NAME + TEXT_TYPE + + COMMA_SEP + AndroidVersionContract.AndroidVersionEntry.COLUMN_NAME_ANDROID_TARGET + TEXT_TYPE + ")"; + + private static final String CREATE_DEVICE_TABLE = + "CREATE TABLE " + DeviceContract.DeviceEntry.TABLE_NAME + + " ( " + DeviceContract.DeviceEntry._ID + INTEGER_PRIMARY_KEY + + COMMA_SEP + DeviceContract.DeviceEntry.COLUMN_NAME_DEVICE_ID + INTEGER_TYPE + + COMMA_SEP + DeviceContract.DeviceEntry.COLUMN_NAME_ANDROID_ID + INTEGER_TYPE + + COMMA_SEP + DeviceContract.DeviceEntry.COLUMN_NAME_DEVICE_NAME + TEXT_TYPE + + COMMA_SEP + DeviceContract.DeviceEntry.COLUMN_NAME_DEVICE_DESC + TEXT_TYPE + + COMMA_SEP + DeviceContract.DeviceEntry.COLUMN_NAME_DEVICE_IMAGE + TEXT_TYPE + ")"; + + /** + * Creates a singleton instance + * @param context + * @return + */ + public static DBHelper getInstance(Context context) { + if(mDbHelper == null) { + mDbHelper = new DBHelper(context); + } + return mDbHelper; + } + + public DBHelper(Context context) { + super(context, DATABASE_NAME, null, DATABASE_VERSION); + } + + @Override + public void onCreate(SQLiteDatabase sqLiteDatabase) { + sqLiteDatabase.execSQL(CREATE_HISTORY_TABLE); + sqLiteDatabase.execSQL(CREATE_DEVICE_TABLE); + } + + @Override + public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) { + + } + + /** + * Inserts a new device to the database + * @param device + * @return + */ + public long insertNewDevice(Devices device){ + SQLiteDatabase db = this.getWritableDatabase(); + ContentValues values = new ContentValues(); + values.put(DeviceContract.DeviceEntry.COLUMN_NAME_DEVICE_ID, device.getDeviceId()); + values.put(DeviceContract.DeviceEntry.COLUMN_NAME_ANDROID_ID, device.getAndroidId()); + values.put(DeviceContract.DeviceEntry.COLUMN_NAME_DEVICE_NAME, device.getDeviceName()); + values.put(DeviceContract.DeviceEntry.COLUMN_NAME_DEVICE_DESC, device.getDeviceDesc()); + values.put(DeviceContract.DeviceEntry.COLUMN_NAME_DEVICE_IMAGE, device.getImageURL()); + long id = db.insert(DeviceContract.DeviceEntry.TABLE_NAME,null,values ); + return id; + } + + /** + * Inserts a new Android Version to the database + * @param androidHistory + * @return + */ + public long insertAndroidVersion(AndroidHistory androidHistory){ + SQLiteDatabase db = this.getWritableDatabase(); + ContentValues values = new ContentValues(); + values.put(AndroidVersionContract.AndroidVersionEntry.COLUMN_NAME_ANDROID_ID, androidHistory.getAndroidId()); + values.put(AndroidVersionContract.AndroidVersionEntry.COLUMN_NAME_ANDROID_CODE_NAME, androidHistory.getCodeName()); + values.put(AndroidVersionContract.AndroidVersionEntry.COLUMN_NAME_ANDROID_DISTRIBUTION, androidHistory.getDistribution()); + values.put(AndroidVersionContract.AndroidVersionEntry.COLUMN_NAME_ANDROID_NAME, androidHistory.getName()); + values.put(AndroidVersionContract.AndroidVersionEntry.COLUMN_NAME_ANDROID_TARGET, androidHistory.getTarget()); + long id= db.insert(AndroidVersionContract.AndroidVersionEntry.TABLE_NAME, null, values); + return id; + } + + /** + * Gets the list of android versions + * @param sortOrder + * @return + */ + public LinkedList getAndroidVersions(String sortOrder) { + LinkedList androidHistoryList = new LinkedList<>(); + SQLiteDatabase db = this.getReadableDatabase(); + Cursor c = null; + + try { + c = db.query(AndroidVersionContract.AndroidVersionEntry.TABLE_NAME, + null, + null, + null, + null, + null, + AndroidVersionContract.AndroidVersionEntry.COLUMN_NAME_ANDROID_ID + sortOrder); + + if(c != null && c.moveToFirst()) { + do { + AndroidHistory history = new AndroidHistory(); + history.setAndroidId(c.getInt(c.getColumnIndex(AndroidVersionContract.AndroidVersionEntry.COLUMN_NAME_ANDROID_ID))); + history.setName(c.getString(c.getColumnIndex(AndroidVersionContract.AndroidVersionEntry.COLUMN_NAME_ANDROID_NAME))); + history.setCodeName(c.getString + (c.getColumnIndex(AndroidVersionContract.AndroidVersionEntry.COLUMN_NAME_ANDROID_CODE_NAME))); + history.setDistribution(c.getString + (c.getColumnIndex(AndroidVersionContract.AndroidVersionEntry.COLUMN_NAME_ANDROID_DISTRIBUTION))); + history.setTarget(c.getString + (c.getColumnIndex(AndroidVersionContract.AndroidVersionEntry.COLUMN_NAME_ANDROID_TARGET))); + androidHistoryList.add(history); + }while(c.moveToNext()); + } + }finally { + if(c != null) { + c.close(); + } + } + return androidHistoryList; + } + + /** + * Gets the list of devices + * @return + */ + public LinkedList getDevices(){ + LinkedList deviceList = new LinkedList<>(); + SQLiteDatabase db = this.getReadableDatabase(); + Cursor c = null; + + try { + c = db.query(DeviceContract.DeviceEntry.TABLE_NAME, + null, + null, + null, + null, + null, + DeviceContract.DeviceEntry.COLUMN_NAME_DEVICE_ID + " DESC "); + + if(c != null && c.moveToFirst()) { + do { + Devices device = new Devices(); + device.setAndroidId(c.getInt(c.getColumnIndex(DeviceContract.DeviceEntry.COLUMN_NAME_ANDROID_ID))); + device.setDeviceDesc(c.getString(c.getColumnIndex(DeviceContract.DeviceEntry.COLUMN_NAME_DEVICE_DESC))); + device.setDeviceId(c.getInt(c.getColumnIndex(DeviceContract.DeviceEntry.COLUMN_NAME_DEVICE_ID))); + device.setDeviceName(c.getString(c.getColumnIndex(DeviceContract.DeviceEntry.COLUMN_NAME_DEVICE_NAME))); + device.setImageURL(c.getString(c.getColumnIndex(DeviceContract.DeviceEntry.COLUMN_NAME_DEVICE_IMAGE))); + deviceList.add(device); + }while(c.moveToNext()); + } + }finally { + if(c != null) { + c.close(); + } + } + return deviceList; + } + + /** + * Checks if there is data in the database + * @return + */ + public boolean hasData() { + SQLiteDatabase db = this.getReadableDatabase(); + long countOfDevices = DatabaseUtils.queryNumEntries(db, DeviceContract.DeviceEntry.TABLE_NAME); + long countOfVersions = DatabaseUtils.queryNumEntries(db, AndroidVersionContract.AndroidVersionEntry.TABLE_NAME); + + if(countOfDevices <= 0 && countOfVersions <= 0) { + return false; + }else { + return true; + } + } + + /** + * Adds a new device to the database + * @param deviceList + */ + public void addDevices(List deviceList) { + Stack stack = new Stack<>(); + stack.addAll(deviceList); + + while(!stack.isEmpty()) { + insertNewDevice(stack.pop()); + } + } + + /** + * Adds an android version to the database + * @param versionList + */ + public void addVersions(List versionList){ + Stack stack = new Stack<>(); + stack.addAll(versionList); + + while(!stack.isEmpty()) { + insertAndroidVersion(stack.pop()); + } + } + + /** + * Gets the android version name to display + * @param androidId + * @return + */ + public String getVersionName(int androidId) { + SQLiteDatabase db =this.getReadableDatabase(); + Cursor c = null; + String androidName = ""; + + try { + c = db.query(AndroidVersionContract.AndroidVersionEntry.TABLE_NAME, + new String[]{AndroidVersionContract.AndroidVersionEntry.COLUMN_NAME_ANDROID_NAME}, + AndroidVersionContract.AndroidVersionEntry.COLUMN_NAME_ANDROID_ID + " =?", + new String[]{String.valueOf(androidId)}, + null, + null, + null); + + if(c != null && c.moveToFirst()) { + androidName = c.getString(c.getColumnIndex(AndroidVersionContract.AndroidVersionEntry.COLUMN_NAME_ANDROID_NAME)); + } + }finally { + if(c != null) { + c.close(); + } + } + + return androidName; + } + + /** + * Delete the device from the database + * @param deviceId + */ + public void deleteDevice(int deviceId) { + SQLiteDatabase db = this.getWritableDatabase(); + db.delete(DeviceContract.DeviceEntry.TABLE_NAME, + DeviceContract.DeviceEntry.COLUMN_NAME_DEVICE_ID + "=?", + new String[]{String.valueOf(deviceId)}); + } + + /** + * Delete the android version from the database + * @param androidId + */ + public void deleteAndroidVersion(int androidId) { + SQLiteDatabase db = this.getWritableDatabase(); + db.delete(AndroidVersionContract.AndroidVersionEntry.TABLE_NAME, + AndroidVersionContract.AndroidVersionEntry.COLUMN_NAME_ANDROID_ID + "=?", + new String[]{String.valueOf(androidId)}); + } +} diff --git a/app/src/main/java/com/dharashah/showcaseandroidapp/db/DeviceContract.java b/app/src/main/java/com/dharashah/showcaseandroidapp/db/DeviceContract.java new file mode 100644 index 0000000..2494417 --- /dev/null +++ b/app/src/main/java/com/dharashah/showcaseandroidapp/db/DeviceContract.java @@ -0,0 +1,20 @@ +package com.dharashah.showcaseandroidapp.db; + +import android.provider.BaseColumns; + +/** + * Created by user on 21/01/2016. + */ +public final class DeviceContract { + public DeviceContract(){} + + public static abstract class DeviceEntry implements BaseColumns { + public static final String TABLE_NAME = "device_master"; + public static final String COLUMN_NAME_DEVICE_ID = "device_id"; + public static final String COLUMN_NAME_DEVICE_NAME = "device_name"; + public static final String COLUMN_NAME_DEVICE_DESC = "device_desc"; + public static final String COLUMN_NAME_DEVICE_IMAGE = "device_image"; + public static final String COLUMN_NAME_ANDROID_ID = "android_id"; + } + +} diff --git a/app/src/main/java/com/dharashah/showcaseandroidapp/fragment/AndroidHistoryFragment.java b/app/src/main/java/com/dharashah/showcaseandroidapp/fragment/AndroidHistoryFragment.java new file mode 100644 index 0000000..1b6c4de --- /dev/null +++ b/app/src/main/java/com/dharashah/showcaseandroidapp/fragment/AndroidHistoryFragment.java @@ -0,0 +1,167 @@ +package com.dharashah.showcaseandroidapp.fragment; + +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.support.v4.widget.SwipeRefreshLayout; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ListView; + +import com.dharashah.showcaseandroidapp.R; +import com.dharashah.showcaseandroidapp.ShowCaseApp; +import com.dharashah.showcaseandroidapp.activity.MainActivity; +import com.dharashah.showcaseandroidapp.adapter.VersionsAdapter; +import com.dharashah.showcaseandroidapp.callback.IDataFunctionListener; +import com.dharashah.showcaseandroidapp.callback.ILoadListener; +import com.dharashah.showcaseandroidapp.db.DBHelper; +import com.dharashah.showcaseandroidapp.model.AllData; +import com.dharashah.showcaseandroidapp.model.AndroidHistory; +import com.dharashah.showcaseandroidapp.network.RestClient; + +import java.util.LinkedList; +import java.util.List; + +import retrofit.Call; +import retrofit.Callback; +import retrofit.Response; +import retrofit.Retrofit; + +/** + * Created by Dhara Shah on 22/01/2016. + */ +public class AndroidHistoryFragment extends Fragment implements ILoadListener, + SwipeRefreshLayout.OnRefreshListener, Callback>, IDataFunctionListener { + private static AndroidHistoryFragment mFragment; + private View mView; + private ListView mListView; + private ILoadListener mListener; + private DBHelper mDbHelper; + private LinkedList mAndroidHistoryList; + private SwipeRefreshLayout mRefreshLayout; + private Callback> mCallback; + private VersionsAdapter mAdapter; + private IDataFunctionListener mDeleteListener; + + public static AndroidHistoryFragment newInstance() { + mFragment = new AndroidHistoryFragment(); + return mFragment; + } + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + mView = inflater.inflate(R.layout.fragment_history, container, false); + initView(); + return mView; + } + + private void initView() { + mDeleteListener = this; + mCallback = this; + mListener = this; + mDbHelper = DBHelper.getInstance(ShowCaseApp.getAppContext()); + mListView = (ListView)mView.findViewById(android.R.id.list); + mRefreshLayout = (SwipeRefreshLayout)mView.findViewById(R.id.swipeRefreshLayout); + mRefreshLayout.setOnRefreshListener(this); + mAndroidHistoryList = new LinkedList<>(); + ((MainActivity)getActivity()).setLoadListener(mListener); + mAdapter = new VersionsAdapter(ShowCaseApp.getAppContext(), mAndroidHistoryList, mDeleteListener); + mListView.setAdapter(mAdapter); + onLoadData(); + } + + @Override + public void onLoadData() { + // get data from the database and load here + LinkedList histories = mDbHelper.getAndroidVersions(" DESC "); + mAndroidHistoryList.clear(); + mAndroidHistoryList.addAll(histories); + + getActivity().runOnUiThread(new Runnable() { + @Override + public void run() { + if(mAdapter != null) { + mAdapter.notifyDataSetChanged(); + } + } + }); + + } + + @Override + public void onRefreshData(AllData data) { + List historyList = data.getAndroidHistoryList(); + mAndroidHistoryList.clear(); + mAndroidHistoryList.addAll(historyList); + + if(mAdapter != null) { + mAdapter.notifyDataSetChanged(); + } + } + + @Override + public void onRefresh() { + int startCounter = (mAndroidHistoryList == null) ? 0 : mAndroidHistoryList.size(); + int endCounter = startCounter + 10; + + if(RestClient.isNetworkAvailable()) { + Call> call = + new RestClient().getApiService().getAndroidVersions(startCounter, endCounter); + call.enqueue(mCallback); + }else { + mRefreshLayout.setRefreshing(false); + } + } + + @Override + public void onResponse(final Response> response, Retrofit retrofit) { + if(response.body() != null) { + LinkedList historyList = new LinkedList<>(); + historyList.addAll(response.body()); + historyList.addAll(mAndroidHistoryList); + mAndroidHistoryList.clear(); + mAndroidHistoryList.addAll(historyList); + if(mAdapter != null) { + mAdapter.notifyDataSetChanged(); + } + + new Thread(new Runnable() { + @Override + public void run() { + mDbHelper.addVersions(response.body()); + } + }).start(); + } + mRefreshLayout.setRefreshing(false); + } + + @Override + public void onFailure(Throwable t) { + mRefreshLayout.setRefreshing(false); + } + + @Override + public void onDeleteSelected(int id) { + mDbHelper.deleteAndroidVersion(id); + + Call deleteCall = new RestClient().getApiService().deleteVersion(id); + deleteCall.enqueue(new Callback() { + @Override + public void onResponse(Response response, Retrofit retrofit) { + + } + + @Override + public void onFailure(Throwable t) { + + } + }); + } + + @Override + public void onDisplaySelected(Object object) { + + } +} diff --git a/app/src/main/java/com/dharashah/showcaseandroidapp/fragment/DeviceFragment.java b/app/src/main/java/com/dharashah/showcaseandroidapp/fragment/DeviceFragment.java new file mode 100644 index 0000000..72ed225 --- /dev/null +++ b/app/src/main/java/com/dharashah/showcaseandroidapp/fragment/DeviceFragment.java @@ -0,0 +1,202 @@ +package com.dharashah.showcaseandroidapp.fragment; + +import android.app.Dialog; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.support.v4.widget.SwipeRefreshLayout; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.widget.ImageView; +import android.widget.ListView; +import android.widget.TextView; + +import com.dharashah.showcaseandroidapp.R; +import com.dharashah.showcaseandroidapp.ShowCaseApp; +import com.dharashah.showcaseandroidapp.activity.MainActivity; +import com.dharashah.showcaseandroidapp.adapter.DeviceAdapter; +import com.dharashah.showcaseandroidapp.callback.IDataFunctionListener; +import com.dharashah.showcaseandroidapp.callback.ILoadListener; +import com.dharashah.showcaseandroidapp.db.DBHelper; +import com.dharashah.showcaseandroidapp.model.AllData; +import com.dharashah.showcaseandroidapp.model.Devices; +import com.dharashah.showcaseandroidapp.network.RestClient; + +import java.util.LinkedList; +import java.util.List; + +import retrofit.Call; +import retrofit.Callback; +import retrofit.Response; +import retrofit.Retrofit; + +/** + * Created by Dhara shah on 22/01/2016. + */ +public class DeviceFragment extends Fragment implements ILoadListener, SwipeRefreshLayout.OnRefreshListener, Callback>, IDataFunctionListener { + private static DeviceFragment mFragment; + private View mView; + private ListView mListView; + private DBHelper mDbHelper; + private ILoadListener mListener; + private LinkedList deviceList; + private SwipeRefreshLayout mRefreshLayout; + private Callback> mCallback; + private DeviceAdapter mAdapter; + private IDataFunctionListener mDeleteListener; + + public static DeviceFragment newInstance() { + mFragment = new DeviceFragment(); + return mFragment; + } + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + mView = inflater.inflate(R.layout.fragment_devices, container, false); + initView(); + return mView; + } + + private void initView() { + mListener = this; + mDeleteListener = this; + mDbHelper = DBHelper.getInstance(ShowCaseApp.getAppContext()); + mListView = (ListView)mView.findViewById(android.R.id.list); + mRefreshLayout = (SwipeRefreshLayout)mView.findViewById(R.id.swipeRefreshLayout); + mRefreshLayout.setOnRefreshListener(this); + deviceList = new LinkedList<>(); + ((MainActivity)getActivity()).setLoadListener(mListener); + mAdapter = new DeviceAdapter(ShowCaseApp.getAppContext(), deviceList, mDeleteListener); + mListView.setAdapter(mAdapter); + onLoadData(); + } + + @Override + public void onLoadData() { + // get data from the database and load here + LinkedList devices = mDbHelper.getDevices(); + deviceList.clear(); + deviceList.addAll(devices); + + getActivity().runOnUiThread(new Runnable() { + @Override + public void run() { + if(mAdapter != null) { + mAdapter.notifyDataSetChanged(); + } + } + }); + } + + @Override + public void onRefreshData(AllData data) { + List items = data.getDeviceList(); + deviceList.clear(); + deviceList.addAll(items); + + getActivity().runOnUiThread(new Runnable() { + @Override + public void run() { + if(mAdapter != null) { + mAdapter.notifyDataSetChanged(); + } + } + }); + } + + @Override + public void onRefresh() { + mCallback = this; + int startCounter = (deviceList == null) ? 0 : deviceList.size(); + int endCounter = startCounter + 10; + + if(RestClient.isNetworkAvailable()) { + Call> call = + new RestClient().getApiService().getDevices(startCounter, endCounter); + call.enqueue(mCallback); + }else { + mRefreshLayout.setRefreshing(false); + } + } + + @Override + public void onResponse(final Response> response, Retrofit retrofit) { + if(response.body() != null) { + LinkedList deviceListNew = new LinkedList<>(); + deviceListNew.addAll(response.body()); + deviceListNew.addAll(deviceList); + deviceList.clear(); + deviceList.addAll(deviceListNew); + + if(mAdapter != null) { + mAdapter.notifyDataSetChanged(); + } + + new Thread(new Runnable() { + @Override + public void run() { + mDbHelper.addDevices(response.body()); + } + }).start(); + } + + mRefreshLayout.setRefreshing(false); + } + + @Override + public void onFailure(Throwable t) { + mRefreshLayout.setRefreshing(false); + } + + @Override + public void onDeleteSelected(int id) { + mDbHelper.deleteDevice(id); + + // make a call to delete the record + Call deleteCall = new RestClient().getApiService().deleteDevice(id); + deleteCall.enqueue(new Callback() { + @Override + public void onResponse(Response response, Retrofit retrofit) { + + } + + @Override + public void onFailure(Throwable t) { + + } + }); + } + + @Override + public void onDisplaySelected(Object object) { + if(object instanceof Devices) { + final Dialog dialog = new Dialog(getActivity()); + dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); + dialog.setContentView(R.layout.pop_up_device_details); + TextView txtAndroidVersionName = (TextView)dialog.findViewById(R.id.txtAndroidVersion); + TextView txtDeviceName = (TextView)dialog.findViewById(R.id.txtDeviceName); + TextView txtDeviceDesc = (TextView)dialog.findViewById(R.id.txtDeviceDesc); + ImageView imgClose = (ImageView)dialog.findViewById(R.id.imgClose); + + Devices device = (Devices)object; + String androidVersionName = mDbHelper.getVersionName(device.getAndroidId()); + + txtAndroidVersionName.setText(androidVersionName); + txtDeviceDesc.setText(device.getDeviceDesc()); + txtDeviceName.setText(device.getDeviceName()); + + imgClose.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + dialog.dismiss(); + } + }); + + dialog.setCancelable(true); + dialog.show(); + } + } +} diff --git a/app/src/main/java/com/dharashah/showcaseandroidapp/manager/SessionManager.java b/app/src/main/java/com/dharashah/showcaseandroidapp/manager/SessionManager.java new file mode 100644 index 0000000..6f100ad --- /dev/null +++ b/app/src/main/java/com/dharashah/showcaseandroidapp/manager/SessionManager.java @@ -0,0 +1,7 @@ +package com.dharashah.showcaseandroidapp.manager; + +/** + * Created by user on 22/01/2016. + */ +public class SessionManager { +} diff --git a/app/src/main/java/com/dharashah/showcaseandroidapp/model/AllData.java b/app/src/main/java/com/dharashah/showcaseandroidapp/model/AllData.java new file mode 100644 index 0000000..c3d6589 --- /dev/null +++ b/app/src/main/java/com/dharashah/showcaseandroidapp/model/AllData.java @@ -0,0 +1,31 @@ +package com.dharashah.showcaseandroidapp.model; + +import com.google.gson.annotations.SerializedName; + +import java.util.List; + +/** + * Created by user on 23/01/2016. + */ +public class AllData { + @SerializedName("android") + private List androidHistoryList; + @SerializedName("devices") + private List deviceList; + + public List getAndroidHistoryList() { + return androidHistoryList; + } + + public void setAndroidHistoryList(List androidHistoryList) { + this.androidHistoryList = androidHistoryList; + } + + public List getDeviceList() { + return deviceList; + } + + public void setDeviceList(List deviceList) { + this.deviceList = deviceList; + } +} diff --git a/app/src/main/java/com/dharashah/showcaseandroidapp/model/AndroidHistory.java b/app/src/main/java/com/dharashah/showcaseandroidapp/model/AndroidHistory.java new file mode 100644 index 0000000..28d31c1 --- /dev/null +++ b/app/src/main/java/com/dharashah/showcaseandroidapp/model/AndroidHistory.java @@ -0,0 +1,69 @@ +package com.dharashah.showcaseandroidapp.model; + +import com.google.gson.annotations.SerializedName; + +/** + * Created by USER on 21-01-2016. + */ +public class AndroidHistory { + @SerializedName("id") + private int androidId; + @SerializedName("name") + private String name; + @SerializedName("version") + private String version; + @SerializedName("codename") + private String codeName; + @SerializedName("target") + private String target; + @SerializedName("distribution") + private String distribution; + + public int getAndroidId() { + return androidId; + } + + public void setAndroidId(int androidId) { + this.androidId = androidId; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public String getCodeName() { + return codeName; + } + + public void setCodeName(String codeName) { + this.codeName = codeName; + } + + public String getTarget() { + return target; + } + + public void setTarget(String target) { + this.target = target; + } + + public String getDistribution() { + return distribution; + } + + public void setDistribution(String distribution) { + this.distribution = distribution; + } +} diff --git a/app/src/main/java/com/dharashah/showcaseandroidapp/model/Devices.java b/app/src/main/java/com/dharashah/showcaseandroidapp/model/Devices.java new file mode 100644 index 0000000..498cb85 --- /dev/null +++ b/app/src/main/java/com/dharashah/showcaseandroidapp/model/Devices.java @@ -0,0 +1,59 @@ +package com.dharashah.showcaseandroidapp.model; + +import com.google.gson.annotations.SerializedName; + +/** + * Created by USER on 21-01-2016. + */ +public class Devices { + @SerializedName("id") + private int deviceId; + @SerializedName("androidId") + private int androidId; + @SerializedName("imageUrl") + private String imageURL; + @SerializedName("name") + private String deviceName; + @SerializedName("snippet") + private String deviceDesc; + + public int getDeviceId() { + return deviceId; + } + + public void setDeviceId(int deviceId) { + this.deviceId = deviceId; + } + + public int getAndroidId() { + return androidId; + } + + public void setAndroidId(int androidId) { + this.androidId = androidId; + } + + public String getImageURL() { + return imageURL; + } + + public void setImageURL(String imageURL) { + this.imageURL = imageURL; + } + + public String getDeviceName() { + return deviceName; + } + + public void setDeviceName(String deviceName) { + this.deviceName = deviceName; + } + + public String getDeviceDesc() { + return deviceDesc; + } + + public void setDeviceDesc(String deviceDesc) { + this.deviceDesc = deviceDesc; + } +} diff --git a/app/src/main/java/com/dharashah/showcaseandroidapp/network/ApiCalls.java b/app/src/main/java/com/dharashah/showcaseandroidapp/network/ApiCalls.java new file mode 100644 index 0000000..19648ce --- /dev/null +++ b/app/src/main/java/com/dharashah/showcaseandroidapp/network/ApiCalls.java @@ -0,0 +1,43 @@ +package com.dharashah.showcaseandroidapp.network; + +import android.content.Context; + +import com.android.volley.RequestQueue; +import com.android.volley.toolbox.Volley; + +/** + * Created by Dhara shah on 22/12/2015.
+ * SingleTon class that initializes the queue to + * load the images from the network
+ */ +public class ApiCalls { + private static ApiCalls mApiCall; + private static Context mContext; + + /** + * Instantiates ApiCalls instance + * @param context + * @return + */ + public static ApiCalls getInstance(Context context) { + mContext = context; + if(mApiCall == null) { + mApiCall = new ApiCalls(); + } + return mApiCall; + } + + private RequestQueue queue; + + /** + * Instantiates the queue + * @return + */ + public RequestQueue getRequestQueue() { + if(queue == null) { + queue = Volley.newRequestQueue(mContext.getApplicationContext()); + queue.start(); + } + return queue; + } +} diff --git a/app/src/main/java/com/dharashah/showcaseandroidapp/network/RestClient.java b/app/src/main/java/com/dharashah/showcaseandroidapp/network/RestClient.java new file mode 100644 index 0000000..2fa1348 --- /dev/null +++ b/app/src/main/java/com/dharashah/showcaseandroidapp/network/RestClient.java @@ -0,0 +1,85 @@ +package com.dharashah.showcaseandroidapp.network; + +import android.content.Context; +import android.net.ConnectivityManager; +import android.net.Network; +import android.net.NetworkInfo; +import android.os.Build; + +import com.dharashah.showcaseandroidapp.ShowCaseApp; +import com.dharashah.showcaseandroidapp.network.interfaces.ApiService; + +import retrofit.GsonConverterFactory; +import retrofit.Retrofit; + + +public class RestClient { + public static final String BASE_URL = "http://mobilesandboxdev.azurewebsites.net/"; + private ApiService mApiService; + + /** + * Initializes Retrofit and sets the base point of connection + */ + public RestClient() { + Retrofit retrofit = new Retrofit.Builder() + .baseUrl(BASE_URL) + .addConverterFactory(GsonConverterFactory.create()) + .build(); + mApiService = retrofit.create(ApiService.class); + } + + /** + * returns the instance of ApiService needed to make service calls + * @return + */ + public ApiService getApiService() { + return mApiService; + } + + /** + * Checks the availability of internet + * @return + */ + public static boolean isNetworkAvailable() { + boolean haveConnectedWifi = false; + boolean haveConnectedMobile = false; + + ConnectivityManager cm = + (ConnectivityManager) ShowCaseApp.getAppContext().getSystemService(Context.CONNECTIVITY_SERVICE); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + Network[] networks = cm.getAllNetworks(); + NetworkInfo networkInfo; + for (Network network : networks) { + networkInfo = cm.getNetworkInfo(network); + + if (networkInfo.getTypeName().equalsIgnoreCase("WIFI")) + if (networkInfo.isConnected()) + haveConnectedWifi = true; + if (networkInfo.getTypeName().equalsIgnoreCase("MOBILE")) + if (networkInfo.isConnected()) + haveConnectedMobile = true; + + if (networkInfo.getState().equals(NetworkInfo.State.CONNECTED)) { + return true; + } + } + }else { + //noinspection deprecation + NetworkInfo[] info = cm.getAllNetworkInfo(); + if (info != null) { + for (NetworkInfo anInfo : info) { + if (anInfo.getState() == NetworkInfo.State.CONNECTED) { + if (anInfo.getTypeName().equalsIgnoreCase("WIFI")) + if (anInfo.isConnected()) + haveConnectedWifi = true; + if (anInfo.getTypeName().equalsIgnoreCase("MOBILE")) + if (anInfo.isConnected()) + haveConnectedMobile = true; + } + } + } + } + return haveConnectedWifi || haveConnectedMobile; + } +} diff --git a/app/src/main/java/com/dharashah/showcaseandroidapp/network/interfaces/ApiService.java b/app/src/main/java/com/dharashah/showcaseandroidapp/network/interfaces/ApiService.java new file mode 100644 index 0000000..e2193da --- /dev/null +++ b/app/src/main/java/com/dharashah/showcaseandroidapp/network/interfaces/ApiService.java @@ -0,0 +1,44 @@ +package com.dharashah.showcaseandroidapp.network.interfaces; + +import com.dharashah.showcaseandroidapp.model.AllData; +import com.dharashah.showcaseandroidapp.model.AndroidHistory; +import com.dharashah.showcaseandroidapp.model.Devices; + +import java.util.List; + +import retrofit.Call; +import retrofit.http.Body; +import retrofit.http.DELETE; +import retrofit.http.GET; +import retrofit.http.POST; +import retrofit.http.Path; +import retrofit.http.Query; + +/** + * Created by Dhara Shah on 22/01/2016.
+ * Holds all the webservice calls to be made. + */ +public interface ApiService { + @GET("android") + Call> getAndroidVersions(@Query(value = "_start", encoded = true) int startValue, + @Query(value="_end", encoded = true) int endValue); + + @GET("devices?_sort=id&_order=DESC") + Call> getDevices(@Query(value = "_start", encoded = true) int startValue, + @Query(value="_end", encoded = true) int endValue); + + @GET("db") + Call getAllData(); + + @POST("android") + Call addAndroidVersion(@Body AndroidHistory androidHistory); + + @POST("devices") + Call addDevice(@Body Devices device); + + @DELETE("android/{id}") + Call deleteVersion(@Path("id") int androidId); + + @DELETE("devices/{id}") + Call deleteDevice(@Path("id") int deviceId); +} diff --git a/app/src/main/java/com/dharashah/showcaseandroidapp/prefs/SharedPrefs.java b/app/src/main/java/com/dharashah/showcaseandroidapp/prefs/SharedPrefs.java new file mode 100644 index 0000000..e4dae79 --- /dev/null +++ b/app/src/main/java/com/dharashah/showcaseandroidapp/prefs/SharedPrefs.java @@ -0,0 +1,75 @@ +package com.dharashah.showcaseandroidapp.prefs; + + +import android.content.Context; +import android.content.SharedPreferences; +import android.content.SharedPreferences.Editor; + +import com.dharashah.showcaseandroidapp.ShowCaseApp; + +/** + * Sharedpreference class that stores the values in the sharedpreference + * related to the app + * + * @author Dhara Shah + */ +public class SharedPrefs { + public static final String DEVICE_START_COUNT = "device_start_count"; + public static final String HISTORY_START_COUNT = "history_start_count"; + public static final String DEVICE_END_COUNT = "device_end_count"; + public static final String HISTORY_END_COUNT = "history_end_count"; + + private static final String PREFS_NAME = "ShowCaseAndroidApp"; + + public static SharedPreferences getPrefs() { + return ShowCaseApp.getAppContext().getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE); + } + + public static String getString(String key, String defaultValue) { + SharedPreferences sp = getPrefs(); + return sp.getString(key, defaultValue); + } + + public static int getInt(String key, int defaultValue) { + SharedPreferences sp = getPrefs(); + return sp.getInt(key, defaultValue); + } + + public static boolean getBoolean(String key, boolean defaultValue) { + SharedPreferences sp = getPrefs(); + return sp.getBoolean(key, defaultValue); + } + + public static void putString(String key, String value) { + SharedPreferences sp = getPrefs(); + Editor editor = sp.edit(); + editor.putString(key, value); + editor.commit(); + } + + public static void putInt(String key, int value) { + SharedPreferences sp = getPrefs(); + Editor editor = sp.edit(); + editor.putInt(key, value); + editor.commit(); + } + + public static void putStrings(String[] keys, String[] values) { + SharedPreferences sp = getPrefs(); + Editor editor = sp.edit(); + + for (int i = 0; i < keys.length; i++) { + String key = keys[i]; + String value = values[i]; + editor.putString(key, value); + } + editor.commit(); + } + + public static void putBoolean(String key, boolean value) { + SharedPreferences sp = getPrefs(); + Editor editor = sp.edit(); + editor.putBoolean(key, value); + editor.commit(); + } +} diff --git a/app/src/main/java/com/dharashah/showcaseandroidapp/utility/CustomExceptionHandler.java b/app/src/main/java/com/dharashah/showcaseandroidapp/utility/CustomExceptionHandler.java new file mode 100644 index 0000000..59d7994 --- /dev/null +++ b/app/src/main/java/com/dharashah/showcaseandroidapp/utility/CustomExceptionHandler.java @@ -0,0 +1,172 @@ +package com.dharashah.showcaseandroidapp.utility; + +import android.app.Activity; +import android.content.Context; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.content.pm.PackageManager.NameNotFoundException; +import android.os.AsyncTask; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.io.Writer; +import java.lang.Thread.UncaughtExceptionHandler; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.ProtocolException; +import java.net.URL; +import java.net.URLEncoder; + +public class CustomExceptionHandler implements UncaughtExceptionHandler { + + private UncaughtExceptionHandler defaultUEH; + public static String sendErrorLogsTo = "dhara.shah@credencys.com" ; + + Activity activity; + + public CustomExceptionHandler(Activity activity) { + this.defaultUEH = Thread.getDefaultUncaughtExceptionHandler(); + this.activity = activity; + } + + public void uncaughtException(Thread t, Throwable e) { + + final Writer result = new StringWriter(); + final PrintWriter printWriter = new PrintWriter(result); + e.printStackTrace(printWriter); + String stacktrace = result.toString(); + printWriter.close(); + String filename = "error" + System.nanoTime() + ".stacktrace"; + + sendToServer(stacktrace, filename); + + StackTraceElement[] arr = e.getStackTrace(); + String report = e.toString() + "\n\n"; + report += "--------- Stack trace ---------\n\n"; + for (int i = 0; i < arr.length; i++) { + report += " " + arr[i].toString() + "\n"; + } + report += "-------------------------------\n\n"; + + report += "--------- Cause ---------\n\n"; + Throwable cause = e.getCause(); + if (cause != null) { + report += cause.toString() + "\n\n"; + arr = cause.getStackTrace(); + for (int i = 0; i < arr.length; i++) { + report += " " + arr[i].toString() + "\n"; + } + } + report += "-------------------------------\n\n"; + + defaultUEH.uncaughtException(t, e); + } + + private void sendToServer(String stacktrace, String filename) { + AsyncTaskClass async = new AsyncTaskClass(stacktrace, filename, + getAppLable(activity)); + async.execute(""); + } + + public String getAppLable(Context pContext) { + PackageManager lPackageManager = pContext.getPackageManager(); + ApplicationInfo lApplicationInfo = null; + try { + lApplicationInfo = lPackageManager.getApplicationInfo( + pContext.getApplicationInfo().packageName, 0); + } catch (final NameNotFoundException e) { + } + return (String) (lApplicationInfo != null ? lPackageManager + .getApplicationLabel(lApplicationInfo) : "Unknown"); + } + + public class AsyncTaskClass extends AsyncTask { + InputStream is = null; + String stacktrace; + final String filename; + String applicationName; + + AsyncTaskClass(final String stacktrace, final String filename, + String applicationName) { + this.applicationName = applicationName; + this.stacktrace = stacktrace; + this.filename = filename; + } + + @Override + protected InputStream doInBackground(String... params) + { + HttpURLConnection connection = null; + try { + String urlMain ="http://suo-yang.com/books/sendErrorLog/sendErrorLogs.php"; + URL url = new URL("http://suo-yang.com/books/sendErrorLog/sendErrorLogs.php"); + connection = (HttpURLConnection) url.openConnection(); + connection.setDoOutput(true); + connection.setDoInput(true); + connection.setRequestMethod("POST"); + connection.setRequestProperty("Content-Type", "application/json"); + connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); + connection.connect(); + + String strParamsToSend = "data=" + URLEncoder.encode(stacktrace, "UTF-8") + + "&to=" + URLEncoder.encode(sendErrorLogsTo, "UTF-8") + + "&subject=" + URLEncoder.encode(applicationName, "UTF-8"); + + if(strParamsToSend != null) { + OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream()); + out.write(strParamsToSend); + out.flush(); + out.close(); + } + + is = connection.getInputStream(); + getStringFromInputStream(is); + + } catch (MalformedURLException e) { + e.printStackTrace(); + } catch (ProtocolException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } finally { + connection.disconnect(); + } + return null; + } + + @Override + protected void onPostExecute(InputStream result) { + super.onPostExecute(result); + } + } + + // convert InputStream to String + private static String getStringFromInputStream(InputStream is) { + BufferedReader reader = null; + StringBuffer buffer = new StringBuffer(); + try { + reader = new BufferedReader(new InputStreamReader(is)); + String line = ""; + while ((line = reader.readLine()) != null) { + buffer.append((line + "\n")); + } + } catch (IOException e) { + e.printStackTrace(); + //Mint.logException(e); + } finally { + try { + is.close(); + } catch (IOException e) { + e.printStackTrace(); + //Mint.logException(e); + } + } + return buffer.toString(); + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/dharashah/showcaseandroidapp/utility/CustomInputValidator.java b/app/src/main/java/com/dharashah/showcaseandroidapp/utility/CustomInputValidator.java new file mode 100644 index 0000000..944d67d --- /dev/null +++ b/app/src/main/java/com/dharashah/showcaseandroidapp/utility/CustomInputValidator.java @@ -0,0 +1,123 @@ +package com.dharashah.showcaseandroidapp.utility; + + +import android.support.v4.content.ContextCompat; +import android.text.Editable; +import android.text.TextUtils; +import android.text.TextWatcher; + +import com.dharashah.showcaseandroidapp.R; +import com.dharashah.showcaseandroidapp.ShowCaseApp; +import com.rengwuxian.materialedittext.MaterialEditText; + +public class CustomInputValidator implements TextWatcher { + private MaterialEditText et; + + /** + * @param editText + */ + public CustomInputValidator(MaterialEditText editText) { + this.et = editText; + } + + /** + * Check error function for all the edittext used in application. + * + * @param editText + * @return boolean + */ + public static boolean checkError(MaterialEditText editText) { + switch (editText.getId()) { + case R.id.etAndroidName: + if (TextUtils.isEmpty(editText.getText().toString())) { + editText.setUnderlineColor(ContextCompat.getColor(ShowCaseApp.getAppContext(), R.color.error_color)); + editText.setHintTextColor(ContextCompat.getColor(ShowCaseApp.getAppContext(), R.color.error_color)); + editText.requestFocus(); + return true; + } + break; + case R.id.etDeviceName: + if (TextUtils.isEmpty(editText.getText().toString())) { + editText.setUnderlineColor(ContextCompat.getColor(ShowCaseApp.getAppContext(), R.color.error_color)); + editText.setHintTextColor(ContextCompat.getColor(ShowCaseApp.getAppContext(), R.color.error_color)); + editText.requestFocus(); + return true; + } + break; + case R.id.etDeviceDescription: + if (TextUtils.isEmpty(editText.getText().toString())) { + editText.setUnderlineColor(ContextCompat.getColor(ShowCaseApp.getAppContext(), R.color.error_color)); + editText.setHintTextColor(ContextCompat.getColor(ShowCaseApp.getAppContext(), R.color.error_color)); + editText.requestFocus(); + return true; + } + break; + case R.id.etAndroidVersion: + if (TextUtils.isEmpty(editText.getText().toString())) { + editText.setUnderlineColor(ContextCompat.getColor(ShowCaseApp.getAppContext(), R.color.error_color)); + editText.setHintTextColor(ContextCompat.getColor(ShowCaseApp.getAppContext(), R.color.error_color)); + editText.requestFocus(); + return true; + } + break; + case R.id.etAndroidCodeName: + if (TextUtils.isEmpty(editText.getText().toString())) { + editText.setUnderlineColor(ContextCompat.getColor(ShowCaseApp.getAppContext(), R.color.error_color)); + editText.setHintTextColor(ContextCompat.getColor(ShowCaseApp.getAppContext(), R.color.error_color)); + editText.requestFocus(); + return true; + } + break; + case R.id.etAndroidTarget: + if (TextUtils.isEmpty(editText.getText().toString())) { + editText.setUnderlineColor(ContextCompat.getColor(ShowCaseApp.getAppContext(), R.color.error_color)); + editText.setHintTextColor(ContextCompat.getColor(ShowCaseApp.getAppContext(), R.color.error_color)); + editText.requestFocus(); + return true; + } + break; + case R.id.etDistribution: + if (TextUtils.isEmpty(editText.getText().toString())) { + editText.setUnderlineColor(ContextCompat.getColor(ShowCaseApp.getAppContext(), R.color.error_color)); + editText.setHintTextColor(ContextCompat.getColor(ShowCaseApp.getAppContext(), R.color.error_color)); + editText.requestFocus(); + return true; + } + break; + } + return false; + + } + + /* + * (non-Javadoc) + * + * @see android.text.TextWatcher#beforeTextChanged(java.lang.CharSequence, int, int, int) + */ + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + } + + /* + * (non-Javadoc) + * + * @see android.text.TextWatcher#onTextChanged(java.lang.CharSequence, int, int, int) + */ + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + if (!checkError(et)) { + et.setUnderlineColor(ContextCompat.getColor(ShowCaseApp.getAppContext(), R.color.colorPrimary)); + et.setHintTextColor(ContextCompat.getColor(ShowCaseApp.getAppContext(), R.color.hint_text)); + } + } + + /* + * (non-Javadoc) + * + * @see android.text.TextWatcher#afterTextChanged(android.text.Editable) + */ + @Override + public void afterTextChanged(Editable s) { + } + +} diff --git a/app/src/main/res/anim/slide_in_down.xml b/app/src/main/res/anim/slide_in_down.xml new file mode 100644 index 0000000..c3bfd2c --- /dev/null +++ b/app/src/main/res/anim/slide_in_down.xml @@ -0,0 +1,5 @@ + + \ No newline at end of file diff --git a/app/src/main/res/anim/slide_in_up.xml b/app/src/main/res/anim/slide_in_up.xml new file mode 100644 index 0000000..24ef764 --- /dev/null +++ b/app/src/main/res/anim/slide_in_up.xml @@ -0,0 +1,5 @@ + + \ No newline at end of file diff --git a/app/src/main/res/anim/slide_out_down.xml b/app/src/main/res/anim/slide_out_down.xml new file mode 100644 index 0000000..0f33954 --- /dev/null +++ b/app/src/main/res/anim/slide_out_down.xml @@ -0,0 +1,5 @@ + + \ No newline at end of file diff --git a/app/src/main/res/anim/slide_out_up.xml b/app/src/main/res/anim/slide_out_up.xml new file mode 100644 index 0000000..12607af --- /dev/null +++ b/app/src/main/res/anim/slide_out_up.xml @@ -0,0 +1,5 @@ + + \ No newline at end of file diff --git a/app/src/main/res/drawable/button_normal.xml b/app/src/main/res/drawable/button_normal.xml new file mode 100644 index 0000000..30bbc80 --- /dev/null +++ b/app/src/main/res/drawable/button_normal.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/button_pressed.xml b/app/src/main/res/drawable/button_pressed.xml new file mode 100644 index 0000000..1bc0000 --- /dev/null +++ b/app/src/main/res/drawable/button_pressed.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/button_selector.xml b/app/src/main/res/drawable/button_selector.xml new file mode 100644 index 0000000..13dedf5 --- /dev/null +++ b/app/src/main/res/drawable/button_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/item_selector.xml b/app/src/main/res/drawable/item_selector.xml new file mode 100644 index 0000000..5dce46d --- /dev/null +++ b/app/src/main/res/drawable/item_selector.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/tooltip_box.9.png b/app/src/main/res/drawable/tooltip_box.9.png new file mode 100644 index 0000000..d7a83ac Binary files /dev/null and b/app/src/main/res/drawable/tooltip_box.9.png differ diff --git a/app/src/main/res/drawable/white_corner_box.xml b/app/src/main/res/drawable/white_corner_box.xml new file mode 100644 index 0000000..015e770 --- /dev/null +++ b/app/src/main/res/drawable/white_corner_box.xml @@ -0,0 +1,15 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_add_device.xml b/app/src/main/res/layout/activity_add_device.xml new file mode 100644 index 0000000..b8965f1 --- /dev/null +++ b/app/src/main/res/layout/activity_add_device.xml @@ -0,0 +1,164 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_add_history.xml b/app/src/main/res/layout/activity_add_history.xml new file mode 100644 index 0000000..bb6a4f7 --- /dev/null +++ b/app/src/main/res/layout/activity_add_history.xml @@ -0,0 +1,254 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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..b3184b9 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,98 @@ + + + + + + + +