commit 65fd282da90cb606ad5e4e0922891b46c3437ac6 Author: Kevin Puertas Date: Sat Jun 3 13:51:01 2017 +0200 Initial source code export diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..47c1190 --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +/.idea/workspace.xml +/.idea/libraries +.DS_Store +/build +/captures +.externalNativeBuild +app/src/main/res/values/admob.xml \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..96cc43e --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml new file mode 100644 index 0000000..e7bedf3 --- /dev/null +++ b/.idea/copyright/profiles_settings.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/.idea/dictionaries/kprkpr.xml b/.idea/dictionaries/kprkpr.xml new file mode 100644 index 0000000..9b334da --- /dev/null +++ b/.idea/dictionaries/kprkpr.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 0000000..7ac24c7 --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,18 @@ + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..146ab09 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,10 @@ + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..3b31283 --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..3d21ecd --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..61b37d5 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml new file mode 100644 index 0000000..7f68460 --- /dev/null +++ b/.idea/runConfigurations.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/GPlayLargelogoapp.png b/GPlayLargelogoapp.png new file mode 100644 index 0000000..61f6883 Binary files /dev/null and b/GPlayLargelogoapp.png differ diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..63d0791 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,9 @@ +## Licencia GPL + +## Licencias de terceros + +**robotoCalendarView** + +https://github.com/marcohc/roboto-calendar-view + +It has an Apache License 2.0 -> https://github.com/marcohc/roboto-calendar-view/blob/master/LICENSE \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..bb3a67b --- /dev/null +++ b/README.md @@ -0,0 +1,16 @@ +# Codigo fuente de "Calendario De Frases" + +Calendario de frases es una aplicacion para Android en la que todos los días tendrás una nueva frase o refrán en tu lugar de notificaciones + +Con un calendario integrado, podrás ver frases anteriores, marcar como favoritos, o compartirlas con tus amigos + +Descargalo en Google Play: https://play.google.com/store/apps/details?id=com.jkanetwork.st.calendariodefrases + +## Problemas al compilar la aplicación + +La aplicación puede dar problemas de compilación al faltar los 2 strings de la API de Admob (No subidas porque son propias, evitamos un mal uso de la API). +Para solucionarlo solo hay que quitar la parte de admob + +## Licencia + +Mire el fichero LICENSE.md para detalles, usamos licencia GPL \ No newline at end of file diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build diff --git a/app/app-release.apk b/app/app-release.apk new file mode 100644 index 0000000..d69b577 Binary files /dev/null and b/app/app-release.apk differ diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..1a89fe9 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,25 @@ +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in /mnt/kevinmem/Android/sdkLinux/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the proguardFiles +# directive in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# Add any project specific keep options here: + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/app/src/androidTest/java/com/jkanetwork/st/calendariodefrases/ExampleInstrumentedTest.java b/app/src/androidTest/java/com/jkanetwork/st/calendariodefrases/ExampleInstrumentedTest.java new file mode 100644 index 0000000..8b94ef3 --- /dev/null +++ b/app/src/androidTest/java/com/jkanetwork/st/calendariodefrases/ExampleInstrumentedTest.java @@ -0,0 +1,26 @@ +package com.jkanetwork.st.calendariodefrases; + +import android.content.Context; +import android.support.test.InstrumentationRegistry; +import android.support.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.*; + +/** + * Instrumentation test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() throws Exception { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getTargetContext(); + + assertEquals("com.jkanetwork.st.unafrasealdia", appContext.getPackageName()); + } +} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f1c3827 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/jkanetwork/st/calendariodefrases/AboutOfActivity.java b/app/src/main/java/com/jkanetwork/st/calendariodefrases/AboutOfActivity.java new file mode 100644 index 0000000..afe4555 --- /dev/null +++ b/app/src/main/java/com/jkanetwork/st/calendariodefrases/AboutOfActivity.java @@ -0,0 +1,20 @@ +package com.jkanetwork.st.calendariodefrases; + +import android.content.Intent; +import android.os.Bundle; +import android.support.v7.app.AppCompatActivity; +import android.view.View; + +/** + * Created by kprkpr on 24/03/17. + */ + +public class AboutOfActivity extends AppCompatActivity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_about); + } + +} diff --git a/app/src/main/java/com/jkanetwork/st/calendariodefrases/Alarm.java b/app/src/main/java/com/jkanetwork/st/calendariodefrases/Alarm.java new file mode 100644 index 0000000..dfbd16c --- /dev/null +++ b/app/src/main/java/com/jkanetwork/st/calendariodefrases/Alarm.java @@ -0,0 +1,73 @@ +package com.jkanetwork.st.calendariodefrases; + +import android.app.AlarmManager; +import android.app.PendingIntent; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import java.util.Calendar; +import android.os.PowerManager; +import android.util.Log; + + +/** + * Created by http://stackoverflow.com/questions/4459058/alarm-manager-example + * Modified by kprkpr + */ + +public class Alarm extends BroadcastReceiver +{ + + @Override + public void onReceive(Context context, Intent intent) + { + PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE); + PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, ""); + wl.acquire(); + // Make notification appear + context.startService(new Intent(context, NotificationHelper.class)); + + wl.release(); + } + + public void putAlarm(Context context){ + Config conf = new Config(context); + + /* Common vars for alarm config */ + Intent i = new Intent(context, Alarm.class); + AlarmManager alarmMgr = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); + PendingIntent sender = PendingIntent.getBroadcast(context, 1, i, 0); + + /* Cancel alarm first */ + alarmMgr.cancel(sender); + + if (conf.getNotifOn() && !conf.getPersistNotifOn()){ + /* Here set the alarm to one time a day in selected date. Default: 8AM */ + Calendar time = Calendar.getInstance(); + /* Shedechule Alarm for tomorrow instead before now if alarm set to before. */ + if (Calendar.HOUR_OF_DAY > conf.getHour() || (Calendar.HOUR_OF_DAY == conf.getHour() && Calendar.MINUTE > conf.getMinute() )){ + /* Add a day */ + time.add(Calendar.DATE, 1); + } + time.set(Calendar.HOUR_OF_DAY, conf.getHour()); + time.set(Calendar.MINUTE, conf.getMinute()); + time.set(Calendar.SECOND, 0); + Log.d("Next notification show",String.valueOf(time.getTime())); + alarmMgr.setRepeating(AlarmManager.RTC, time.getTimeInMillis(), 1000*3600*24, sender); // Repeat every day + } + + if (conf.getNotifOn() && conf.getPersistNotifOn()){ + /* Here set the alarm to one time a day in selected date. Default: 8AM */ + Calendar time = Calendar.getInstance(); + /* Set for 0:00:01 of next day */ + time.add(Calendar.DATE, 1); + time.set(Calendar.HOUR_OF_DAY, 0); + time.set(Calendar.MINUTE, 0); + time.set(Calendar.SECOND, 1); + Log.d("Next notification show",String.valueOf(time.getTime())); + alarmMgr.setRepeating(AlarmManager.RTC, time.getTimeInMillis(), 1000*3600*24, sender); // Repeat every day + context.startService(new Intent(context, NotificationHelper.class)); /* Auto start service for show notif */ + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/jkanetwork/st/calendariodefrases/Config.java b/app/src/main/java/com/jkanetwork/st/calendariodefrases/Config.java new file mode 100644 index 0000000..610b4aa --- /dev/null +++ b/app/src/main/java/com/jkanetwork/st/calendariodefrases/Config.java @@ -0,0 +1,73 @@ +package com.jkanetwork.st.calendariodefrases; + +import android.content.Context; +import android.content.SharedPreferences; + +/** + * Created by kprkpr on 21/03/17. + */ + +public class Config { + + private final String SHARED_PREFS_FILE = "Prefs"; + private final String KEY_HOUR = "Hour"; + private final String KEY_MINUTE = "Minute"; + private final String KEY_NOTIFON = "Notify"; + private final String KEY_PERSISTNOTIFON = "PersistNotify"; + private final String KEY_FIRSTTIME = "FirstTime"; + + private Context emContext; + + + public Config(Context context){ + emContext = context; + } + + + private SharedPreferences getSettings(){ + return emContext.getSharedPreferences(SHARED_PREFS_FILE, 0); + } + + public Integer getHour(){ + return getSettings().getInt(KEY_HOUR, 8); + } + public Integer getMinute(){ + return getSettings().getInt(KEY_MINUTE, 0); + } + public Boolean getNotifOn(){ + return getSettings().getBoolean(KEY_NOTIFON, true); + } + public Boolean getPersistNotifOn(){return getSettings().getBoolean(KEY_PERSISTNOTIFON, false);} + public Boolean getFirstTime(){return getSettings().getBoolean(KEY_FIRSTTIME, true);} + + + public void setHour(Integer hour){ + SharedPreferences.Editor editor = getSettings().edit(); + editor.putInt(KEY_HOUR, hour ); + editor.apply(); + } + public void setMinute(Integer minute){ + SharedPreferences.Editor editor = getSettings().edit(); + editor.putInt(KEY_MINUTE, minute ); + editor.apply(); + } + + public void setNotifOn(Boolean notifon){ + SharedPreferences.Editor editor = getSettings().edit(); + editor.putBoolean(KEY_NOTIFON, notifon ); + editor.apply(); + } + + public void setPersistNotifOn(Boolean notifon){ + SharedPreferences.Editor editor = getSettings().edit(); + editor.putBoolean(KEY_PERSISTNOTIFON, notifon ); + editor.apply(); + } + + public void setFirstTime(Boolean notifon){ + SharedPreferences.Editor editor = getSettings().edit(); + editor.putBoolean(KEY_FIRSTTIME, notifon ); + editor.apply(); + } + +} diff --git a/app/src/main/java/com/jkanetwork/st/calendariodefrases/DatabaseHelper.java b/app/src/main/java/com/jkanetwork/st/calendariodefrases/DatabaseHelper.java new file mode 100644 index 0000000..8366525 --- /dev/null +++ b/app/src/main/java/com/jkanetwork/st/calendariodefrases/DatabaseHelper.java @@ -0,0 +1,262 @@ +package com.jkanetwork.st.calendariodefrases; + +import android.content.Context; +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteOpenHelper; +import android.util.Log; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.List; + +public class DatabaseHelper extends SQLiteOpenHelper { + private static final int DATABASE_VERSION = 7; + private static final String DATABASE_NAME = "database.db"; + private final Context contextdb; + + public DatabaseHelper(Context context) { + super(context, DATABASE_NAME, null, DATABASE_VERSION); + contextdb = context; + } + + /** Return the sentence passing the ID of it */ + public String getFraseFromID(int IDF){ + SQLiteDatabase db = this.getWritableDatabase(); + String sentence; + + if (IDF == 0){return "No hay más frases disponibles...";} + else if (IDF == -1){return "No puedes ver aún esta frase";} + else if (IDF == -2){return "A ocurrido un error";} + else { //If there is a sentence + + try { + Cursor c = db.rawQuery("SELECT Frase FROM frases WHERE _id = '" + IDF + "'", null); + c.moveToFirst(); + sentence = c.getString(0); + c.close(); + } catch (Exception e) { + Log.e("Database", e.toString()); + sentence = "Error al buscar la frase"; + } + return sentence; + } + } + + public String getAutorFromID(int IDF){ + SQLiteDatabase db = this.getWritableDatabase(); + String sentence; + + if (IDF <= 0){return "";} + else { //If there is a sentence + try { + Cursor c = db.rawQuery("SELECT Autor FROM autores a WHERE _id=(SELECT AutorID from frases WHERE _id='"+ IDF + "')",null); + c.moveToFirst(); + sentence = c.getString(0); + c.close(); + } catch (Exception e) { + Log.e("Database", e.getMessage()); + sentence = ""; + } + return sentence; + } + } + + + /** Add a sentence as favorite */ + public void addFav(int IDF){ + SQLiteDatabase db = this.getWritableDatabase(); + try{ + db.execSQL("INSERT INTO frasesFav VALUES('"+IDF+"')"); + }catch(Exception e){ + Log.e("Database",e.toString()); + } + } + + /** Del a favorite sentence */ + public void delFav(int IDF){ + SQLiteDatabase db = this.getWritableDatabase(); + try{ + db.execSQL("DELETE FROM frasesFav WHERE IDFrase='"+IDF+"'"); + }catch(Exception e){ + Log.e("Database",e.toString()); + } + } + + /** Returns ID from a day X sentence, if possible */ + public Integer getIDFraseDay(int year,int month,int dayOfMonth){ + Calendar cal = Calendar.getInstance(); + try { + Integer ret; + SQLiteDatabase db = this.getWritableDatabase(); + + /* For ever have two digits month and day */ + String sYear = Integer.toString(year); + String sMonth; /* month selected */ + String sDay; /* day selected */ + if (month < 10) { + sMonth = "0" + Integer.toString(month); + }else{ + sMonth = Integer.toString(month); + } + if (dayOfMonth < 10) { + sDay = "0" + Integer.toString(dayOfMonth); + }else{ + sDay = Integer.toString(dayOfMonth); + } + + /* Same for calendar day */ + String cYear = Integer.toString(cal.get(Calendar.YEAR)); + String cMonth; /* Calendar month */ + String cDay; /* Calendar day */ + if ((cal.get(Calendar.MONTH)+1) < 10) { + cMonth = "0" + Integer.toString(cal.get(Calendar.MONTH)+1); + }else{ + cMonth = Integer.toString(cal.get(Calendar.MONTH)+1); + } + if (cal.get(Calendar.DAY_OF_MONTH) < 10) { + cDay = "0" + Integer.toString(cal.get(Calendar.DAY_OF_MONTH)); + }else{ + cDay = Integer.toString(cal.get(Calendar.DAY_OF_MONTH)); + } + + String diaArg = sYear+sMonth+sDay; //Dia pasado a string yyyymmdd + String diaAct = cYear+cMonth+cDay; + Cursor query = db.rawQuery("SELECT IDFrase FROM frasesG WHERE Tday = '"+diaArg+"'", null); + if(query.getCount() != 0) { + query.moveToFirst(); + ret = query.getInt(0); + query.close(); + return ret; + //Else for make sentence if there is today or someday before has a sentence (This is possible if app was installed but not opened) + }else if ((Integer.decode(diaArg) < Integer.decode(diaAct) && db.rawQuery("SELECT IDFrase FROM frasesG WHERE Tday < '"+diaArg+"'", null).getCount() > 0) || ( Integer.decode(diaArg).equals(Integer.decode(diaAct)) ) ) { + //}else{ //Make sentence all times (DEBUG) + try { + query = db.rawQuery("SELECT _id FROM frases WHERE _id NOT IN (SELECT IDFrase FROM frasesG) ORDER BY RANDOM() LIMIT 1", null); + query.moveToFirst(); + db.rawQuery("INSERT INTO frasesG (Tday,IDFrase) VALUES('" + diaArg + "','" + query.getString(0) + "')", null).moveToFirst(); + ret = query.getInt(0); + return ret; + } catch (Exception e) { + return 0; //0 its no more sentences + } + }else{ //Not today, do not make one + return -1; //-1 its day not accesible now + } + } catch (Exception e) { + Log.e("Database",e.toString()); + return -2; //BUG + } + } + + /** Returns ID of today's sentence */ + public Integer getIDFraseHoy(){ + Calendar cal = Calendar.getInstance(); + //Month + 1 because Android starts with month=0 + return getIDFraseDay(cal.get(Calendar.YEAR),cal.get(Calendar.MONTH)+1,cal.get(Calendar.DAY_OF_MONTH)); + } + + /** Returns an array of favorite IDs */ + public Integer[] getIDFavs(){ + SQLiteDatabase db = this.getWritableDatabase(); + List a = new ArrayList<>(); + + Cursor c = db.rawQuery("SELECT IDFrase FROM frasesFav",null); + + for (c.moveToFirst(); !c.isAfterLast(); c.moveToNext()){ + a.add(c.getInt(0)); + } + + Integer[] Favorites = new Integer[a.size()]; + a.toArray(Favorites); + c.close(); + return Favorites; + } + + /** Returns an array of favorite IDs */ + public String[] getAllDaysYet(){ + SQLiteDatabase db = this.getWritableDatabase(); + List a = new ArrayList<>(); + + Cursor c = db.rawQuery("SELECT Tday FROM frasesG",null); + + for (c.moveToFirst(); !c.isAfterLast(); c.moveToNext()){ + a.add(c.getString(0)); + } + + String[] Favorites = new String[a.size()]; + a.toArray(Favorites); + c.close(); + return Favorites; + } + + + /* Here Startup of database. When changes, change number up in class */ + + @Override + public void onCreate(SQLiteDatabase db) { + db.execSQL("CREATE TABLE frases (" + + "`_id` INTEGER PRIMARY KEY AUTOINCREMENT," + + "`Frase` TEXT NOT NULL UNIQUE," + + "`AutorID` INTEGER" + + ")"); + db.execSQL("CREATE TABLE autores (" + + "`_id` INTEGER PRIMARY KEY AUTOINCREMENT," + + "`Autor` TEXT UNIQUE" + + ")"); + db.execSQL("CREATE TABLE frasesG (" + + "`_id` INTEGER PRIMARY KEY AUTOINCREMENT," + + "`Tday` TEXT NOT NULL UNIQUE," + + "`IDFrase` INTEGER NOT NULL" + + ")"); + db.execSQL("CREATE TABLE frasesFav (" + + "`IDFrase` INTEGER NOT NULL UNIQUE" + + ")"); + db.execSQL(readSqldata("Frases")); + db.execSQL(readSqldata("Autores")); + } + + @Override + public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { + db.execSQL("DROP TABLE frases"); + db.execSQL("DROP TABLE autores"); + db.execSQL("CREATE TABLE frases (" + + "`_id` INTEGER PRIMARY KEY AUTOINCREMENT," + + "`Frase` TEXT NOT NULL UNIQUE," + + "`AutorID` INTEGER" + + ")"); + db.execSQL("CREATE TABLE autores (" + + "`_id` INTEGER PRIMARY KEY AUTOINCREMENT," + + "`Autor` TEXT UNIQUE" + + ")"); + db.execSQL(readSqldata("Frases")); + db.execSQL(readSqldata("Autores")); + } + + private String readSqldata(String str){ + //getting the file + InputStream inputStream; + if (str.equals("Frases")) { + inputStream = contextdb.getResources().openRawResource(R.raw.sqlfrases); + }else{ + inputStream = contextdb.getResources().openRawResource(R.raw.sqlautores); + } + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + try { + int i = inputStream.read(); + while (i != -1) { + byteArrayOutputStream.write(i); + i = inputStream.read(); + } + inputStream.close(); + + } catch (IOException e) { + e.printStackTrace(); + } + return byteArrayOutputStream.toString(); + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/jkanetwork/st/calendariodefrases/FavsActivity.java b/app/src/main/java/com/jkanetwork/st/calendariodefrases/FavsActivity.java new file mode 100644 index 0000000..ca32767 --- /dev/null +++ b/app/src/main/java/com/jkanetwork/st/calendariodefrases/FavsActivity.java @@ -0,0 +1,109 @@ +package com.jkanetwork.st.calendariodefrases; + +import android.content.ClipData; +import android.content.ClipboardManager; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.support.v7.app.AppCompatActivity; +import android.util.Log; +import android.view.ContextMenu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View; +import android.widget.AdapterView; +import android.widget.ListView; +import android.widget.SimpleAdapter; +import android.widget.Toast; + +import java.util.ArrayList; +import java.util.HashMap; + + +/** + * Created by kprkpr on 21/03/17. + * Help from: http://androidexample.com/Create_A_Simple_Listview_-_Android_Example/index.php?view=article_discription&aid=65 + */ + +public class FavsActivity extends AppCompatActivity { + DatabaseHelper db = new DatabaseHelper(this); + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_favs); + + final ListView listFavs = (ListView) findViewById(R.id.listSentences); + + // Defined Array values to show in ListView + + //Get IDs of sentences that are favs, and create an array of same length + final Integer[] IDFavs = db.getIDFavs(); + + final String[] sentences = new String[IDFavs.length]; + final String[] authorNames = new String[IDFavs.length]; + //Follow all IDFavs recovering sentence + if (IDFavs.length != 0) { + for (int x = 0; x <= IDFavs.length - 1; x++) { + sentences[x] = db.getFraseFromID(IDFavs[x]); + authorNames[x] = db.getAutorFromID(IDFavs[x]); + } + } + + if (IDFavs.length != 0) { + ArrayList> items = new ArrayList<>(); + HashMap listItem; + for (int x = 0; x <= IDFavs.length - 1; x++) { + listItem = new HashMap<>(); + listItem.put("item", sentences[x]); + listItem.put("subitem", authorNames[x]); + items.add(listItem); + } + SimpleAdapter adapter = new SimpleAdapter(this, items, android.R.layout.simple_list_item_2, new String[]{"item", "subitem"}, new int[]{android.R.id.text1, android.R.id.text2}); + listFavs.setAdapter(adapter); + } + + /* Register context menu */ + registerForContextMenu(listFavs); + } + + + @Override + public void onCreateContextMenu(ContextMenu menu, View v, + ContextMenu.ContextMenuInfo menuInfo) { + super.onCreateContextMenu(menu, v, menuInfo); + MenuInflater inflater = getMenuInflater(); + inflater.inflate(R.menu.proverbmenu_del, menu); + } + + @Override + public boolean onContextItemSelected(MenuItem item) { + + ListView listFavs = (ListView) findViewById(R.id.listSentences); + AdapterView.AdapterContextMenuInfo info = + (AdapterView.AdapterContextMenuInfo) item.getMenuInfo(); + @SuppressWarnings("unchecked") /* Because next line has a type change without checking it */ + HashMap obj = (HashMap) listFavs.getItemAtPosition(info.position); + + switch (item.getItemId()) { + case R.id.copy: + ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE); + clipboard.setPrimaryClip(ClipData.newPlainText("Sentence", obj.get("item")+this.getString(R.string.sharefrom))); + Toast.makeText(getApplicationContext(), "Copiado al portapapeles", Toast.LENGTH_LONG ).show(); + return true; + case R.id.delfav: + Integer[] IDFavs = db.getIDFavs(); + db.delFav(IDFavs[info.position]); + /* Restart activity for refresh favs */ + finish(); + startActivity(getIntent()); + return true; + case R.id.share: + Intent intent = new Intent(Intent.ACTION_SEND); + intent.setType("text/plain"); + intent.putExtra(Intent.EXTRA_TEXT,obj.get("item")+this.getString(R.string.sharefrom)); + startActivity(Intent.createChooser(intent, "Compartir con")); + return true; + } + return false; + } +} diff --git a/app/src/main/java/com/jkanetwork/st/calendariodefrases/FirstStartActivity.java b/app/src/main/java/com/jkanetwork/st/calendariodefrases/FirstStartActivity.java new file mode 100644 index 0000000..22b1343 --- /dev/null +++ b/app/src/main/java/com/jkanetwork/st/calendariodefrases/FirstStartActivity.java @@ -0,0 +1,30 @@ +package com.jkanetwork.st.calendariodefrases; + +import android.content.Intent; +import android.os.Bundle; +import android.support.v7.app.AppCompatActivity; +import android.view.View; + +/** + * Created by kprkpr on 24/03/17. + */ + +public class FirstStartActivity extends AppCompatActivity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_first); + Config conf = new Config(this); + conf.setFirstTime(false); /* App opened at least one time */ + + (findViewById(R.id.btnStart)).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + Intent newMA= new Intent(FirstStartActivity.this,MainActivity.class); + startActivity(newMA); + } + }); + } + +} diff --git a/app/src/main/java/com/jkanetwork/st/calendariodefrases/MainActivity.java b/app/src/main/java/com/jkanetwork/st/calendariodefrases/MainActivity.java new file mode 100644 index 0000000..c83b3aa --- /dev/null +++ b/app/src/main/java/com/jkanetwork/st/calendariodefrases/MainActivity.java @@ -0,0 +1,256 @@ +package com.jkanetwork.st.calendariodefrases; + +import android.content.ClipData; +import android.content.ClipboardManager; +import android.content.Context; +import android.content.Intent; +import android.support.v7.app.AppCompatActivity; +import android.os.Bundle; +import android.view.ContextMenu; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View; +import android.widget.TextView; +import android.widget.Toast; + +import com.google.android.gms.ads.AdRequest; +import com.google.android.gms.ads.AdView; +import com.google.android.gms.ads.MobileAds; +import com.marcohc.robotocalendar.RobotoCalendarView.RobotoCalendarListener; +import com.marcohc.robotocalendar.RobotoCalendarView; + +import java.text.DateFormatSymbols; +import java.util.Calendar; + + +public class MainActivity extends AppCompatActivity implements RobotoCalendarListener { + + private RobotoCalendarView robotoCalendarView; + DatabaseHelper db = new DatabaseHelper(this); + Calendar cal = Calendar.getInstance(); + Integer IDFrase; + final Config conf = new Config(this); + + /* Will use when move month back and forth, because library doesnt show the actual month.. */ + Integer calMonth = cal.get(Calendar.MONTH)+1; //From 1 to 12, and not from 0 to 11 + Integer calYear = cal.get(Calendar.YEAR); + + /* Texts making all activity used, and valued in onCreate */ + TextView txtfraseTitle; + TextView txtfraseText; + TextView txtfraseAutor; + + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + MenuInflater inflater = getMenuInflater(); + inflater.inflate(R.menu.main, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case R.id.favorites: + Intent newIF= new Intent(MainActivity.this,FavsActivity.class); + startActivity(newIF); + return true; + case R.id.options: + Intent newIO= new Intent(MainActivity.this,OptsActivity.class); + startActivity(newIO); + return true; + case R.id.about: + Intent newIA= new Intent(MainActivity.this,AboutOfActivity.class); + startActivity(newIA); + return true; + case R.id.exit: + moveTaskToBack(true); /* Returns to "desktop" */ + default: + return super.onOptionsItemSelected(item); + } + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + /* First of all,before loading, see if its the first time using the app */ + if (conf.getFirstTime()){ + Intent newFA= new Intent(MainActivity.this,FirstStartActivity.class); + startActivity(newFA); + } + + setContentView(R.layout.activity_main); + txtfraseTitle = (TextView) findViewById(R.id.txt_frasetitle); + txtfraseText = (TextView) findViewById(R.id.txt_frasetext); + txtfraseAutor = (TextView) findViewById(R.id.txt_fraseautor); + + /* Calendar basic settings */ + robotoCalendarView = (RobotoCalendarView) findViewById(R.id.calendarPicker); + robotoCalendarView.setRobotoCalendarListener(this); + robotoCalendarView.setShortWeekDays(false); + robotoCalendarView.showDateTitle(true); + + /* Admob ads */ + MobileAds.initialize(getApplicationContext(), MainActivity.this.getString(R.string.admob_launch_api)); + AdView mAdView = (AdView) findViewById(R.id.adView); + AdRequest adRequest = new AdRequest.Builder().build(); + mAdView.loadAd(adRequest); + + onResume(); /* Here all that as to be refreshed when app opens from background */ + + + /* Configure alarm */ + Alarm alarm = new Alarm(); + alarm.putAlarm(this); + + /* Register context menu */ + registerForContextMenu(txtfraseText); + } + + @Override + public void onResume(){ + super.onResume(); + /* Refresh calendar */ + cal = Calendar.getInstance(); + calMonth = cal.get(Calendar.MONTH)+1; //From 1 to 12, and not from 0 to 11 + calYear = cal.get(Calendar.YEAR); + + + //Load today's sentence and set texts + IDFrase = db.getIDFraseHoy(); + + /* Refresh calendar, after load sentences for checks */ + robotoCalendarView.updateView(); + markDates(); + + txtfraseText.setText(db.getFraseFromID(IDFrase)); + txtfraseAutor.setText(db.getAutorFromID(IDFrase)); + + + // ListView Item Click Listener + txtfraseText.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View viewIn) { + ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE); + clipboard.setPrimaryClip(ClipData.newPlainText("Sentence", txtfraseText.getText()+MainActivity.this.getString(R.string.sharefrom))); + Toast.makeText(getApplicationContext(), "Copiado al portapapeles", Toast.LENGTH_LONG ).show(); + } + }); + } + + + /* Close app on back button */ + @Override + public void onBackPressed() + { + moveTaskToBack(true); + } + + + @Override + public void onCreateContextMenu(ContextMenu menu, View v, + ContextMenu.ContextMenuInfo menuInfo) { + super.onCreateContextMenu(menu, v, menuInfo); + MenuInflater inflater = getMenuInflater(); + inflater.inflate(R.menu.proverbmenu_add, menu); + } + + @Override + public boolean onContextItemSelected(MenuItem item) { + TextView txtfraseText = (TextView) findViewById(R.id.txt_frasetext); + String sentence = txtfraseText.getText().toString(); + switch (item.getItemId()) { + case R.id.copy: + ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE); + clipboard.setPrimaryClip(ClipData.newPlainText("Sentence", sentence+MainActivity.this.getString(R.string.sharefrom))); + Toast.makeText(getApplicationContext(), "Copiado al portapapeles", Toast.LENGTH_LONG ).show(); + return true; + case R.id.addfav: + db.addFav(IDFrase); + return true; + case R.id.share: + Intent intent = new Intent(Intent.ACTION_SEND); + intent.setType("text/plain"); + intent.putExtra(Intent.EXTRA_TEXT, sentence+MainActivity.this.getString(R.string.sharefrom)); + startActivity(Intent.createChooser(intent, "Compartir con")); + return true; + } + return false; + } + + + @Override + public void onDayClick(Calendar daySelectedCalendar) { + Integer month = daySelectedCalendar.get(Calendar.MONTH); + Integer day = daySelectedCalendar.get(Calendar.DAY_OF_MONTH); + Integer year = daySelectedCalendar.get(Calendar.YEAR); + month=month+1; //Now months start with 1 and not 0 + /* Load sentence */ + IDFrase = db.getIDFraseDay(year, month, day); + String frase = db.getFraseFromID(IDFrase); + txtfraseText.setText(frase); //Change text + txtfraseAutor.setText(db.getAutorFromID(IDFrase)); + /* Set Title before sentence */ + if (year != cal.get(Calendar.YEAR) || month != (cal.get(Calendar.MONTH)+1) || day != cal.get(Calendar.DAY_OF_MONTH)) { + txtfraseTitle.setText("Frase del " + day + " de " + getMonth(month)); //Change title + }else { + txtfraseTitle.setText(R.string.txt_todaysentence); //Change title (today) + } + //markDates(); TODO El programa borra el día seleccionado al hacerlo + } + + /** It returns the month name */ + public String getMonth(int month) { + String str = new DateFormatSymbols().getMonths()[month-1]; + return str.substring(0, 1).toUpperCase() + str.substring(1); + } + + @Override + public void onDayLongClick(Calendar daySelectedCalendar) { + onDayClick(daySelectedCalendar); + } + + public void markDates() { + robotoCalendarView.clearCalendar(); + + Calendar time = Calendar.getInstance(); + String[] IDDays = db.getAllDaysYet(); + if (IDDays.length != 0) { + for (int x = 0; x <= IDDays.length - 1; x++) { + //Log.d("Date", "String: " + String.valueOf(IDDays[x])); + Integer year = Integer.parseInt(IDDays[x].substring(0, 4)); + Integer month = Integer.parseInt(IDDays[x].substring(4, 6)); + Integer day = Integer.parseInt(IDDays[x].substring(6, 8)); + if (year.equals(calYear) && month.equals(calMonth)) { + time.set(Calendar.DAY_OF_MONTH, day); + time.set(Calendar.MONTH, month-1); + //Log.d("Date", "Marking: " + day); + robotoCalendarView.markCircleImage1(time); + } + } + } + } + + /* Overrides for month plus and minus */ + @Override + public void onRightButtonClick() { + calMonth += 1; + if (calMonth > 12){ + calMonth = 1; + calYear += 1; + } + markDates(); + } + + @Override + public void onLeftButtonClick() { + calMonth -= 1; + if (calMonth < 1){ + calMonth = 12; + calYear -= 1; + } + markDates(); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/jkanetwork/st/calendariodefrases/NotificationHelper.java b/app/src/main/java/com/jkanetwork/st/calendariodefrases/NotificationHelper.java new file mode 100644 index 0000000..859beb4 --- /dev/null +++ b/app/src/main/java/com/jkanetwork/st/calendariodefrases/NotificationHelper.java @@ -0,0 +1,83 @@ +package com.jkanetwork.st.calendariodefrases; + + + +import android.app.Notification; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.app.Service; +import android.content.Intent; +import android.graphics.BitmapFactory; +import android.os.IBinder; +import android.support.v7.app.NotificationCompat; +import android.util.Log; + + +/** + * Created by kprkpr on 20/03/17. + */ + +public class NotificationHelper extends Service { + private static final String TAG = "NotificationHelper"; + DatabaseHelper db = new DatabaseHelper(this); + + @Override + public IBinder onBind(Intent i) { + return null; + } + + @Override + public int onStartCommand(final Intent intent, int flags, int startId) { + + new Thread(new Runnable() { + + @Override + public void run() { + Log.d(TAG, "Service Started"); + // El servicio se finaliza a sí mismo cuando finaliza su + // trabajo. + final Config conf = new Config(NotificationHelper.this); + try { + // Instanciamos e inicializamos nuestro manager. + NotificationManager nm = (NotificationManager)getSystemService(NOTIFICATION_SERVICE); + nm.cancel(1); /* Cancel first */ + if (conf.getNotifOn().equals(true)) { /* Only set things if notification is enabled */ + Intent OpenIntent = new Intent(NotificationHelper.this, MainActivity.class); + PendingIntent notifIntent = PendingIntent.getActivity(NotificationHelper.this, 0, OpenIntent, 0); + + CharSequence ticker = "Frase del día"; + CharSequence contentTitle = "Frase de hoy:"; + CharSequence contentText = db.getFraseFromID(db.getIDFraseHoy()); + NotificationCompat.Builder notibuilder = (android.support.v7.app.NotificationCompat.Builder) new NotificationCompat.Builder(NotificationHelper.this) + .setContentIntent(notifIntent) + .setTicker(ticker) + .setContentTitle(contentTitle) + .setStyle(new NotificationCompat.BigTextStyle().bigText(contentText)) /* For big texts */ + .setContentText(contentText) /* For when bigText cant be show */ + .setLargeIcon(BitmapFactory.decodeResource(NotificationHelper.this.getResources(), R.mipmap.ic_launcher)); + /* If lollipop, new white icon, if not, grey icon */ + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP){ + notibuilder.setSmallIcon(R.drawable.notifwhite); + } else{ + notibuilder.setSmallIcon(R.drawable.notifgris); + } + + Notification noti = notibuilder.build(); + if (conf.getPersistNotifOn().equals(true)) { + noti.flags = Notification.FLAG_ONGOING_EVENT; + } + nm.notify(1, noti); + } + } catch (Exception e) { + e.printStackTrace(); + } + + } + }).start(); + Log.d(TAG, "Service Finished"); + this.stopSelf(); + return super.onStartCommand(intent, flags, startId); + } + + +} diff --git a/app/src/main/java/com/jkanetwork/st/calendariodefrases/OptsActivity.java b/app/src/main/java/com/jkanetwork/st/calendariodefrases/OptsActivity.java new file mode 100644 index 0000000..cd8a9fa --- /dev/null +++ b/app/src/main/java/com/jkanetwork/st/calendariodefrases/OptsActivity.java @@ -0,0 +1,138 @@ +package com.jkanetwork.st.calendariodefrases; + +import android.app.NotificationManager; +import android.content.Intent; +import android.os.Bundle; +import android.support.v7.app.AppCompatActivity; +import android.view.View; +import android.widget.ArrayAdapter; +import android.widget.Button; +import android.widget.CheckBox; +import android.widget.Spinner; + + +import java.util.ArrayList; +import java.util.List; + +import static java.lang.String.valueOf; + + +/** + * Created by kprkpr on 21/03/17. + */ + +public class OptsActivity extends AppCompatActivity { + + + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_opts); + final Config conf = new Config(this); + /* Do variables of objects */ + final Spinner spinnerHour = (Spinner) findViewById(R.id.spinnerHour); + final Spinner spinnerMinute = (Spinner) findViewById(R.id.spinnerMinute); + final CheckBox chkalarm = (CheckBox) findViewById(R.id.chk_alarm); + final CheckBox chkpersistent = (CheckBox) findViewById(R.id.chk_persistent); + /* Set texts and checks from configs */ + chkalarm.setChecked(conf.getNotifOn()); + chkpersistent.setChecked(conf.getPersistNotifOn()); + + // Hour and minute elements create + + // Spinner Drop down elements + List Hours = new ArrayList<>(); + for (int x = 0; x <= 23; x++) { + Hours.add(x); + } + List Minutes = new ArrayList<>(); + for (int x = 0; x <= 59; x++) { + Minutes.add(x); + } + // Creating adapter for spinner + ArrayAdapter hourAdapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, Hours); + ArrayAdapter minuteAdapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, Minutes); + // Drop down layout style - list view with radio button + hourAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + minuteAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + // attaching data adapter to spinner + spinnerHour.setAdapter(hourAdapter); + spinnerMinute.setAdapter(minuteAdapter); + + spinnerHour.setSelection(conf.getHour()); + spinnerMinute.setSelection(conf.getMinute()); + + + setEnabledParts(); + + /* Disable options if notification is disabled */ + chkalarm.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + setEnabledParts(); + } + }); + /* For not set date if persistent is enabled */ + chkpersistent.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + setEnabledParts(); + } + }); + + + Button btnsave = (Button) findViewById(R.id.btnSaveNotif); + btnsave.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + Integer hourSave, minuteSave; + + hourSave = Integer.decode(String.valueOf(spinnerHour.getSelectedItemPosition())); + + minuteSave = Integer.decode(String.valueOf(spinnerMinute.getSelectedItemPosition())); + + conf.setHour(hourSave); + conf.setMinute(minuteSave); + //Log.d("EnabledNotif", String.valueOf(chkalarm.isChecked())); + /* Enable or disable notification and persistent */ + conf.setNotifOn(chkalarm.isChecked()); + conf.setPersistNotifOn(chkpersistent.isChecked()); + + /* Cancel notif when save changes first */ + NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); + nm.cancel(1); + + Alarm alarm = new Alarm(); + alarm.putAlarm(OptsActivity.this); + if (chkpersistent.isChecked() && chkalarm.isChecked()) { + OptsActivity.this.startService(new Intent(OptsActivity.this, NotificationHelper.class)); + } + } + }); + + } + public void setEnabledParts(){ + /* I have to set vars again because is out of onCreate */ + Spinner notifHour = (Spinner) findViewById(R.id.spinnerHour); + Spinner notifMinute = (Spinner) findViewById(R.id.spinnerMinute); + CheckBox chkalarm = (CheckBox) findViewById(R.id.chk_alarm); + CheckBox chkpersistent = (CheckBox) findViewById(R.id.chk_persistent); + if (chkalarm.isChecked()){ + chkpersistent.setEnabled(true); + /* This other checks is chkpersistent checked dependent */ + if (chkpersistent.isChecked()){ + notifHour.setEnabled(false); + notifMinute.setEnabled(false); + }else{ + notifHour.setEnabled(true); + notifMinute.setEnabled(true); + } + }else{ + chkpersistent.setEnabled(false); + notifHour.setEnabled(false); + notifMinute.setEnabled(false); + } + } + +} diff --git a/app/src/main/res/drawable/cerebro.png b/app/src/main/res/drawable/cerebro.png new file mode 100644 index 0000000..5657afb Binary files /dev/null and b/app/src/main/res/drawable/cerebro.png differ diff --git a/app/src/main/res/drawable/fondo_opts.png b/app/src/main/res/drawable/fondo_opts.png new file mode 100644 index 0000000..f142aa7 Binary files /dev/null and b/app/src/main/res/drawable/fondo_opts.png differ diff --git a/app/src/main/res/drawable/notifgris.png b/app/src/main/res/drawable/notifgris.png new file mode 100644 index 0000000..1f04666 Binary files /dev/null and b/app/src/main/res/drawable/notifgris.png differ diff --git a/app/src/main/res/drawable/notifwhite.png b/app/src/main/res/drawable/notifwhite.png new file mode 100644 index 0000000..c295a06 Binary files /dev/null and b/app/src/main/res/drawable/notifwhite.png differ diff --git a/app/src/main/res/layout/activity_about.xml b/app/src/main/res/layout/activity_about.xml new file mode 100644 index 0000000..d07c3a6 --- /dev/null +++ b/app/src/main/res/layout/activity_about.xml @@ -0,0 +1,17 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_favs.xml b/app/src/main/res/layout/activity_favs.xml new file mode 100644 index 0000000..88708c6 --- /dev/null +++ b/app/src/main/res/layout/activity_favs.xml @@ -0,0 +1,10 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_first.xml b/app/src/main/res/layout/activity_first.xml new file mode 100644 index 0000000..70057e0 --- /dev/null +++ b/app/src/main/res/layout/activity_first.xml @@ -0,0 +1,20 @@ + + + + + +