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/build.gradle b/app/build.gradle new file mode 100644 index 0000000..19b6dda --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,38 @@ +apply plugin: 'com.android.application' + +android { + compileSdkVersion 24 + buildToolsVersion "25.0.0" + defaultConfig { + applicationId "com.akilloren.t2modus_android_test" + minSdkVersion 16 + targetSdkVersion 24 + versionCode 1 + versionName "1.0" + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } +} + +dependencies { + compile fileTree(dir: 'libs', include: ['*.jar']) + androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { + exclude group: 'com.android.support', module: 'support-annotations' + }) + compile 'com.android.support:appcompat-v7:24.2.1' + compile 'com.android.support.constraint:constraint-layout:1.0.0-beta3' + compile 'com.android.support:design:24.2.1' + compile 'com.android.support:recyclerview-v7:24.2.1' + compile 'com.squareup.picasso:picasso:2.5.2' + compile 'com.google.code.gson:gson:2.6.1' + compile 'com.squareup.retrofit:retrofit:2.0.0-beta2' + compile 'com.squareup.retrofit:converter-gson:2.0.0-beta2' + compile 'com.squareup.okhttp:okhttp:2.4.0' + compile 'com.android.support:cardview-v7:24.2.1' + testCompile 'junit:junit:4.12' +} diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..8094279 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,25 @@ +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in /home/alank/Android/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 *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/app/src/androidTest/java/com/akilloren/t2modus_android_test/ExampleInstrumentedTest.java b/app/src/androidTest/java/com/akilloren/t2modus_android_test/ExampleInstrumentedTest.java new file mode 100644 index 0000000..093d7c1 --- /dev/null +++ b/app/src/androidTest/java/com/akilloren/t2modus_android_test/ExampleInstrumentedTest.java @@ -0,0 +1,26 @@ +package com.akilloren.t2modus_android_test; + +import android.content.Context; +import android.support.test.InstrumentationRegistry; +import android.support.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.*; + +/** + * Instrumentation test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() throws Exception { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getTargetContext(); + + assertEquals("com.akilloren.t2modus_android_test", appContext.getPackageName()); + } +} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..069b508 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/akilloren/t2modus_android_test/activity/DetailActivity.java b/app/src/main/java/com/akilloren/t2modus_android_test/activity/DetailActivity.java new file mode 100644 index 0000000..a86b65d --- /dev/null +++ b/app/src/main/java/com/akilloren/t2modus_android_test/activity/DetailActivity.java @@ -0,0 +1,206 @@ +package com.akilloren.t2modus_android_test.activity; + +import android.app.ProgressDialog; +import android.os.AsyncTask; +import android.os.Bundle; +import android.support.v7.app.AppCompatActivity; +import android.view.MenuItem; +import android.widget.ImageView; +import android.widget.TextView; + +import com.akilloren.t2modus_android_test.R; +import com.akilloren.t2modus_android_test.misc.AppConst; +import com.akilloren.t2modus_android_test.model.Friend; +import com.akilloren.t2modus_android_test.views.CircleTransform; +import com.squareup.okhttp.Callback; +import com.squareup.okhttp.OkHttpClient; +import com.squareup.okhttp.Request; +import com.squareup.okhttp.Response; +import com.squareup.picasso.Picasso; + +import org.json.JSONObject; + +import java.io.IOException; + +public class DetailActivity extends AppCompatActivity { + + private ImageView personPhoto; + private TextView personName; + private TextView personStatus; + private TextView personContactInfo; + private TextView personBioInfo; + private ProgressDialog progressDialog; + private ImageView statusIndicator; + + @SuppressWarnings("ConstantConditions") + @Override + protected void onCreate(Bundle savedInstanceState) { + + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_detail); + + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + + initViews(); + + // get id from intent and call server to get details + if (getIntent().hasExtra("id")) { + int id = getIntent().getIntExtra("id", -1); + if (id > -1) { + getFriendDetails(id); + } + } + + //get passed in status text for display since we don't get it from the details + if (getIntent().hasExtra("status")) { + personStatus.setText(getIntent().getStringExtra("status")); + } + } + + /** + * Initialize the views used in this activity + */ + private void initViews() { + + progressDialog = new ProgressDialog(this); + personPhoto = (ImageView) findViewById(R.id.personPhoto); + personName = (TextView) findViewById(R.id.personName); + personStatus = (TextView) findViewById(R.id.personStatus); + personContactInfo = (TextView) findViewById(R.id.personContactInfo); + personBioInfo = (TextView) findViewById(R.id.personBioInfo); + statusIndicator = (ImageView) findViewById(R.id.status_indicator); + } + + /** + * Calls server API and returns details for a person - Uses OKHttpClient to save TONS of repetitive HTTP coding + * + * @param id Integer value representing the id of the person + */ + private void getFriendDetails(final int id) { + + new AsyncTask() { + + @Override + protected void onPreExecute() { + super.onPreExecute(); + showProgress(getString(R.string.text_loading)); + } + + @Override + protected Response doInBackground(String... strings) { + OkHttpClient client = new OkHttpClient(); + Response response; + Request request = new Request.Builder().url(AppConst.BASE_FRIENDS_API_URL + "/" + id).build(); + + try { + response = client.newCall(request).execute(); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + return response; + } + + @Override + protected void onPostExecute(Response response) { + super.onPostExecute(response); + hideProgress(); + + if (response != null) { + String sResponse; + try { + sResponse = response.body().string(); + + //parse JSON + parseJSON(sResponse); + + } catch (Exception e) { + e.printStackTrace(); + } + } + } + }.execute(); + } + + /** + * Helper method to parse thru returned JSON and populate Friend object + * + * @param json JSON String to parse + */ + private void parseJSON(String json) { + + try { + JSONObject jObj = new JSONObject(json); + Friend friend = new Friend(); + friend.setFirst_name(jObj.getString("first_name")); + friend.setLast_name(jObj.getString("last_name")); + friend.setImg(jObj.getString("img")); + friend.setPhone(jObj.getString("phone")); + friend.setAddress_1(jObj.getString("address_1")); + friend.setCity(jObj.getString("city")); + friend.setState(jObj.getString("state")); + friend.setZipcode(jObj.getString("zipcode")); + friend.setBio(jObj.getString("bio")); + friend.setAvailable(jObj.getBoolean("available")); + + //update UI + updateUI(friend); + + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * Helper method to update views with data from Friend object + * + * @param friend Friend object + */ + private void updateUI(Friend friend) { + + Picasso.with(this).load(friend.getImg()) + .transform(new CircleTransform()) + .error(R.drawable.placeholder) + .placeholder(R.drawable.placeholder) + .into(personPhoto); + personName.setText(friend.getFirst_name() + " " + friend.getLast_name()); + personContactInfo.setText(friend.getAddress_1() + + "\n" + friend.getCity() + + ", " + friend.getState().toUpperCase() + + " " + friend.getZipcode() + + "\n" + friend.getPhone()); + personBioInfo.setText(friend.getBio()); + if (friend.isAvailable()) { + statusIndicator.setImageResource(R.drawable.online); + } else { + statusIndicator.setImageResource(R.drawable.offline); + } + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + + if (item.getItemId() == android.R.id.home) { + finish(); + } + return super.onOptionsItemSelected(item); + } + + /** + * Show a progress dialog + * + * @param msg String message to display + */ + private void showProgress(String msg) { + + progressDialog.setMessage(msg); + progressDialog.show(); + } + + /** + * Hide progress dialog + */ + private void hideProgress() { + progressDialog.dismiss(); + } +} diff --git a/app/src/main/java/com/akilloren/t2modus_android_test/activity/MainActivity.java b/app/src/main/java/com/akilloren/t2modus_android_test/activity/MainActivity.java new file mode 100644 index 0000000..0c8fefd --- /dev/null +++ b/app/src/main/java/com/akilloren/t2modus_android_test/activity/MainActivity.java @@ -0,0 +1,118 @@ +package com.akilloren.t2modus_android_test.activity; + +import android.app.ProgressDialog; +import android.os.Bundle; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.util.Log; +import android.widget.Toast; + +import com.akilloren.t2modus_android_test.R; +import com.akilloren.t2modus_android_test.adapter.FriendAdapter; +import com.akilloren.t2modus_android_test.api.RetrofitAPI; +import com.akilloren.t2modus_android_test.misc.AppConst; +import com.akilloren.t2modus_android_test.model.Friend; + +import java.util.List; + +import retrofit.Call; +import retrofit.Callback; +import retrofit.GsonConverterFactory; +import retrofit.Response; +import retrofit.Retrofit; + +public class MainActivity extends AppCompatActivity { + + private Call> call; + private RecyclerView recyclerView; + private FriendAdapter adapter; + private List friends; + private ProgressDialog progressDialog; + + @Override + protected void onCreate(Bundle savedInstanceState) { + + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + initViews(); + getData(); + } + + /** + * Initialize all the views that will be used in this activity + */ + private void initViews() { + + progressDialog = new ProgressDialog(this); + LinearLayoutManager llm = new LinearLayoutManager(this); + recyclerView = (RecyclerView) findViewById(R.id.recyclerView); + recyclerView.setLayoutManager(llm); + recyclerView.setHasFixedSize(true); + + //The following line can be uncommented if you are not using a CardView in the layout and just want a regular "listview" + //recyclerView.addItemDecoration(new SimpleDividerItemDecoration(getApplicationContext())); + } + + /** + * Calls server API and returns populated list from JSON - Uses Retrofit/GSON in one call + */ + private void getData() { + + Log.i(AppConst.TAG, "Getting data using Retrofit..."); + showProgress(getString(R.string.text_loading)); + + Retrofit retrofit = new Retrofit.Builder() + .baseUrl(AppConst.BASE_API_URL) + .addConverterFactory(GsonConverterFactory.create()) + .build(); + RetrofitAPI service = retrofit.create(RetrofitAPI.class); + + call = service.getFriendList(); + call.enqueue(new Callback>() { + + @Override + public void onResponse(Response> response, Retrofit retrofit) { + hideProgress(); + friends = response.body(); + if (friends != null && friends.size() > 0) { + getAdapter(); + Log.i(AppConst.TAG, "Data received and list populated."); + } + } + + @Override + public void onFailure(Throwable t) { + hideProgress(); + Toast.makeText(MainActivity.this, "Problem occurred while retrieving data", Toast.LENGTH_SHORT).show(); + Log.e(AppConst.TAG, "Failed to receive data using Retrofit"); + } + }); + } + + /** + * Initializes the data adapter + */ + private void getAdapter() { + + adapter = new FriendAdapter(this, friends); + recyclerView.setAdapter(adapter); + } + + @Override + protected void onDestroy() { + + super.onDestroy(); + call.cancel();//cancel any calls to the server if we exit + } + + private void showProgress(String msg) { + + progressDialog.setMessage(msg); + progressDialog.show(); + } + + private void hideProgress() { + progressDialog.dismiss(); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/akilloren/t2modus_android_test/adapter/FriendAdapter.java b/app/src/main/java/com/akilloren/t2modus_android_test/adapter/FriendAdapter.java new file mode 100644 index 0000000..ee15c40 --- /dev/null +++ b/app/src/main/java/com/akilloren/t2modus_android_test/adapter/FriendAdapter.java @@ -0,0 +1,96 @@ +package com.akilloren.t2modus_android_test.adapter; + +import android.content.Context; +import android.content.Intent; +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.akilloren.t2modus_android_test.R; +import com.akilloren.t2modus_android_test.activity.DetailActivity; +import com.akilloren.t2modus_android_test.model.Friend; +import com.akilloren.t2modus_android_test.views.CircleTransform; +import com.squareup.picasso.Picasso; + +import java.util.List; + +/** + * RecyclerView adapter - holds the data for the Friends list + * + * @author alank + */ + +public class FriendAdapter extends RecyclerView.Adapter { + + private List friends; + private Context context; + + public FriendAdapter(Context context, List friends) { + this.friends = friends; + this.context = context; + } + + class FriendViewHolder extends RecyclerView.ViewHolder { + + TextView friendName; + TextView friendStatus; + ImageView friendPhoto; + ImageView statusIndicator; + View mRootView; + + FriendViewHolder(View itemView) { + super(itemView); + friendName = (TextView) itemView.findViewById(R.id.full_name); + friendStatus = (TextView) itemView.findViewById(R.id.status); + friendPhoto = (ImageView) itemView.findViewById(R.id.personimage); + statusIndicator = (ImageView) itemView.findViewById(R.id.status_indicator); + mRootView = itemView; + } + } + + @Override + public void onAttachedToRecyclerView(RecyclerView recyclerView) { + super.onAttachedToRecyclerView(recyclerView); + } + + @Override + public FriendViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { + View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.list_item, viewGroup, false); + return new FriendViewHolder(v); + } + + @Override + public void onBindViewHolder(FriendViewHolder friendViewHolder, int i) { + final Friend friend = friends.get(i); + friendViewHolder.friendName.setText(friend.getFirst_name() + " " + friend.getLast_name()); + friendViewHolder.friendStatus.setText(friend.getStatus()); + if (friend.isAvailable()) { + friendViewHolder.statusIndicator.setImageResource(R.drawable.online); + } else { + friendViewHolder.statusIndicator.setImageResource(R.drawable.offline); + } + Picasso.with(context).load(friend.getImg()) + .transform(new CircleTransform()) + .error(R.drawable.placeholder) + .placeholder(R.drawable.placeholder) + .into(friendViewHolder.friendPhoto); + + friendViewHolder.mRootView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + Intent intent = new Intent(context, DetailActivity.class); + intent.putExtra("id", friend.getId()); + intent.putExtra("status",friend.getStatus()); + context.startActivity(intent); + } + }); + } + + @Override + public int getItemCount() { + return friends.size(); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/akilloren/t2modus_android_test/api/RetrofitAPI.java b/app/src/main/java/com/akilloren/t2modus_android_test/api/RetrofitAPI.java new file mode 100644 index 0000000..337d880 --- /dev/null +++ b/app/src/main/java/com/akilloren/t2modus_android_test/api/RetrofitAPI.java @@ -0,0 +1,23 @@ +package com.akilloren.t2modus_android_test.api; + + +import com.akilloren.t2modus_android_test.model.Friend; + +import java.util.List; + +import retrofit.Call; +import retrofit.http.GET; + +/** + * The Retrofit interface and endpoint definintions + * @author alank + */ + +public interface RetrofitAPI { + + @GET("friends") + Call> getFriendList(); + + //add more endpoints/calls here + +} \ No newline at end of file diff --git a/app/src/main/java/com/akilloren/t2modus_android_test/misc/AppConst.java b/app/src/main/java/com/akilloren/t2modus_android_test/misc/AppConst.java new file mode 100644 index 0000000..4896f84 --- /dev/null +++ b/app/src/main/java/com/akilloren/t2modus_android_test/misc/AppConst.java @@ -0,0 +1,15 @@ +package com.akilloren.t2modus_android_test.misc; + +/** + * Miscellaneous constants + * + * @author alank + */ + +public class AppConst { + + public static String TAG = "T2ModusTest"; + public static String BASE_API_URL = "https://private-c1b9f-t2mobile.apiary-mock.com"; + public static String BASE_FRIENDS_API_URL = BASE_API_URL+ "/friends"; + +} diff --git a/app/src/main/java/com/akilloren/t2modus_android_test/model/Friend.java b/app/src/main/java/com/akilloren/t2modus_android_test/model/Friend.java new file mode 100644 index 0000000..38b40a6 --- /dev/null +++ b/app/src/main/java/com/akilloren/t2modus_android_test/model/Friend.java @@ -0,0 +1,139 @@ +package com.akilloren.t2modus_android_test.model; + +import java.util.List; + +/** + * Friend data object + * + * @author alank + */ + +public class Friend { + + private int id; + private String img; + private String first_name; + private String last_name; + private String status; + private boolean available; + private String phone; + private String address_1; + private String city; + private String state; + private String zipcode; + private String bio; + private List photos; + private List statuses; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getImg() { + return img; + } + + public void setImg(String img) { + this.img = img; + } + + public String getFirst_name() { + return first_name; + } + + public void setFirst_name(String first_name) { + this.first_name = first_name; + } + + public String getLast_name() { + return last_name; + } + + public void setLast_name(String last_name) { + this.last_name = last_name; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public boolean isAvailable() { + return available; + } + + public void setAvailable(boolean available) { + this.available = available; + } + + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } + + public String getAddress_1() { + return address_1; + } + + public void setAddress_1(String address_1) { + this.address_1 = address_1; + } + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } + + public String getState() { + return state; + } + + public void setState(String state) { + this.state = state; + } + + public String getZipcode() { + return zipcode; + } + + public void setZipcode(String zipcode) { + this.zipcode = zipcode; + } + + public String getBio() { + return bio; + } + + public void setBio(String bio) { + this.bio = bio; + } + + public List getPhotos() { + return photos; + } + + public void setPhotos(List photos) { + this.photos = photos; + } + + public List getStatuses() { + return statuses; + } + + public void setStatuses(List statuses) { + this.statuses = statuses; + } +} diff --git a/app/src/main/java/com/akilloren/t2modus_android_test/views/CircleTransform.java b/app/src/main/java/com/akilloren/t2modus_android_test/views/CircleTransform.java new file mode 100644 index 0000000..e1ac28b --- /dev/null +++ b/app/src/main/java/com/akilloren/t2modus_android_test/views/CircleTransform.java @@ -0,0 +1,49 @@ +package com.akilloren.t2modus_android_test.views; + +import android.graphics.Bitmap; +import android.graphics.BitmapShader; +import android.graphics.Canvas; +import android.graphics.Paint; + +import com.squareup.picasso.Transformation; + +/** + * Creates a round image from a bitmap (for Picasso) + * + * @author alank + */ + +public class CircleTransform implements Transformation { + @Override + public Bitmap transform(Bitmap source) { + int size = Math.min(source.getWidth(), source.getHeight()); + + int x = (source.getWidth() - size) / 2; + int y = (source.getHeight() - size) / 2; + + Bitmap squaredBitmap = Bitmap.createBitmap(source, x, y, size, size); + if (squaredBitmap != source) { + source.recycle(); + } + + Bitmap bitmap = Bitmap.createBitmap(size, size, source.getConfig()); + + Canvas canvas = new Canvas(bitmap); + Paint paint = new Paint(); + BitmapShader shader = new BitmapShader(squaredBitmap, + BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP); + paint.setShader(shader); + paint.setAntiAlias(true); + + float r = size / 2f; + canvas.drawCircle(r, r, r, paint); + + squaredBitmap.recycle(); + return bitmap; + } + + @Override + public String key() { + return "circle"; + } +} diff --git a/app/src/main/java/com/akilloren/t2modus_android_test/views/SimpleDividerItemDecoration.java b/app/src/main/java/com/akilloren/t2modus_android_test/views/SimpleDividerItemDecoration.java new file mode 100644 index 0000000..8bab6f8 --- /dev/null +++ b/app/src/main/java/com/akilloren/t2modus_android_test/views/SimpleDividerItemDecoration.java @@ -0,0 +1,40 @@ +package com.akilloren.t2modus_android_test.views; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.drawable.Drawable; +import android.support.v7.widget.RecyclerView; +import android.view.View; + +import com.akilloren.t2modus_android_test.R; + +/** + * Created by alank on 4/14/17. + */ + +public class SimpleDividerItemDecoration extends RecyclerView.ItemDecoration { + private Drawable mDivider; + + public SimpleDividerItemDecoration(Context context) { + mDivider = context.getResources().getDrawable(R.drawable.line_divider); + } + + @Override + public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) { + int left = parent.getPaddingLeft(); + int right = parent.getWidth() - parent.getPaddingRight(); + + int childCount = parent.getChildCount(); + for (int i = 0; i < childCount; i++) { + View child = parent.getChildAt(i); + + RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams(); + + int top = child.getBottom() + params.bottomMargin; + int bottom = top + mDivider.getIntrinsicHeight(); + + mDivider.setBounds(left, top, right, bottom); + mDivider.draw(c); + } + } +} diff --git a/app/src/main/res/drawable/line_divider.xml b/app/src/main/res/drawable/line_divider.xml new file mode 100644 index 0000000..fc4aca7 --- /dev/null +++ b/app/src/main/res/drawable/line_divider.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/offline.xml b/app/src/main/res/drawable/offline.xml new file mode 100644 index 0000000..32635da --- /dev/null +++ b/app/src/main/res/drawable/offline.xml @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/online.xml b/app/src/main/res/drawable/online.xml new file mode 100644 index 0000000..acbf92b --- /dev/null +++ b/app/src/main/res/drawable/online.xml @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/placeholder.png b/app/src/main/res/drawable/placeholder.png new file mode 100644 index 0000000..b51fd2a Binary files /dev/null and b/app/src/main/res/drawable/placeholder.png differ diff --git a/app/src/main/res/layout/activity_detail.xml b/app/src/main/res/layout/activity_detail.xml new file mode 100644 index 0000000..cfbfd7f --- /dev/null +++ b/app/src/main/res/layout/activity_detail.xml @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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..5574ab6 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,14 @@ + + + + + + diff --git a/app/src/main/res/layout/list_item.xml b/app/src/main/res/layout/list_item.xml new file mode 100644 index 0000000..e52ac28 --- /dev/null +++ b/app/src/main/res/layout/list_item.xml @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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/colors.xml b/app/src/main/res/values/colors.xml new file mode 100644 index 0000000..597d72c --- /dev/null +++ b/app/src/main/res/values/colors.xml @@ -0,0 +1,9 @@ + + + #3F51B5 + #303F9F + #FF4081 + #cccccc + #1f9b06 + #cc1010 + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..1f54bff --- /dev/null +++ b/app/src/main/res/values/strings.xml @@ -0,0 +1,8 @@ + + T2 Modus Android Test + + Loading... + Contact Info + Bio + + diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..5885930 --- /dev/null +++ b/app/src/main/res/values/styles.xml @@ -0,0 +1,11 @@ + + + + + + diff --git a/app/src/test/java/com/akilloren/t2modus_android_test/ExampleUnitTest.java b/app/src/test/java/com/akilloren/t2modus_android_test/ExampleUnitTest.java new file mode 100644 index 0000000..5fe0e2e --- /dev/null +++ b/app/src/test/java/com/akilloren/t2modus_android_test/ExampleUnitTest.java @@ -0,0 +1,17 @@ +package com.akilloren.t2modus_android_test; + +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * Example local unit test, which will execute on the development machine (host). + * + * @see Testing documentation + */ +public class ExampleUnitTest { + @Test + public void addition_isCorrect() throws Exception { + assertEquals(4, 2 + 2); + } +} \ No newline at end of file