diff --git a/AndroidBase/.gitignore b/AndroidBase/.gitignore new file mode 100644 index 0000000..5edb4ee --- /dev/null +++ b/AndroidBase/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +.DS_Store +/build +/captures +.externalNativeBuild diff --git a/AndroidBase/.idea/caches/build_file_checksums.ser b/AndroidBase/.idea/caches/build_file_checksums.ser new file mode 100644 index 0000000..864bfc8 Binary files /dev/null and b/AndroidBase/.idea/caches/build_file_checksums.ser differ diff --git a/AndroidBase/.idea/codeStyles/Project.xml b/AndroidBase/.idea/codeStyles/Project.xml new file mode 100644 index 0000000..30aa626 --- /dev/null +++ b/AndroidBase/.idea/codeStyles/Project.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/AndroidBase/.idea/dictionaries/ams.xml b/AndroidBase/.idea/dictionaries/ams.xml new file mode 100644 index 0000000..5b26dae --- /dev/null +++ b/AndroidBase/.idea/dictionaries/ams.xml @@ -0,0 +1,7 @@ + + + + gson + + + \ No newline at end of file diff --git a/AndroidBase/.idea/gradle.xml b/AndroidBase/.idea/gradle.xml new file mode 100644 index 0000000..b6752e1 --- /dev/null +++ b/AndroidBase/.idea/gradle.xml @@ -0,0 +1,20 @@ + + + + + + \ No newline at end of file diff --git a/AndroidBase/.idea/misc.xml b/AndroidBase/.idea/misc.xml new file mode 100644 index 0000000..99202cc --- /dev/null +++ b/AndroidBase/.idea/misc.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/AndroidBase/.idea/runConfigurations.xml b/AndroidBase/.idea/runConfigurations.xml new file mode 100644 index 0000000..7f68460 --- /dev/null +++ b/AndroidBase/.idea/runConfigurations.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/AndroidBase/androidBase/.gitignore b/AndroidBase/androidBase/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/AndroidBase/androidBase/.gitignore @@ -0,0 +1 @@ +/build diff --git a/AndroidBase/androidBase/build.gradle b/AndroidBase/androidBase/build.gradle new file mode 100644 index 0000000..1009779 --- /dev/null +++ b/AndroidBase/androidBase/build.gradle @@ -0,0 +1,50 @@ +apply plugin: 'com.android.library' + +android { + compileSdkVersion 28 + + + + defaultConfig { + minSdkVersion 22 + targetSdkVersion 28 + versionCode 1 + versionName "1.0" + + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } + + sourceSets { main { res.srcDirs = ['src/main/res', 'src/main/res/layout'] } } +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation 'com.android.support:appcompat-v7:28.0.0' + testImplementation 'junit:junit:4.12' + androidTestImplementation 'com.android.support.test:runner:1.0.2' + androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' + implementation 'com.jakewharton:butterknife:10.0.0' + annotationProcessor 'com.jakewharton:butterknife-compiler:10.0.0' + implementation 'io.reactivex.rxjava2:rxandroid:2.1.0' + implementation 'com.google.code.gson:gson:2.8.5' + implementation 'android.arch.persistence.room:runtime:1.1.1' + annotationProcessor 'android.arch.persistence.room:compiler:1.1.1' + implementation 'com.android.support:recyclerview-v7:28.0.0' + implementation "com.github.skydoves:preferenceroom:1.1.3" + annotationProcessor "com.github.skydoves:preferenceroom-processor:1.1.3" + implementation 'frankiesardo:icepick:3.2.0' + compileOnly 'frankiesardo:icepick-processor:3.2.0' + implementation 'com.squareup.retrofit2:retrofit:2.5.0' + implementation 'com.squareup.retrofit2:adapter-rxjava2:2.5.0' + implementation 'it.sephiroth.android.library.imagezoom:imagezoom:+' + implementation 'org.parceler:parceler-api:1.1.12' + annotationProcessor 'org.parceler:parceler:1.1.12' +} diff --git a/AndroidBase/androidBase/proguard-rules.pro b/AndroidBase/androidBase/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/AndroidBase/androidBase/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# 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/AndroidBase/androidBase/src/androidTest/java/ams/android_base/ExampleInstrumentedTest.java b/AndroidBase/androidBase/src/androidTest/java/ams/android_base/ExampleInstrumentedTest.java new file mode 100644 index 0000000..77e3cb1 --- /dev/null +++ b/AndroidBase/androidBase/src/androidTest/java/ams/android_base/ExampleInstrumentedTest.java @@ -0,0 +1,26 @@ +package ams.android_base; + +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.*; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getTargetContext(); + + assertEquals("ams.android_base.test", appContext.getPackageName()); + } +} diff --git a/AndroidBase/androidBase/src/main/AndroidManifest.xml b/AndroidBase/androidBase/src/main/AndroidManifest.xml new file mode 100644 index 0000000..c9ebd39 --- /dev/null +++ b/AndroidBase/androidBase/src/main/AndroidManifest.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + diff --git a/AndroidBase/androidBase/src/main/java/ams/android_base/BaseAPIsConnector.java b/AndroidBase/androidBase/src/main/java/ams/android_base/BaseAPIsConnector.java new file mode 100644 index 0000000..b263ce8 --- /dev/null +++ b/AndroidBase/androidBase/src/main/java/ams/android_base/BaseAPIsConnector.java @@ -0,0 +1,44 @@ +package ams.android_base; + + +import java.util.concurrent.TimeUnit; + +import okhttp3.OkHttpClient; +import retrofit2.Converter; +import retrofit2.Retrofit; +import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory; + +@SuppressWarnings({"WeakerAccess", "unused"}) +public abstract class BaseAPIsConnector { + + private static Retrofit retrofit; + + protected OkHttpClient.Builder getOkHttpBuilder() { + int timeOut = 200; + return new OkHttpClient.Builder() + .connectTimeout(timeOut, TimeUnit.SECONDS) + .writeTimeout(timeOut, TimeUnit.SECONDS) + .readTimeout(timeOut, TimeUnit.SECONDS); + } + + protected Retrofit.Builder getRetrofitBuilder() { + return new Retrofit.Builder() + .baseUrl(getBaseURL()) + .addConverterFactory(getConverterFactory()) + .client(getOkHttpBuilder().build()) + .addCallAdapterFactory(RxJava2CallAdapterFactory.create()); + } + + protected final void buildRetrofit () { if (retrofit == null) retrofit = getRetrofitBuilder().build(); } + + protected Retrofit getRetrofit () { return retrofit; } + + protected APIsInterface getRetrofitClient(Class restAPIsInterface) { + buildRetrofit(); + return retrofit.create(restAPIsInterface); + } + + protected abstract String getBaseURL (); + protected abstract Converter.Factory getConverterFactory (); + +} diff --git a/AndroidBase/androidBase/src/main/java/ams/android_base/ZoomImageActivity.java b/AndroidBase/androidBase/src/main/java/ams/android_base/ZoomImageActivity.java new file mode 100755 index 0000000..9cf47ab --- /dev/null +++ b/AndroidBase/androidBase/src/main/java/ams/android_base/ZoomImageActivity.java @@ -0,0 +1,49 @@ +package ams.android_base; + +import android.content.Intent; +import android.graphics.Bitmap; +import android.os.Bundle; +import android.support.v7.app.AppCompatActivity; +import android.view.WindowManager; + +import it.sephiroth.android.library.imagezoom.ImageViewTouch; + +public abstract class ZoomImageActivity extends AppCompatActivity { + + protected ImageViewTouch imageView; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + initView(); + renderImageView(); + } + + private void initView() { + setContentView(R.layout.activity_zoom_image); + if(getSupportActionBar() != null) getSupportActionBar().hide(); + // Remove activity title + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + //noinspection deprecation,RedundantCast + imageView = (ImageViewTouch) findViewById(R.id.imageView); + } + + protected abstract void renderImageView (); + + @Override + public void onBackPressed() { + super.onBackPressed(); + this.finish(); + } + + + // This is how to send image to view/zoom image page + // Bitmap will be cached for 10 seconds only +// public void sendImageToViewPage (Bitmap bitmap) { +// new CacheManger(this).cacheBitmapTemporary(GlobalKeys.TEMP_BITMAP, bitmap, 10); +// Intent intent = new Intent(this, ZoomImageActivity.class); +// startActivity(intent); +// } + +} diff --git a/AndroidBase/androidBase/src/main/java/ams/android_base/baseClasses/BasePage.java b/AndroidBase/androidBase/src/main/java/ams/android_base/baseClasses/BasePage.java new file mode 100644 index 0000000..6aafb74 --- /dev/null +++ b/AndroidBase/androidBase/src/main/java/ams/android_base/baseClasses/BasePage.java @@ -0,0 +1,32 @@ +package ams.android_base.baseClasses; + +@SuppressWarnings("WeakerAccess") +public class BasePage { + + private int itemsCount; + private int itemsPerPage = 20; + private int pageNumber = 1; + + public void setItemsCount(int itemsCount) { this.itemsCount = itemsCount; } + + public int getItemsPerPage() { return itemsPerPage; } + + public int getPageNumber() { return pageNumber; } + + + // Helper methods + public void resetPageCount () { this.pageNumber = 1; } + + public void incrementPageNumber () { this.pageNumber ++; } + + public int getTotalNumberOfPages() { + float tempItemsCount = itemsCount; + float tempItemsPerPage = itemsPerPage; + return (int) (Math.ceil(tempItemsCount/tempItemsPerPage)); + } + + public boolean hasNext() { return pageNumber <= getTotalNumberOfPages(); } + + public void resetPage () { resetPageCount(); } + +} \ No newline at end of file diff --git a/AndroidBase/androidBase/src/main/java/ams/android_base/baseClasses/globalKeys/BaseDateAndTimeFormats.java b/AndroidBase/androidBase/src/main/java/ams/android_base/baseClasses/globalKeys/BaseDateAndTimeFormats.java new file mode 100755 index 0000000..8b5efb3 --- /dev/null +++ b/AndroidBase/androidBase/src/main/java/ams/android_base/baseClasses/globalKeys/BaseDateAndTimeFormats.java @@ -0,0 +1,35 @@ +package ams.android_base.baseClasses.globalKeys; + +/** + * Created by Ahmad Mahmoud on 22-Feb-18. + */ + +// Ref : https://stackoverflow.com/questions/5369682/get-current-time-and-date-on-android + +public class BaseDateAndTimeFormats { + + // Day + public static final String DAY = "dd"; + // Month + public static final String MONTH_NUMBER = "MM"; + public static final String MONTH_ABBREVIATION = "MMM"; + public static final String MONTH_NAME = "MMMM"; + // Year + public static final String YEAR = "YY"; + public static final String YEAR_NUMBER = "YYYY"; + // Hours + public static final String _12HOURS = "hh"; + public static final String _24HOURS = "HH"; + // Minuets + public static final String MINUTES = "mm"; + // Seconds + public static final String SECONDS = "ss"; + // AM/PM + public static final String AM_PM = "a"; + // Full formats + // Time + public static final String _12Hours_FORMAT = "hh:mm:ss aa"; + public static final String _24Hours_FORMAT = "HH:mm:ss"; + // Date & time + public static final String DATE_AND_TIME = "hh:mm:ss a dd/MM/yyyy"; +} diff --git a/AndroidBase/androidBase/src/main/java/ams/android_base/baseClasses/globalKeys/BasePatterns.java b/AndroidBase/androidBase/src/main/java/ams/android_base/baseClasses/globalKeys/BasePatterns.java new file mode 100755 index 0000000..222761e --- /dev/null +++ b/AndroidBase/androidBase/src/main/java/ams/android_base/baseClasses/globalKeys/BasePatterns.java @@ -0,0 +1,27 @@ +package ams.android_base.baseClasses.globalKeys; + +/** + * Created by Ahmad on 23-Nov-16. + */ + +@SuppressWarnings({"unused", "DefaultFileTemplate"}) +public class BasePatterns { + + // Must match + public static final String EMAIL_PATTERN = "^[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*@ [A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$"; + // Must not match + public static final String SPECIAL_CHARACTERS_PATTERN = "[!#$%^&*()-+=\\/;:\"',> extends AppCompatActivity implements BaseViewDelegator { + + private Presenter presenter; + private Unbinder butterKnifeUnBinder; + + @CallSuper + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(getLayout()); + bindActivityViews(); + presenter = initPresenter(); + } + + protected void bindActivityViews () { butterKnifeUnBinder = ButterKnife.bind(this); } + + @CallSuper + @Override + protected void onDestroy() { + super.onDestroy(); + unBind(); + } + + protected final void unBind() { if (butterKnifeUnBinder != null) butterKnifeUnBinder.unbind(); } + + protected abstract + @LayoutRes + int getLayout(); + + protected abstract Presenter initPresenter(); + + public final Presenter getPresenter() { return presenter; } + + @Override + public void showLoading() { } + + @Override + public void hideLoading() { } + +} diff --git a/AndroidBase/androidBase/src/main/java/ams/android_base/baseClasses/mvp/BaseFragment.java b/AndroidBase/androidBase/src/main/java/ams/android_base/baseClasses/mvp/BaseFragment.java new file mode 100644 index 0000000..7b6a8c0 --- /dev/null +++ b/AndroidBase/androidBase/src/main/java/ams/android_base/baseClasses/mvp/BaseFragment.java @@ -0,0 +1,66 @@ +package ams.android_base.baseClasses.mvp; + +import android.os.Bundle; +import android.support.annotation.CallSuper; +import android.support.annotation.LayoutRes; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import butterknife.ButterKnife; +import butterknife.Unbinder; + +public abstract class BaseFragment extends Fragment implements BaseViewDelegator { + + private Presenter presenter; + private Unbinder butterKnifeUnBinder; + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + return inflater.inflate(getLayout(), container, false); + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + bindFragmentViews(this, view); + presenter = initPresenter(); + } + + + @CallSuper + @Override + public void onDestroy() { + super.onDestroy(); + unBind(); + } + + protected void bindFragmentViews (Fragment fragment, View view) { + butterKnifeUnBinder = ButterKnife.bind(fragment, view); + } + + protected final void unBind() { + if (butterKnifeUnBinder != null) + butterKnifeUnBinder.unbind(); + } + + protected abstract + @LayoutRes + int getLayout(); + + protected abstract + Presenter initPresenter(); + + public final Presenter getPresenter() { return presenter; } + + @Override + public void showLoading() {} + + @Override + public void hideLoading() {} + +} diff --git a/AndroidBase/androidBase/src/main/java/ams/android_base/baseClasses/mvp/BasePresenter.java b/AndroidBase/androidBase/src/main/java/ams/android_base/baseClasses/mvp/BasePresenter.java new file mode 100644 index 0000000..0290c19 --- /dev/null +++ b/AndroidBase/androidBase/src/main/java/ams/android_base/baseClasses/mvp/BasePresenter.java @@ -0,0 +1,13 @@ +package ams.android_base.baseClasses.mvp; + +import android.support.annotation.NonNull; + +public class BasePresenter { + + private ViewDelegator viewDelegator; + + public BasePresenter (@NonNull ViewDelegator viewDelegator) { this.viewDelegator = viewDelegator; } + + protected ViewDelegator getViewDelegator() { return viewDelegator; } + +} diff --git a/AndroidBase/androidBase/src/main/java/ams/android_base/baseClasses/mvp/BaseViewDelegator.java b/AndroidBase/androidBase/src/main/java/ams/android_base/baseClasses/mvp/BaseViewDelegator.java new file mode 100644 index 0000000..a806f04 --- /dev/null +++ b/AndroidBase/androidBase/src/main/java/ams/android_base/baseClasses/mvp/BaseViewDelegator.java @@ -0,0 +1,9 @@ +package ams.android_base.baseClasses.mvp; + +public interface BaseViewDelegator { + public void showLoading(); + public void hideLoading(); + public void onGoOnline(); + public void onGoOffline(); + public void onLogOut(); +} diff --git a/AndroidBase/androidBase/src/main/java/ams/android_base/baseClasses/mvp/BaseWidget.java b/AndroidBase/androidBase/src/main/java/ams/android_base/baseClasses/mvp/BaseWidget.java new file mode 100755 index 0000000..aa19cab --- /dev/null +++ b/AndroidBase/androidBase/src/main/java/ams/android_base/baseClasses/mvp/BaseWidget.java @@ -0,0 +1,107 @@ +package ams.android_base.baseClasses.mvp; + +import android.app.PendingIntent; +import android.appwidget.AppWidgetManager; +import android.appwidget.AppWidgetProvider; +import android.appwidget.AppWidgetProviderInfo; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.support.annotation.LayoutRes; +import android.widget.RemoteViews; + +import java.util.Random; + + +public abstract class BaseWidget extends AppWidgetProvider implements BaseViewDelegator { + + private Presenter presenter; + + @Override + public void onAppWidgetOptionsChanged(Context context, AppWidgetManager appWidgetManager, int appWidgetId, Bundle newOptions) { + super.onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, newOptions); + } + + @Override + public void onEnabled(Context context) { + super.onEnabled(context); + } + + @Override + public void onDisabled(Context context) { + super.onDisabled(context); + } + + @Override + public void onDeleted(Context context, int[] appWidgetIds) { super.onDeleted(context, appWidgetIds); } + + @Override + public void onRestored(Context context, int[] oldWidgetIds, int[] newWidgetIds) { super.onRestored(context, oldWidgetIds, newWidgetIds); } + + @Override + public void onReceive(Context context, Intent intent) { + super.onReceive(context, intent); + } + + @Override + public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { + final int widgetCount = appWidgetIds.length; + /* + In the onUpdate() method we iterate through all our widgets (In case the user has placed multiple widgets) + to get RemoteViews object then update the RemoteView’s (widget_normal_layout's) textview with a new random number + between 100 and 999 then specify the action that should occur when the Button is tapped. + // + To request a manual update when the update button is clicked, we use a PendingIntent. + The action for the Intent is set to AppWidgetManager.ACTION_APPWIDGET_UPDATE. + This is the same action sent by the system when the widget_normal_layout needs to be updated automatically. + We also indicate the widgets that should be updated (all of the app widgets) by calling : + intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds). + To update the current widget_normal_layout only you can call : + intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId); + Finally we request the AppWidgetManager object to update the app widget_normal_layout + giving it the current widgetId and the current RemoteViews object. + */ + for (int widgetLayoutId : appWidgetIds) { + /* + If your widget is displayed on a lock screen, + you might want to show different data, or a different layout. + To detect if the widget is on a lock screen you request the widget options + using appWidgetManager.getAppWidgetOptions(int widgetId), This method returns a bundle + which we can get options category (as int), + This will either be a WIDGET_CATEGORY_HOME_SCREEN or WIDGET_CATEGORY_KEYGUARD (Lock screen). + You can provide a different layout based on the result. + */ + // + Bundle widgetOptions = appWidgetManager.getAppWidgetOptions(widgetLayoutId); + // Get the value of OPTION_APPWIDGET_HOST_CATEGORY + int category = widgetOptions.getInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY, -1); + // If the value is WIDGET_CATEGORY_KEYGUARD, it's a lockscreen widget_normal_layout + boolean isKeyguard = category == AppWidgetProviderInfo.WIDGET_CATEGORY_KEYGUARD; + int baseLayout = isKeyguard ? getLockScreenLayout() : getLayout(); + // + String number = String.format("%03d", (new Random().nextInt(900) + 100)); +// RemoteViews remoteViews = new RemoteViews(context.getPackageName(), +// R.layout.widget_normal_layout); + updateWidget(context, appWidgetManager, widgetLayoutId, number); + } + } + + protected abstract void updateWidget(Context context, AppWidgetManager widgetLayoutId, int widgetId, String str); + + protected final RemoteViews getWidgetRemoteViews (Context context, int widgetLayoutId) { + return new RemoteViews(context.getPackageName(), widgetLayoutId); + } + + protected abstract Presenter initPresenter(); + + public final Presenter getPresenter() { return presenter; } + + protected abstract + @LayoutRes + int getLayout(); + + protected abstract + @LayoutRes + int getLockScreenLayout(); + +} diff --git a/AndroidBase/androidBase/src/main/java/ams/android_base/baseClasses/recyclerView/BaseRecyclerAdapter.java b/AndroidBase/androidBase/src/main/java/ams/android_base/baseClasses/recyclerView/BaseRecyclerAdapter.java new file mode 100644 index 0000000..6fb8e89 --- /dev/null +++ b/AndroidBase/androidBase/src/main/java/ams/android_base/baseClasses/recyclerView/BaseRecyclerAdapter.java @@ -0,0 +1,229 @@ +package ams.android_base.baseClasses.recyclerView; + +import android.content.Context; +import android.support.annotation.LayoutRes; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import java.util.ArrayList; +import java.util.List; + +/** + * Base generic RecyclerView adapter. + * Handles basic logic such as adding/removing items, + * setting listener, binding ViewHolders. + * Extend the adapter for appropriate use case. + * + * @param type of objects, which will be used in the adapter's dataset + * @param click listener {@link BaseRecyclerViewListener} + * @param ViewHolder {@link BaseRecyclerViewHolder} + */ +@SuppressWarnings("unused") +public abstract class BaseRecyclerAdapter> extends RecyclerView.Adapter { + + private List items; + private L listener; + private LayoutInflater layoutInflater; + + /** + * Base constructor. + * Allocate adapter-related objects here if needed. + * + * @param context Context needed to retrieve LayoutInflater + */ + public BaseRecyclerAdapter(Context context) { + layoutInflater = LayoutInflater.from(context); + items = new ArrayList<>(); + } + + /** + * To be implemented in as specific adapter + * + * @param parent The ViewGroup into which the new View will be added after it is bound to an adapter position. + * @param viewType The view type of the new View. + * @return A new ViewHolder that holds a View of the given view type. + */ + @NonNull + @Override + public abstract VH onCreateViewHolder(@NonNull ViewGroup parent, int viewType); + + /** + * Called by RecyclerView to display the data at the specified position. This method should + * update the contents of the itemView to reflect the item at the given + * position. + * + * @param holder The ViewHolder which should be updated to represent the contents of the + * item at the given position in the data set. + * @param position The position of the item within the adapter's data set. + */ + @Override + public void onBindViewHolder(@NonNull VH holder, int position) { + T item = items.get(position); + holder.onBind(item, listener); + } + + /** + * Returns the total number of items in the data set held by the adapter. + * + * @return The total number of items in this adapter. + */ + @Override + public int getItemCount() { + return items != null ? items.size() : 0; + } + + /** + * Sets items to the adapter and notifies that data set has been changed. + * + * @param items items to set to the adapter + * @throws IllegalArgumentException in case of setting `null` items + */ + public void setItems(List items) { + if (items == null) { + throw new IllegalArgumentException("Cannot set `null` item to the Recycler adapter"); + } + this.items.clear(); + this.items.addAll(items); + notifyDataSetChanged(); + } + + /** + * Returns getAllMatches items from the data set held by the adapter. + * + * @return All of items in this adapter. + */ + public List getItems() { + return items; + } + + /** + * Returns an items from the data set at a certain position. + * + * @return All of items in this adapter. + */ + public T getItem(int position) { + return items.get(position); + } + + /** + * Adds item to the end of the data set. + * Notifies that item has been inserted. + * + * @param item item which has to be added to the adapter. + */ + public void add(T item) { + if (item == null) { + throw new IllegalArgumentException("Cannot add null item to the Recycler adapter"); + } + items.add(item); + notifyItemInserted(items.size() - 1); + } + + /** + * Adds list of items to the end of the adapter's data set. + * Notifies that item has been inserted. + * + * @param items items which has to be added to the adapter. + */ + public void addAll(List items) { + if (items == null) { + throw new IllegalArgumentException("Cannot add `null` items to the Recycler adapter"); + } + this.items.addAll(items); + notifyItemRangeInserted(this.items.size() - items.size(), items.size()); + } + + /** + * Clears getAllMatches the items in the adapter. + */ + public void clear() { + items.clear(); + notifyDataSetChanged(); + } + + /** + * Removes an item from the adapter. + * Notifies that item has been removed. + * + * @param item to be removed + */ + public void remove(T item) { + int position = items.indexOf(item); + if (position > -1) { + items.remove(position); + notifyItemRemoved(position); + } + } + + /** + * Returns whether adapter is empty or not. + * + * @return `true` if adapter is empty or `false` otherwise + */ + public boolean isEmpty() { + return getItemCount() == 0; + } + + /** + * Indicates whether each item in the data set can be represented with a unique identifier + * of type {@link Long}. + * + * @param hasStableIds Whether items in data set have unique identifiers or not. + * @see #hasStableIds() + * @see #getItemId(int) + */ + @Override + public void setHasStableIds(boolean hasStableIds) { + super.setHasStableIds(hasStableIds); + } + + + /** + * Set click listener, which must extend {@link BaseRecyclerViewListener} + * + * @param listener click listener + */ + public void setListener(L listener) { + this.listener = listener; + } + + /** + * Inflates a view. + * + * @param layout layout to me inflater + * @param parent container where to inflate + * @param attachToRoot whether to attach to root or not + * @return inflated View + */ + @SuppressWarnings("WeakerAccess") + @NonNull + protected View inflate(@LayoutRes final int layout, @Nullable final ViewGroup parent, @SuppressWarnings("SameParameterValue") final boolean attachToRoot) { + return layoutInflater.inflate(layout, parent, attachToRoot); + } + + /** + * Inflates a view. + * + * @param layout layout to me inflater + * @param parent container where to inflate + * @return inflated View + */ + @NonNull + protected View inflate(@LayoutRes final int layout, final @Nullable ViewGroup parent) { + return inflate(layout, parent, false); + } + + public interface OnRecyclerObjectClickViewListener extends BaseRecyclerViewListener { + /** + * Item has been clicked. + * + * @param item object associated with the clicked item. + */ + void onItemClicked(T item); + } + +} diff --git a/AndroidBase/androidBase/src/main/java/ams/android_base/baseClasses/recyclerView/BaseRecyclerViewHolder.java b/AndroidBase/androidBase/src/main/java/ams/android_base/baseClasses/recyclerView/BaseRecyclerViewHolder.java new file mode 100644 index 0000000..bfb8cac --- /dev/null +++ b/AndroidBase/androidBase/src/main/java/ams/android_base/baseClasses/recyclerView/BaseRecyclerViewHolder.java @@ -0,0 +1,27 @@ +package ams.android_base.baseClasses.recyclerView; + +import android.support.annotation.Nullable; +import android.support.v7.widget.RecyclerView; +import android.view.View; + +import butterknife.ButterKnife; + +public abstract class BaseRecyclerViewHolder extends RecyclerView.ViewHolder { + + public BaseRecyclerViewHolder(View view) { + super(view); + bindViews(view); + } + + @SuppressWarnings("WeakerAccess") + protected void bindViews(View view) { ButterKnife.bind(this, view); } + + /** + * Bind data to the item and set listener if needed. + * + * @param item object, associated with the item. + * @param listener listener a listener {@link BaseRecyclerViewListener} which has to b set at the item (if not `null`). + */ + public abstract void onBind(T item, @Nullable L listener); + +} diff --git a/AndroidBase/androidBase/src/main/java/ams/android_base/baseClasses/recyclerView/BaseRecyclerViewListener.java b/AndroidBase/androidBase/src/main/java/ams/android_base/baseClasses/recyclerView/BaseRecyclerViewListener.java new file mode 100644 index 0000000..7735523 --- /dev/null +++ b/AndroidBase/androidBase/src/main/java/ams/android_base/baseClasses/recyclerView/BaseRecyclerViewListener.java @@ -0,0 +1,3 @@ +package ams.android_base.baseClasses.recyclerView; + +public interface BaseRecyclerViewListener {} diff --git a/AndroidBase/androidBase/src/main/java/ams/android_base/baseClasses/recyclerView/BaseSection.java b/AndroidBase/androidBase/src/main/java/ams/android_base/baseClasses/recyclerView/BaseSection.java new file mode 100644 index 0000000..6cca984 --- /dev/null +++ b/AndroidBase/androidBase/src/main/java/ams/android_base/baseClasses/recyclerView/BaseSection.java @@ -0,0 +1,48 @@ +package ams.android_base.baseClasses.recyclerView; + +//import android.support.v7.widget.RecyclerView; +//import android.view.View; +// +//import com.androidchallenge.instabug.instabugandroidchallenge.models.entites.roomDatabaseEntites.DaySection; +//import com.androidchallenge.instabug.instabugandroidchallenge.models.entites.roomDatabaseEntites.MatchEntity; +//import com.androidchallenge.instabug.instabugandroidchallenge.scenes.mainScreenScene.matchesListing.allMatchesFragment.SectionInteractionListener; +// +//import io.github.luizgrp.sectionedrecyclerviewadapter.SectionParameters; +//import io.github.luizgrp.sectionedrecyclerviewadapter.StatelessSection; + +//public class BaseSection
extends StatelessSection { +// +// private Section section; +// private L listener; +// +// protected Section getSection() { return section; } +// +// protected L getListener() { return listener; } +// +// /** +// * Create a stateless Section object based on {@link SectionParameters}. +// * +// * @param sectionParameters section parameters +// */ +// public BaseSection(SectionParameters sectionParameters) { super(sectionParameters); } +// +// protected void init (Section section, L listener) { this.section = section; this.listener = listener; } +// +// @Override +// public int getContentItemsTotal() { return 0; } +// +// @Override +// public RecyclerView.ViewHolder getItemViewHolder(View view) { return null; } +// +// @Override +// public void onBindItemViewHolder(RecyclerView.ViewHolder holder, int position) { +// MatchEntity match = this.section.getMatchesList().get(position); +// ((VH)holder).onBind(match, listener); +// } +// +// @Override +// public void onBindHeaderViewHolder(RecyclerView.ViewHolder holder) { +// super.onBindHeaderViewHolder(holder); +// ((HVH)holder).onBind(section, listener); +// } +//} diff --git a/AndroidBase/androidBase/src/main/java/ams/android_base/baseClasses/roomDB/BaseDAO.java b/AndroidBase/androidBase/src/main/java/ams/android_base/baseClasses/roomDB/BaseDAO.java new file mode 100644 index 0000000..5c32803 --- /dev/null +++ b/AndroidBase/androidBase/src/main/java/ams/android_base/baseClasses/roomDB/BaseDAO.java @@ -0,0 +1,29 @@ +package ams.android_base.baseClasses.roomDB; + +import android.arch.persistence.db.SupportSQLiteQuery; +import android.arch.persistence.room.Dao; +import android.arch.persistence.room.Insert; +import android.arch.persistence.room.Query; +import android.arch.persistence.room.RawQuery; + +import java.util.List; + +import static android.arch.persistence.room.OnConflictStrategy.REPLACE; + +@Dao +public interface BaseDAO { + @Insert + void insertAll(List records); + @Insert + void insert(T record); + @Insert(onConflict = REPLACE) + void update(T record); + @RawQuery + List getAll(SupportSQLiteQuery query); + @RawQuery + List getPageItems(SupportSQLiteQuery query); + @RawQuery + int numberOfRows(SupportSQLiteQuery query); + @RawQuery + void deleteAllSections(SupportSQLiteQuery query); +} \ No newline at end of file diff --git a/AndroidBase/androidBase/src/main/java/ams/android_base/helpers/DisplayMetricsConverter.java b/AndroidBase/androidBase/src/main/java/ams/android_base/helpers/DisplayMetricsConverter.java new file mode 100755 index 0000000..2ce12f7 --- /dev/null +++ b/AndroidBase/androidBase/src/main/java/ams/android_base/helpers/DisplayMetricsConverter.java @@ -0,0 +1,24 @@ +package ams.android_base.helpers; + +import android.content.res.Resources; +import android.util.DisplayMetrics; + +/** + * Created by Ahmad Mahmoud on 22-Feb-18. + */ + +public class DisplayMetricsConverter { + + private static DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics(); + + public static float convertPixelsToDp(float px){ + float dp = px / (metrics.densityDpi / 160f); + return Math.round(dp); + } + + public static float convertDpToPixel(float dp){ + float px = dp * (metrics.densityDpi / 160f); + return Math.round(px); + } + +} diff --git a/AndroidBase/androidBase/src/main/java/ams/android_base/helpers/checkers/AndroidVersion.java b/AndroidBase/androidBase/src/main/java/ams/android_base/helpers/checkers/AndroidVersion.java new file mode 100755 index 0000000..4c5f5cb --- /dev/null +++ b/AndroidBase/androidBase/src/main/java/ams/android_base/helpers/checkers/AndroidVersion.java @@ -0,0 +1,22 @@ +package ams.android_base.helpers.checkers; + +import android.os.Build; + +/** + * Created by Ahmad Mahmoud on 05-Feb-18. + */ + +public class AndroidVersion { + + public static boolean isLollipopOrHigher () { + return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M; + } + + public static boolean isNougatOrHigher() { + return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N; + } + + public static boolean isJellyBeanOrHigher () { + return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN; + } +} diff --git a/AndroidBase/androidBase/src/main/java/ams/android_base/helpers/checkers/PatternCheckers.java b/AndroidBase/androidBase/src/main/java/ams/android_base/helpers/checkers/PatternCheckers.java new file mode 100755 index 0000000..8bbe413 --- /dev/null +++ b/AndroidBase/androidBase/src/main/java/ams/android_base/helpers/checkers/PatternCheckers.java @@ -0,0 +1,19 @@ +package ams.android_base.helpers.checkers; + +import static ams.android_base.baseClasses.globalKeys.BasePatterns.EMAIL_PATTERN; +import static ams.android_base.baseClasses.globalKeys.BasePatterns.SPECIAL_CHARACTERS_PATTERN; +import static ams.android_base.baseClasses.globalKeys.BasePatterns.get24TimeFormatPattern; + +/** + * Created by Ahmad Mahmoud on 22-Feb-18. + */ + +@SuppressWarnings("unused") +public class PatternCheckers { + public static boolean isValidMailPattern(String mail){ + return mail.matches(EMAIL_PATTERN); + } + public static boolean containsSpecialCharacter(String text){ return text.matches(SPECIAL_CHARACTERS_PATTERN); } + public static boolean isValid24HoursString(String timeString, String splittingCharacter){ return timeString.matches(get24TimeFormatPattern(splittingCharacter)); } + public boolean isValidPasswordPattern(String password, String passwordPattern){ return password.matches(passwordPattern); } +} diff --git a/AndroidBase/androidBase/src/main/java/ams/android_base/utils/RoomUtils.java b/AndroidBase/androidBase/src/main/java/ams/android_base/utils/RoomUtils.java new file mode 100644 index 0000000..41309e6 --- /dev/null +++ b/AndroidBase/androidBase/src/main/java/ams/android_base/utils/RoomUtils.java @@ -0,0 +1,28 @@ +package ams.android_base.utils; + +import android.arch.persistence.db.SimpleSQLiteQuery; + +public class RoomUtils { + + @SuppressWarnings("WeakerAccess") + public static SimpleSQLiteQuery getQuery(String selectStatement) { return new SimpleSQLiteQuery(selectStatement); } + + public static SimpleSQLiteQuery selectAllQuery(String tableName) { return getQuery("SELECT * FROM" + tableName); } + + public static SimpleSQLiteQuery selectPageItemsQuery(String tableName, int itemsPerPage, int offset) { + return getQuery("SELECT * FROM" + tableName + " LIMIT " + itemsPerPage + " OFFSET " + offset); + } + + public static SimpleSQLiteQuery totalNumberOfRowsQuery(String tableName) { + return getQuery("SELECT COUNT(*) FROM " + tableName); + } + + public static SimpleSQLiteQuery totalNumberOfRowsQuery(String tableName, String condition) { + return getQuery("SELECT COUNT(*) FROM " + tableName + condition); + } + + public static SimpleSQLiteQuery deleteAllRowsQuery(String tableName) { + return getQuery("DELETE FROM " + tableName); + } + +} diff --git a/AndroidBase/androidBase/src/main/java/ams/android_base/utils/TextViewLinkHandler.java b/AndroidBase/androidBase/src/main/java/ams/android_base/utils/TextViewLinkHandler.java new file mode 100755 index 0000000..9539172 --- /dev/null +++ b/AndroidBase/androidBase/src/main/java/ams/android_base/utils/TextViewLinkHandler.java @@ -0,0 +1,53 @@ +package ams.android_base.utils; + +import android.text.Layout; +import android.text.Spannable; +import android.text.method.LinkMovementMethod; +import android.text.style.URLSpan; +import android.view.MotionEvent; +import android.widget.TextView; + +/** + * Created by Ahmad Mahmoud on 11-May-17. + */ + +@SuppressWarnings({"DefaultFileTemplate", "unused"}) +public abstract class TextViewLinkHandler extends LinkMovementMethod { + + public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) { + if (event.getAction() != MotionEvent.ACTION_UP) + return super.onTouchEvent(widget, buffer, event); + + int x = (int) event.getX(); + int y = (int) event.getY(); + + x -= widget.getTotalPaddingLeft(); + y -= widget.getTotalPaddingTop(); + + x += widget.getScrollX(); + y += widget.getScrollY(); + + Layout layout = widget.getLayout(); + int line = layout.getLineForVertical(y); + int off = layout.getOffsetForHorizontal(line, x); + + URLSpan[] link = buffer.getSpans(off, off, URLSpan.class); + if (link.length != 0) { + onLinkClick(link[0].getURL()); + } + return true; + } + + @SuppressWarnings("WeakerAccess") + abstract public void onLinkClick(String url); + + // This is how to make clickable links in list or recycler view + /* + holder.tvMessage.setMovementMethod(new TextViewLinkHandler() { + @Override + public void onLinkClick(String url) { + Toast.makeText(holder.tvMessage.getContext(), url, Toast.LENGTH_SHORT); + } + }); + */ +} \ No newline at end of file diff --git a/AndroidBase/androidBase/src/main/java/ams/android_base/utils/TypeConverter.java b/AndroidBase/androidBase/src/main/java/ams/android_base/utils/TypeConverter.java new file mode 100755 index 0000000..ef6550b --- /dev/null +++ b/AndroidBase/androidBase/src/main/java/ams/android_base/utils/TypeConverter.java @@ -0,0 +1,34 @@ +package ams.android_base.utils; + +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; + +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * Created by Ahmad Mahmoud on 12-Feb-18. + */ + +@SuppressWarnings("unused") +public class TypeConverter { + + private TypeConverter() {} + + private final static Gson gson = new Gson(); + + public static List listOfObjectsFromString (String string, Class clazz) { + T[] list = gson.fromJson(string, clazz); + return Arrays.asList(list); + } + public static T objectFromString (String string, Class t) { return gson.fromJson(string, t); } + public static String objectToString (Class t) { return gson.toJson(t); } + public static ArrayList listFromString(String string) { + Type listType = new TypeToken>() {}.getType(); + return new Gson().fromJson(string, listType); + } + public static String fromArrayList(ArrayList list) { return gson.toJson(list); } + +} diff --git a/AndroidBase/androidBase/src/main/res/layout/activity_zoom_image.xml b/AndroidBase/androidBase/src/main/res/layout/activity_zoom_image.xml new file mode 100755 index 0000000..d8173b6 --- /dev/null +++ b/AndroidBase/androidBase/src/main/res/layout/activity_zoom_image.xml @@ -0,0 +1,10 @@ + + + + diff --git a/AndroidBase/androidBase/src/main/res/values/strings.xml b/AndroidBase/androidBase/src/main/res/values/strings.xml new file mode 100644 index 0000000..3c7d688 --- /dev/null +++ b/AndroidBase/androidBase/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + Android Base + diff --git a/AndroidBase/androidBase/src/test/java/ams/android_base/ExampleUnitTest.java b/AndroidBase/androidBase/src/test/java/ams/android_base/ExampleUnitTest.java new file mode 100644 index 0000000..04ae042 --- /dev/null +++ b/AndroidBase/androidBase/src/test/java/ams/android_base/ExampleUnitTest.java @@ -0,0 +1,17 @@ +package ams.android_base; + +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() { + assertEquals(4, 2 + 2); + } +} \ No newline at end of file diff --git a/AndroidBase/app/.gitignore b/AndroidBase/app/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/AndroidBase/app/.gitignore @@ -0,0 +1 @@ +/build diff --git a/AndroidBase/app/build.gradle b/AndroidBase/app/build.gradle new file mode 100644 index 0000000..6c890b5 --- /dev/null +++ b/AndroidBase/app/build.gradle @@ -0,0 +1,35 @@ +apply plugin: 'com.android.application' + +apply plugin: 'kotlin-android' + +apply plugin: 'kotlin-android-extensions' + + +android { + compileSdkVersion 27 + defaultConfig { + applicationId "ams.androidbase.androidbase" + minSdkVersion 22 + targetSdkVersion 27 + versionCode 1 + versionName "1.0" + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + implementation 'com.android.support:appcompat-v7:27.1.1' + implementation 'com.android.support.constraint:constraint-layout:1.1.3' + testImplementation 'junit:junit:4.12' + androidTestImplementation 'com.android.support.test:runner:1.0.2' + androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' + +} diff --git a/AndroidBase/app/proguard-rules.pro b/AndroidBase/app/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/AndroidBase/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# 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/AndroidBase/app/src/androidTest/java/ams/androidbase/androidbase/ExampleInstrumentedTest.kt b/AndroidBase/app/src/androidTest/java/ams/androidbase/androidbase/ExampleInstrumentedTest.kt new file mode 100644 index 0000000..2bcc1b2 --- /dev/null +++ b/AndroidBase/app/src/androidTest/java/ams/androidbase/androidbase/ExampleInstrumentedTest.kt @@ -0,0 +1,24 @@ +package ams.androidbase.androidbase + +import android.support.test.InstrumentationRegistry +import android.support.test.runner.AndroidJUnit4 + +import org.junit.Test +import org.junit.runner.RunWith + +import org.junit.Assert.* + +/** + * Instrumented test, which will execute on an Android device. + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +@RunWith(AndroidJUnit4::class) +class ExampleInstrumentedTest { + @Test + fun useAppContext() { + // Context of the app under test. + val appContext = InstrumentationRegistry.getTargetContext() + assertEquals("ams.androidbase.androidbase", appContext.packageName) + } +} diff --git a/AndroidBase/app/src/main/AndroidManifest.xml b/AndroidBase/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..3735c9b --- /dev/null +++ b/AndroidBase/app/src/main/AndroidManifest.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/AndroidBase/app/src/main/java/ams/androidbase/androidbase/SharedPreference.java b/AndroidBase/app/src/main/java/ams/androidbase/androidbase/SharedPreference.java new file mode 100644 index 0000000..43ff006 --- /dev/null +++ b/AndroidBase/app/src/main/java/ams/androidbase/androidbase/SharedPreference.java @@ -0,0 +1,5 @@ +package ams.androidbase.androidbase; + +//@PreferenceEntity(name = "UserProfile") +//public interface SharedPreference { +//} diff --git a/AndroidBase/app/src/main/java/ams/androidbase/androidbase/SplashScreenActivity.kt b/AndroidBase/app/src/main/java/ams/androidbase/androidbase/SplashScreenActivity.kt new file mode 100644 index 0000000..929a0f4 --- /dev/null +++ b/AndroidBase/app/src/main/java/ams/androidbase/androidbase/SplashScreenActivity.kt @@ -0,0 +1,12 @@ +package ams.androidbase.androidbase + +import android.support.v7.app.AppCompatActivity +import android.os.Bundle + +class SplashScreenActivity : AppCompatActivity() { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_splash_screen) + } +} diff --git a/AndroidBase/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/AndroidBase/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..c7bd21d --- /dev/null +++ b/AndroidBase/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + diff --git a/AndroidBase/app/src/main/res/drawable/ic_launcher_background.xml b/AndroidBase/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..d5fccc5 --- /dev/null +++ b/AndroidBase/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/AndroidBase/app/src/main/res/layout/activity_splash_screen.xml b/AndroidBase/app/src/main/res/layout/activity_splash_screen.xml new file mode 100644 index 0000000..9253946 --- /dev/null +++ b/AndroidBase/app/src/main/res/layout/activity_splash_screen.xml @@ -0,0 +1,18 @@ + + + + + + \ No newline at end of file diff --git a/AndroidBase/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/AndroidBase/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/AndroidBase/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/AndroidBase/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/AndroidBase/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/AndroidBase/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/AndroidBase/app/src/main/res/mipmap-hdpi/ic_launcher.png b/AndroidBase/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000..a2f5908 Binary files /dev/null and b/AndroidBase/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/AndroidBase/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/AndroidBase/app/src/main/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 0000000..1b52399 Binary files /dev/null and b/AndroidBase/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/AndroidBase/app/src/main/res/mipmap-mdpi/ic_launcher.png b/AndroidBase/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000..ff10afd Binary files /dev/null and b/AndroidBase/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/AndroidBase/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/AndroidBase/app/src/main/res/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 0000000..115a4c7 Binary files /dev/null and b/AndroidBase/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/AndroidBase/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/AndroidBase/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000..dcd3cd8 Binary files /dev/null and b/AndroidBase/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/AndroidBase/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/AndroidBase/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 0000000..459ca60 Binary files /dev/null and b/AndroidBase/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/AndroidBase/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/AndroidBase/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..8ca12fe Binary files /dev/null and b/AndroidBase/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/AndroidBase/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/AndroidBase/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..8e19b41 Binary files /dev/null and b/AndroidBase/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/AndroidBase/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/AndroidBase/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000..b824ebd Binary files /dev/null and b/AndroidBase/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/AndroidBase/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/AndroidBase/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..4c19a13 Binary files /dev/null and b/AndroidBase/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/AndroidBase/app/src/main/res/values/colors.xml b/AndroidBase/app/src/main/res/values/colors.xml new file mode 100644 index 0000000..3ab3e9c --- /dev/null +++ b/AndroidBase/app/src/main/res/values/colors.xml @@ -0,0 +1,6 @@ + + + #3F51B5 + #303F9F + #FF4081 + diff --git a/AndroidBase/app/src/main/res/values/strings.xml b/AndroidBase/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..76ec99e --- /dev/null +++ b/AndroidBase/app/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + AndroidBase + diff --git a/AndroidBase/app/src/main/res/values/styles.xml b/AndroidBase/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..5885930 --- /dev/null +++ b/AndroidBase/app/src/main/res/values/styles.xml @@ -0,0 +1,11 @@ + + + + + + diff --git a/AndroidBase/app/src/test/java/ams/androidbase/androidbase/ExampleUnitTest.kt b/AndroidBase/app/src/test/java/ams/androidbase/androidbase/ExampleUnitTest.kt new file mode 100644 index 0000000..aa300be --- /dev/null +++ b/AndroidBase/app/src/test/java/ams/androidbase/androidbase/ExampleUnitTest.kt @@ -0,0 +1,17 @@ +package ams.androidbase.androidbase + +import org.junit.Test + +import org.junit.Assert.* + +/** + * Example local unit test, which will execute on the development machine (host). + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +class ExampleUnitTest { + @Test + fun addition_isCorrect() { + assertEquals(4, 2 + 2) + } +} diff --git a/AndroidBase/build.gradle b/AndroidBase/build.gradle new file mode 100644 index 0000000..059200b --- /dev/null +++ b/AndroidBase/build.gradle @@ -0,0 +1,28 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. +apply plugin: 'com.jakewharton.butterknife' + +buildscript { + ext.kotlin_version = '1.2.51' + repositories { + google() + mavenCentral() + jcenter() + + } + dependencies { + classpath 'com.android.tools.build:gradle:3.1.3' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + classpath 'com.jakewharton:butterknife-gradle-plugin:10.0.0' + } +} + +allprojects { + repositories { + google() + jcenter() + } +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/AndroidBase/gradle.properties b/AndroidBase/gradle.properties new file mode 100644 index 0000000..743d692 --- /dev/null +++ b/AndroidBase/gradle.properties @@ -0,0 +1,13 @@ +# Project-wide Gradle settings. +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +org.gradle.jvmargs=-Xmx1536m +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true diff --git a/AndroidBase/gradle/wrapper/gradle-wrapper.jar b/AndroidBase/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..7a3265e Binary files /dev/null and b/AndroidBase/gradle/wrapper/gradle-wrapper.jar differ diff --git a/AndroidBase/gradle/wrapper/gradle-wrapper.properties b/AndroidBase/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..4d50a1d --- /dev/null +++ b/AndroidBase/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Fri Jan 11 14:04:28 EET 2019 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip diff --git a/AndroidBase/gradlew b/AndroidBase/gradlew new file mode 100755 index 0000000..cccdd3d --- /dev/null +++ b/AndroidBase/gradlew @@ -0,0 +1,172 @@ +#!/usr/bin/env sh + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/AndroidBase/gradlew.bat b/AndroidBase/gradlew.bat new file mode 100644 index 0000000..e95643d --- /dev/null +++ b/AndroidBase/gradlew.bat @@ -0,0 +1,84 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/AndroidBase/settings.gradle b/AndroidBase/settings.gradle new file mode 100644 index 0000000..39e663b --- /dev/null +++ b/AndroidBase/settings.gradle @@ -0,0 +1 @@ +include ':app', ':android_base', ':androidBase'