Translate

Wednesday, June 24, 2020

Android Code to stop progressBar spinning


While implementing circler progressBar , I have faced issue of ProgressBar spin never stops.
After loading the UI progressBar circle continuously rotating.

I have tried various solutions and out of all those following solution works for me to stop the circle spinning.

circle.xml :
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="ring"
android:innerRadiusRatio="2.3"
android:thicknessRatio="15.0"
android:useLevel="true">
<solid android:color="#0099ff"/>

</shape>


main_activity.xml :
RelativeLayout
android:layout_width="45dp"
android:layout_height="45dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginRight="24dp">
<ProgressBar
android:id="@+id/progressBar"
android:layout_width="45dp"
android:layout_height="45dp"
android:layout_centerInParent="true"
android:indeterminate="false"
android:clickable="false"
android:progress="80"
android:max="10"
style="?android:progressBarStyleHorizontal"
android:progressDrawable="@drawable/circular" />
<TextView
android:id="@+id/txtProgress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="134"
android:layout_centerInParent="true"
android:textSize="8sp"
android:textColor="#FFF" />
</RelativeLayout>


Monday, June 22, 2020

Best coding practices to implement Android applications with clean architecture

Monday, June 1, 2020

Android Code for backend RESTful API call using Retrofit and RXjava callback methods


build.gradle :
apply plugin: 'com.android.application'

android {
compileSdkVersion 28
buildToolsVersion "29.0.2"
defaultConfig {
applicationId "com.example.cbrecodingtest"
minSdkVersion 15
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
multiDexEnabled true
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}

dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.0"
implementation 'com.android.support:appcompat-v7:28+'
implementation 'com.android.support:recyclerview-v7:28+'
implementation 'com.android.support:cardview-v7:28+'
implementation 'com.android.support.constraint:constraint-layout:1.0.2'

implementation 'com.squareup.retrofit2:retrofit:2.3.0'
implementation 'com.squareup.retrofit2:converter-gson:2.3.0'
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
implementation 'io.reactivex.rxjava2:rxjava:2.1.9'
implementation 'io.reactivex.rxjava2:rxandroid:2.0.2'

testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.1'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
implementation 'com.squareup.retrofit2:converter-jackson:2.4.0'


implementation 'io.reactivex:rxandroid:1.2.1'
implementation 'io.reactivex:rxjava:1.1.6'

implementation 'com.android.support:support-v4:28.2.0'
implementation 'com.android.support:design:28.2.0'

implementation 'com.squareup.picasso:picasso:2.71828'

implementation 'com.google.android.gms:play-services-maps:17.0.0'
implementation 'com.google.android.gms:play-services-location:17.0.0'

implementation 'com.android.support:multidex:1.0.3'
}

MainActivity.java
import android.os.Bundle;
import android.util.Log;

import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.viewpager.widget.ViewPager;

import com.example.cbrecodingtest.adapter.TabAdapter;
import com.example.cbrecodingtest.interfaces.RestaurantData;
import com.example.cbrecodingtest.model.RestaurantsModel;
import com.example.cbrecodingtest.utils.Utils;
import com.example.cbrecodingtest.view.MapTabFragment;
import com.example.cbrecodingtest.view.RestaurantTabFragment;
import com.google.android.material.tabs.TabLayout;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

import java.io.Serializable;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

public class MainActivity extends AppCompatActivity implements Callback<List<RestaurantsModel>>{

private TabAdapter mTabAdapter;
private TabLayout mTabLayout;
private ViewPager mViewPager;
public static final String BASE_URL = "http://dallas-restaurants.33gfuuywva.us-east-2.elasticbeanstalk.com/";
private int[] tabIcons = {
R.drawable.ic_restaurant,
R.drawable.ic_map
};
private Toolbar mToolbar;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

initViewIds();
backendApiCall();
}

private void initViewIds() {
mToolbar = findViewById(R.id.toolbar);
setSupportActionBar(mToolbar);

mViewPager = findViewById(R.id.viewPager);
mTabLayout = findViewById(R.id.tabLayout);
mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
highLightCurrentTab(position);
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
}

private void highLightCurrentTab(int position) {
for (int i = 0; i < mTabLayout.getTabCount(); i++) {
TabLayout.Tab tab = mTabLayout.getTabAt(i);
assert tab != null;
tab.setCustomView(null);
tab.setCustomView(mTabAdapter.getTabView(i));
}
TabLayout.Tab tab = mTabLayout.getTabAt(position);
assert tab != null;
tab.setCustomView(null);
tab.setCustomView(mTabAdapter.getSelectedTabView(position));
}

private void backendApiCall() {
Gson gson = new GsonBuilder()
.setLenient()
.create();

Retrofit retrofit = new Retrofit.Builder()
.baseUrl(Utils.BASE_URL)
.addConverterFactory(GsonConverterFactory.create(gson))
.build();

RestaurantData gerritAPI = retrofit.create(RestaurantData.class);

Call<List<RestaurantsModel>> call = gerritAPI.getRestaurantsData();
call.enqueue(this);
}

@Override
public void onResponse(Call<List<RestaurantsModel>> call, Response<List<RestaurantsModel>> response) {
if(response.isSuccessful()) {

List<RestaurantsModel> restaurantsList = response.body();

if(restaurantsList != null && restaurantsList.size() > 0) {
//Sort list items into alphabetical order..
Collections.sort(restaurantsList, new Comparator<RestaurantsModel>() {
@Override
public int compare(RestaurantsModel modelObj1, RestaurantsModel modelObj2) {
String s1 = modelObj1.getName();
String s2 = modelObj2.getName();
return s1.compareToIgnoreCase(s2);
}

});

//Create Bundle with Restaurant list...
Bundle bundle = new Bundle();
// putting questions list into the bundle .. as key value pair.
// so you can retrieve the arrayList with this key
bundle.putSerializable(Utils.RESTAURANT_LIST_KEY, (Serializable) restaurantsList);

mTabAdapter = new TabAdapter(getSupportFragmentManager(), this, bundle);
mTabAdapter.addFragment(new RestaurantTabFragment(), getResources().getString(R.string.tab1_text), tabIcons[0]);
mTabAdapter.addFragment(new MapTabFragment(), getResources().getString(R.string.tab2_text), tabIcons[1]);

mViewPager.setAdapter(mTabAdapter);
mTabLayout.setupWithViewPager(mViewPager);
highLightCurrentTab(0);
}
} else {
Log.e("MainActivity","error response " + response.errorBody());
}
}

@Override
public void onFailure(Call<List<RestaurantsModel>> call, Throwable t) {
Log.e("MainActivity","Failure in response " );
t.printStackTrace();
}
}

RestaurantData.java
import com.example.cbrecodingtest.model.RestaurantsModel;
import java.util.List;
import retrofit2.Call;
import retrofit2.http.GET;
public interface RestaurantData {
@GET("restaurants/")
Call<List<RestaurantsModel>> getRestaurantsData();
}

RestaurantsModel.java
import java.io.Serializable;
public class RestaurantsModel implements Serializable {
/**
* "name": "Liberty Burger",
"postalCode": "75214",
"phoneNumber": "(214) 887-9999",
"state": "Texas",
"id": "b75862f1-d28a-11e9-b5c9-0a389e6da5d4",
"websiteUrl": "https://www.givemelibertyburger.com",
"description": "Local chain outpost supplying high-end burgers plus salads & sides in spare but stylish digs.",
"category": "Burgers",
"city": "Dallas",
"longitude": -96.752351,
"goodFor": "Comfort food,Outdoor seating,Quick bite",
"latitude": 32.813099,
"closeTime": "9PM",
"streetAddress": "1904 Abrams Pkwy",
"openTime": "11AM",
"imageUrl": "https://dallas-restaurants.s3.us-east-2.amazonaws.com/fd7b13a2-ce94-11e9-a32f-2a2ae2dbcce4.jpg"
*/
String name;
String postalCode;
String phoneNumber ;
String state;
String id;
String websiteUrl;
String description;
String category;
String city;
Double longitude;
String goodFor;
Double latitude;
String closeTime;
String streetAddress;
String openTime;
String imageUrl;

public RestaurantsModel(String name, String postalCode, String phoneNumber, String state, String id, String websiteUrl,
String description, String category, String city, Double longitude, String goodFor, Double latitude, String closeTime,
String streetAddress, String openTime, String imageUrl) {
this.name = name;
this.postalCode = postalCode;
this.phoneNumber = phoneNumber;
this.state = state;
this.id = id;
this.websiteUrl = websiteUrl;
this.description = description;
this.category = category;
this.city = city;
this.longitude = longitude;
this.goodFor = goodFor;
this.latitude = latitude;
this.closeTime = closeTime;
this.streetAddress = streetAddress;
this.openTime = openTime;
this.imageUrl = imageUrl;
}

public String getName() {
return name;
}

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

public String getPostalCode() {
return postalCode;
}

public void setPostalCode(String postalCode) {
this.postalCode = postalCode;
}

public String getPhoneNumber() {
return phoneNumber;
}

public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}

public String getState() {
return state;
}

public void setState(String state) {
this.state = state;
}

public String getId() {
return id;
}

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

public String getWebsiteUrl() {
return websiteUrl;
}

public void setWebsiteUrl(String websiteUrl) {
this.websiteUrl = websiteUrl;
}

public String getDescription() {
return description;
}

public void setDescription(String description) {
this.description = description;
}

public String getCategory() {
return category;
}

public void setCategory(String category) {
this.category = category;
}

public String getCity() {
return city;
}

public void setCity(String city) {
this.city = city;
}

public Double getLongitude() {
return longitude;
}

public void setLongitude(Double longitude) {
this.longitude = longitude;
}

public String getGoodFor() {
return goodFor;
}

public void setGoodFor(String goodFor) {
this.goodFor = goodFor;
}

public Double getLatitude() {
return latitude;
}

public void setLatitude(Double latitude) {
this.latitude = latitude;
}

public String getCloseTime() {
return closeTime;
}

public void setCloseTime(String closeTime) {
this.closeTime = closeTime;
}

public String getStreetAddress() {
return streetAddress;
}

public void setStreetAddress(String streetAddress) {
this.streetAddress = streetAddress;
}

public String getOpenTime() {
return openTime;
}

public void setOpenTime(String openTime) {
this.openTime = openTime;
}

public String getImageUrl() {
return imageUrl;
}

public void setImageUrl(String imageUrl) {
this.imageUrl = imageUrl;
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include
android:layout_width="match_parent"
android:layout_height="wrap_content"
layout="@layout/app_bar"
android:layout_alignParentTop="true"/>
<androidx.viewpager.widget.ViewPager
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@+id/tabLayout"
android:layout_below="@+id/toolbar"/>
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="90dp"
app:tabGravity="fill"
app:tabIndicatorColor="@color/white"
app:tabIndicatorHeight="4dp"
app:tabBackground="@color/tab_background"
android:layout_alignParentBottom="true" />
</RelativeLayout>
</androidx.constraintlayout.widget.ConstraintLayout>



Implement RecyclerView using constraintlayout in Android


RestaurantTabFragment.java :
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.example.cbrecodingtest.R;
import com.example.cbrecodingtest.adapter.RestaurantsAdapter;
import com.example.cbrecodingtest.model.RestaurantsModel;
import com.example.cbrecodingtest.utils.Utils;

import java.util.ArrayList;

public class RestaurantTabFragment extends Fragment {

private RecyclerView mRecyclerView;
RecyclerView.LayoutManager mLayoutManager;
private RecyclerView.Adapter mRecyclerAdapter;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

ArrayList<RestaurantsModel> restaurantsList = (ArrayList<RestaurantsModel>) getArguments().getSerializable(Utils.RESTAURANT_LIST_KEY);
mRecyclerAdapter = new RestaurantsAdapter(restaurantsList, getActivity());

View rootView = inflater.inflate(R.layout.restaurant_tab_fragment, container, false);
mLayoutManager = new LinearLayoutManager(getActivity());
mRecyclerView = rootView.findViewById(R.id.recycler_view);
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.setAdapter(mRecyclerAdapter);

return rootView;
}
}

restaurant_tab_fragment.xml :
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/restTabView">
<!-- A RecyclerView with some commonly used attributes -->
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>


RestaurantsAdapter.java :
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
import androidx.recyclerview.widget.RecyclerView;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;


import com.example.cbrecodingtest.R;
import com.example.cbrecodingtest.model.RestaurantsModel;
import com.example.cbrecodingtest.utils.Utils;
import com.example.cbrecodingtest.view.RestaurantDetailsScreen;
import com.squareup.picasso.Picasso;

import java.util.ArrayList;

public class RestaurantsAdapter extends RecyclerView.Adapter<RestaurantsAdapter.ViewHolder> {

private ArrayList<RestaurantsModel> mRestaurantList;
private Context context;

public RestaurantsAdapter(ArrayList<RestaurantsModel> mRestaurantList, Context context) {
this.mRestaurantList = mRestaurantList;
this.context = context;
}

@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.restaurant_row, parent, false);

return new ViewHolder(v);
}

@Override
public void onBindViewHolder(ViewHolder holder, final int position) {
RestaurantsModel restaurantsModel = mRestaurantList.get(position);

holder.restName.setText(restaurantsModel.getName());
holder.restCategory.setText(restaurantsModel.getCategory());
holder.restGoodFor.setText(restaurantsModel.getGoodFor());

String openTime = restaurantsModel.getOpenTime();
String closeTime = restaurantsModel.getCloseTime();
if(Utils.isRestaurantOpen(openTime , closeTime)) {
holder.restOpenClose.setText("Open until "+closeTime);
holder.restOpenClose.setTextColor(context.getResources().getColor(R.color.green));
} else {
holder.restOpenClose.setText("Closed until tomorrow at "+openTime);
holder.restOpenClose.setTextColor(context.getResources().getColor(R.color.red));
}

Picasso.get().load(restaurantsModel.getImageUrl()).into(holder.imageDataView);

holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//listener for row click

/*FragmentTransaction ft = ((FragmentActivity)context).getSupportFragmentManager().beginTransaction();
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
RestaurantDetailsScreen fragment2 = new RestaurantDetailsScreen();

Bundle bundle = new Bundle();
bundle.putSerializable(Utils.RESTAURANT_KEY , mRestaurantList.get(position));
fragment2.setArguments(bundle);
ft.replace(android.R.id.content, fragment2);
//ft.addToBackStack(null);
ft.commit();*/


RestaurantDetailsScreen fragment2 = new RestaurantDetailsScreen();
FragmentTransaction ft = ((FragmentActivity)context).getSupportFragmentManager().beginTransaction();
Bundle bundle = new Bundle();
bundle.putSerializable(Utils.RESTAURANT_KEY , mRestaurantList.get(position));
fragment2.setArguments(bundle);
ft.replace(R.id.restTabView, fragment2);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.addToBackStack(null);
ft.commit();
}
});
}

@Override
public int getItemCount() {
if (mRestaurantList != null) {
return mRestaurantList.size();
} else {
return 0;
}
}

public static class ViewHolder extends RecyclerView.ViewHolder {
public final View view;
public final TextView restName;
public final TextView restCategory;
public final TextView restGoodFor;
public final TextView restOpenClose;
public final ImageView imageDataView;

public ViewHolder(View view) {
super(view);
this.view = view;
restName = view.findViewById(R.id.restName);
restCategory = view.findViewById(R.id.restCategory);
restGoodFor = view.findViewById(R.id.restGoodFor);
restOpenClose = view.findViewById(R.id.restOpenClose);
imageDataView = view.findViewById(R.id.mImageView);
}
}
}

restaurant_row.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/mViewRoot"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
android:clickable="true"
android:focusable="true">
<ImageView
android:id="@+id/mImageView"
android:layout_width="120dp"
android:layout_height="90dp"
android:src="@mipmap/ic_launcher"
android:scaleType="fitCenter"
android:adjustViewBounds="true"
android:layout_margin="6dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:visibility="visible" />
<TextView
android:id="@+id/restName"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="restName"
android:textAppearance="@style/TextAppearance.AppCompat.Headline"
android:textSize="@dimen/nameTextSize"
android:textStyle="bold"
android:layout_marginLeft="4dp"
app:layout_constraintBottom_toBottomOf="@+id/mImageView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/mImageView"
app:layout_constraintTop_toTopOf="@+id/mImageView"
app:layout_constraintVertical_bias="0.0" />
<TextView
android:id="@+id/restCategory"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textSize="@dimen/categoryTextSize"
android:textColor="@color/category"
android:text="restState "
app:layout_constraintLeft_toLeftOf="@+id/restName"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/restName" />
<TextView
android:id="@+id/restGoodFor"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textSize="@dimen/goodForTextSize"
android:textColor="@color/category"
android:text="restGoodFor"
app:layout_constraintLeft_toLeftOf="@+id/restCategory"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/restCategory" />
<TextView
android:id="@+id/restOpenClose"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textSize="@dimen/openCloseTextSize"
android:text="restOpenClose "
app:layout_constraintLeft_toLeftOf="@+id/restGoodFor"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/restGoodFor" />
<View
android:id="@+id/lineView"
android:layout_width="match_parent"
android:layout_height="3dp"
android:background="@color/black"
android:layout_marginTop="6dp"
app:layout_constraintLeft_toLeftOf="@+id/mImageView"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/mImageView" />
</androidx.constraintlayout.widget.ConstraintLayout>


Could not identify launch activity: Default activity not found : Error while Launching activity

Problem : I got this Error , When I tried to create an application without any Activity . Basically like to develop an Android Headless appl...