diff --git a/mobile/build.gradle b/mobile/build.gradle index 41cb15c26a214ca14b66f67871daa3d538cd780e..0500571d5899be3805174c15ae5059350a870c3e 100644 --- a/mobile/build.gradle +++ b/mobile/build.gradle @@ -105,8 +105,9 @@ configurations { } dependencies { + implementation 'com.android.support:cardview-v7:28.0.0' // implementation 'com.android.support:appcompat-v7:28.0.0' - implementation "androidx.appcompat:appcompat:1.0.0" + implementation "androidx.appcompat:appcompat:1.0.2" implementation "androidx.legacy:legacy-support-v4:1.0.0" implementation "androidx.recyclerview:recyclerview:1.0.0" implementation "com.google.android.material:material:1.0.0" @@ -170,6 +171,14 @@ dependencies { } androidTestImplementation 'tools.fastlane:screengrab:1.1.0' + + + + implementation "com.android.support:cardview-v7:28.0.0" + implementation 'com.android.support:recyclerview-v7:28.0.0' + + implementation 'com.squareup.retrofit2:retrofit:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.3.0' } dependencyVerification { diff --git a/mobile/src/main/java/org/openhab/habdroid/model/Recognitions.java b/mobile/src/main/java/org/openhab/habdroid/model/Recognitions.java new file mode 100644 index 0000000000000000000000000000000000000000..b91d00ff58d80006b3e693d0d032247972980484 --- /dev/null +++ b/mobile/src/main/java/org/openhab/habdroid/model/Recognitions.java @@ -0,0 +1,77 @@ +package org.openhab.habdroid.model; + +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; + +/* + * OpenLicht + * Recognition data as POJO + * By Muhammad Ibrahim Rahman + */ + +public class Recognitions {@SerializedName("identifier") + +@Expose +private Integer identifier; + @SerializedName("type") + @Expose + private String type; + @SerializedName("activity") + @Expose + private String activity; + @SerializedName("description") + @Expose + private String description; + @SerializedName("timestamp") + @Expose + private Integer timestamp; + + public Recognitions(Integer identifier, String type, String activity, String description, Integer timestamp) { + this.identifier = identifier; + this.type = type; + this.activity = activity; + this.description = description; + this.timestamp = timestamp; + } + + public Integer getIdentifier() { + + return identifier; + } + + public void setIdentifier(Integer identifier) { + this.identifier = identifier; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getActivity() { + return activity; + } + + public void setActivity(String activity) { + this.activity = activity; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public Integer getTimestamp() { + return timestamp; + } + + public void setTimestamp(Integer timestamp) { + this.timestamp = timestamp; + } +} diff --git a/mobile/src/main/java/org/openhab/habdroid/ui/RecognitionsActivity.java b/mobile/src/main/java/org/openhab/habdroid/ui/RecognitionsActivity.java index d5ee82dabce245c25de607d6c53ddaeec6467da8..730829bbadd7121ac66b496be7b0886a3634a9c0 100644 --- a/mobile/src/main/java/org/openhab/habdroid/ui/RecognitionsActivity.java +++ b/mobile/src/main/java/org/openhab/habdroid/ui/RecognitionsActivity.java @@ -1,55 +1,94 @@ package org.openhab.habdroid.ui; -import android.app.AlertDialog; -import android.content.Context; +import android.app.ProgressDialog; import android.os.Bundle; import android.view.MenuItem; -import com.danielstone.materialaboutlibrary.MaterialAboutFragment; -import com.danielstone.materialaboutlibrary.items.MaterialAboutActionItem; -import com.danielstone.materialaboutlibrary.items.MaterialAboutTitleItem; -import com.danielstone.materialaboutlibrary.model.MaterialAboutCard; -import com.danielstone.materialaboutlibrary.model.MaterialAboutList; - - import org.openhab.habdroid.R; import org.openhab.habdroid.util.Util; +import org.openhab.habdroid.model.Recognitions; +import org.openhab.habdroid.util.GetDataService; +import org.openhab.habdroid.util.RetrofitClientInstance; + +import java.util.List; + +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Response; import androidx.annotation.StringRes; import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.Toolbar; import androidx.fragment.app.FragmentManager; +import androidx.recyclerview.widget.RecyclerView; +import androidx.recyclerview.widget.LinearLayoutManager; +import android.widget.Toast; -import static org.openhab.habdroid.util.Util.getSitemapByName; -import static org.openhab.habdroid.util.Util.obfuscateString; +/* + * Activity for OpenLicht Recognitions + * By Muhammad Ibrahim Rahman + */ + +public class RecognitionsActivity extends AppCompatActivity{ + + private RecognitionsAdapter adapter; + private RecyclerView recyclerView; + ProgressDialog progressDialog; -public class RecognitionsActivity extends AppCompatActivity implements - FragmentManager.OnBackStackChangedListener { @Override public void onCreate(Bundle savedInstanceState) { Util.setActivityTheme(this); super.onCreate(savedInstanceState); setContentView(R.layout.activity_recognitions); - getSupportFragmentManager().addOnBackStackChangedListener(this); Toolbar toolbar = findViewById(R.id.openhab_toolbar); setSupportActionBar(toolbar); getSupportActionBar().setDisplayHomeAsUpEnabled(true); if (savedInstanceState == null) { - RecognitionsMainFragment f = new RecognitionsMainFragment(); - f.setArguments(getIntent().getExtras()); - getSupportFragmentManager() - .beginTransaction() - .add(R.id.recognitions_container, f) - .commit(); + getRESTData(); } updateTitle(); setResult(RESULT_OK); } + private void getRESTData() { + progressDialog = new ProgressDialog(RecognitionsActivity.this); + progressDialog.setMessage("Loading...."); + progressDialog.show(); + + // Interface for the RetrofitInstance + GetDataService service = RetrofitClientInstance.getRetrofitInstance().create(GetDataService.class); + + Call<List<Recognitions>> call = service.getAllRecognitions(); + call.enqueue(new Callback<List<Recognitions>>() { + + @Override + public void onResponse(Call<List<Recognitions>> call, Response<List<Recognitions>> response) { + progressDialog.dismiss(); + generateDataList(response.body()); + } + + @Override + public void onFailure(Call<List<Recognitions>> call, Throwable t) { + progressDialog.dismiss(); + Toast.makeText(RecognitionsActivity.this, "Error loading Recognitions. Please check your network connection.", Toast.LENGTH_SHORT).show(); + } + }); + + } + + // generates a List using RecyclerView with the RecognitionsAdapter + private void generateDataList(List<Recognitions> recognitionsList) { + recyclerView = findViewById(R.id.customRecyclerView); + adapter = new RecognitionsAdapter(this,recognitionsList); + RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(RecognitionsActivity.this); + recyclerView.setLayoutManager(layoutManager); + recyclerView.setAdapter(adapter); + } + @Override public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == android.R.id.home) { @@ -65,11 +104,6 @@ public class RecognitionsActivity extends AppCompatActivity implements Util.overridePendingTransition(this, true); } - @Override - public void onBackStackChanged() { - updateTitle(); - } - private void updateTitle() { FragmentManager fm = getSupportFragmentManager(); int count = fm.getBackStackEntryCount(); @@ -78,113 +112,4 @@ public class RecognitionsActivity extends AppCompatActivity implements : R.string.recognitions_title; setTitle(titleResId); } - - public static class RecognitionsMainFragment extends MaterialAboutFragment { - private static final String TAG = RecognitionsMainFragment.class.getSimpleName(); - - // Placeholder Recognitions - String dialogTitle; - String dialogText; - String br = "\n"; - // 1st Recognition - String rec1When = "Today, 12:37"; - String rec1What1 = "Recognized: Sitting in armchair"; - String rec1Which1 = "Changed Huelris2 to Green"; - String rec1Which2 = "Changed HueGo3 to Green"; - String rec1Desc = rec1What1 + br + rec1Which1 + br + rec1Which2; - // 2nd Recognition - String rec2When = "Yesterday, 22:27"; - String rec2What1 = "Recognized: Going to sleep"; - String rec2Which1 = "Changed: HueGo3 to off"; - String rec2Desc = rec2What1 + br + rec2Which1; - // 3rd Recognition - String rec3When = "2017-12-31, 18:01"; - String rec3What1 = "Manual setting to Party"; - String rec3Which1 = "Changed all lights to Random Color"; - String rec3Desc = rec3What1 + br + rec3Which1; - - @Override - protected MaterialAboutList getMaterialAboutList (final Context context) { - -// Recent Recognition - MaterialAboutCard.Builder recentCard = new MaterialAboutCard.Builder(); - recentCard.addItem(new MaterialAboutTitleItem.Builder() - .text("Most recent Recognition") - .build()); - recentCard.addItem(new MaterialAboutActionItem.Builder() - .text(rec1When) - .subText(rec1Desc) - .icon(R.drawable.ic_update_grey_24dp) - .setOnClickAction(() -> { - dialogTitle = rec1When; - dialogText = rec1Desc; - openDialog(); - }) - .build()); - -// Past Recognitions - MaterialAboutCard.Builder pastCard = new MaterialAboutCard.Builder(); - pastCard.title("Past Recognitions"); - pastCard.addItem(new MaterialAboutActionItem.Builder() - .text(rec1When) - .subText(rec1Desc) - .icon(R.drawable.ic_update_grey_24dp) - .setOnClickAction(() -> { - dialogTitle = rec1When; - dialogText = rec1Desc; - openDialog(); - }) - .build()); - pastCard.addItem(new MaterialAboutActionItem.Builder() - .text(rec2When) - .subText(rec2Desc) - .icon(R.drawable.ic_update_grey_24dp) - .setOnClickAction(() -> { - dialogTitle = rec2When; - dialogText = rec2Desc; - openDialog(); - }) - .build()); - pastCard.addItem(new MaterialAboutActionItem.Builder() - .text(rec3When) - .subText(rec3Desc) - .icon(R.drawable.ic_update_grey_24dp) - .setOnClickAction(() -> { - dialogTitle = rec3When; - dialogText = rec3Desc; - openDialog(); - }) - .build()); - - return new MaterialAboutList.Builder() - .addCard(recentCard.build()) - .addCard(pastCard.build()) - .build(); - } - -// On-click Dialog Box - private void openDialog() { - new AlertDialog.Builder(getContext()) - .setTitle(dialogTitle) - .setMessage(dialogText) - .setCancelable(true) - .setPositiveButton("Reapply", (dialog, which) -> { - // Reapply the recognition - }) - .setNegativeButton("Cancel", (dialogInterface, i) -> { - // Close dialog - }) - .setNeutralButton("Forget", (dialogInterface, i) -> { - // Delete the Recognition - }) - .show(); - } - - @Override - protected int getTheme() { - return Util.getActivityThemeId(getActivity()); - } - - } - } diff --git a/mobile/src/main/java/org/openhab/habdroid/ui/RecognitionsAdapter.java b/mobile/src/main/java/org/openhab/habdroid/ui/RecognitionsAdapter.java new file mode 100644 index 0000000000000000000000000000000000000000..4b5ac2358f59637463dc03a92b20842deab5697c --- /dev/null +++ b/mobile/src/main/java/org/openhab/habdroid/ui/RecognitionsAdapter.java @@ -0,0 +1,71 @@ +package org.openhab.habdroid.ui; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import org.openhab.habdroid.R; +import org.openhab.habdroid.model.Recognitions; + +import java.util.List; + +import androidx.recyclerview.widget.RecyclerView; + +/* + * OpenLicht + * Displaying to RecyclerView + * By Muhammad Ibrahim Rahman + */ + +public class RecognitionsAdapter extends RecyclerView.Adapter<RecognitionsAdapter.CustomViewHolder> { + + private List<Recognitions> dataList; + private Context context; + + public RecognitionsAdapter(Context context, List<Recognitions> dataList){ + this.context = context; + this.dataList = dataList; + } + + class CustomViewHolder extends RecyclerView.ViewHolder { + + public final View mView; + + TextView recDescription; + TextView recType; + TextView recActivity; + TextView recTimestamp; + + CustomViewHolder(View itemView) { + super(itemView); + mView = itemView; + + recDescription = mView.findViewById(R.id.recognitionDescription); + recType = mView.findViewById(R.id.recognitionType); + recActivity = mView.findViewById(R.id.recognitionActivity); + recTimestamp = mView.findViewById(R.id.recognitionTimestamp); + } + } + + @Override + public CustomViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext()); + View view = layoutInflater.inflate(R.layout.custom_row, parent, false); + return new CustomViewHolder(view); + } + + @Override + public void onBindViewHolder(CustomViewHolder holder, int position) { + holder.recDescription.setText(dataList.get(position).getDescription()); + holder.recType.setText(dataList.get(position).getType()); + holder.recActivity.setText(dataList.get(position).getActivity()); + holder.recTimestamp.setText(String.valueOf(dataList.get(position).getTimestamp())); + } + + @Override + public int getItemCount() { + return dataList.size(); + } +} diff --git a/mobile/src/main/java/org/openhab/habdroid/util/GetDataService.java b/mobile/src/main/java/org/openhab/habdroid/util/GetDataService.java new file mode 100644 index 0000000000000000000000000000000000000000..4669e06575fd2d29015450fc382a500369ebfd1b --- /dev/null +++ b/mobile/src/main/java/org/openhab/habdroid/util/GetDataService.java @@ -0,0 +1,20 @@ +package org.openhab.habdroid.util; + +import org.openhab.habdroid.model.Recognitions; + +import java.util.List; + +import retrofit2.Call; +import retrofit2.http.GET; + +/* + * OpenLicht + * All Endpoints are defined here + * By Muhammad Ibrahim Rahman + */ + +public interface GetDataService { + + @GET("/recognitions") + Call<List<Recognitions>> getAllRecognitions(); +} diff --git a/mobile/src/main/java/org/openhab/habdroid/util/RetrofitClientInstance.java b/mobile/src/main/java/org/openhab/habdroid/util/RetrofitClientInstance.java new file mode 100644 index 0000000000000000000000000000000000000000..24460184d9fef3ea56eeb648cca8e84743535dae --- /dev/null +++ b/mobile/src/main/java/org/openhab/habdroid/util/RetrofitClientInstance.java @@ -0,0 +1,26 @@ +package org.openhab.habdroid.util; + +import retrofit2.Retrofit; +import retrofit2.converter.gson.GsonConverterFactory; + +/* + * OpenLicht + * Use Retrofit to call the API + * By Muhammad Ibrahim Rahman + */ + +public class RetrofitClientInstance { + + private static Retrofit retrofit; + private static final String BASE_URL = "http://10.0.2.2:5000"; + + public static Retrofit getRetrofitInstance() { + if (retrofit == null) { + retrofit = new Retrofit.Builder() + .baseUrl(BASE_URL) + .addConverterFactory(GsonConverterFactory.create()) + .build(); + } + return retrofit; + } +} diff --git a/mobile/src/main/res/layout/activity_recognitions.xml b/mobile/src/main/res/layout/activity_recognitions.xml index 22866036f9983461fa758f8df7dc0738260d202b..ad135acc63f36fabb309e6de037e0cd06738f2a4 100644 --- a/mobile/src/main/res/layout/activity_recognitions.xml +++ b/mobile/src/main/res/layout/activity_recognitions.xml @@ -1,8 +1,13 @@ <?xml version="1.0" encoding="utf-8"?> + +<!--Layout for OpenLicht Recognitions--> +<!--By Muhammad Ibrahim Rahman--> + <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" android:orientation="vertical"> <androidx.appcompat.widget.Toolbar @@ -14,9 +19,9 @@ app:popupTheme="@style/ThemeOverlay.AppCompat.Light" app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" /> - <FrameLayout - android:id="@+id/recognitions_container" + <androidx.recyclerview.widget.RecyclerView + android:id="@+id/customRecyclerView" android:layout_width="match_parent" - android:layout_height="match_parent" /> - + android:layout_height="match_parent" + /> </LinearLayout> \ No newline at end of file diff --git a/mobile/src/main/res/layout/custom_row.xml b/mobile/src/main/res/layout/custom_row.xml new file mode 100644 index 0000000000000000000000000000000000000000..3151bbf94c37b074369ddee9cbc8a93c6825e356 --- /dev/null +++ b/mobile/src/main/res/layout/custom_row.xml @@ -0,0 +1,58 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!--OpenLicht--> +<!--Layout for RecyclerView--> +<!--By Muhammad Ibrahim Rahman--> + +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + xmlns:card_view="http://schemas.android.com/apk/res-auto" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:padding="6dp" + > + + <androidx.cardview.widget.CardView + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:id="@+id/card_view" + card_view:cardUseCompatPadding="true" + card_view:cardCornerRadius="2dp" + + > + + <RelativeLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:padding="6dp" + > + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:id="@+id/recognitionDescription" + android:layout_alignParentTop="true" + android:textSize="30sp" + tools:text="Sample Text"/> + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:id="@+id/recognitionType" + android:layout_below="@+id/recognitionDescription" + tools:text="Sample Text"/> + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:id="@+id/recognitionActivity" + android:layout_below="@+id/recognitionType" + tools:text="Sample Text"/> + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:id="@+id/recognitionTimestamp" + android:layout_below="@+id/recognitionActivity" + tools:text="Sample Text"/> + + </RelativeLayout> + </androidx.cardview.widget.CardView> +</LinearLayout>