Kaynağa Gözat

Merge branch 'master' into Location

Iñigo Valentin 9 yıl önce
ebeveyn
işleme
3d57e0e80e

+ 2 - 0
.gitignore

@@ -1,6 +1,8 @@
  
 # Built application files
 /*/build/
+build/android-profile/
+projectFilesBackup/
 
 # Crashlytics configuations
 com_crashlytics_export_strings.xml

+ 2 - 2
app/src/main/AndroidManifest.xml

@@ -2,8 +2,8 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
           xmlns:tools="http://schemas.android.com/tools"
           package="com.ivalentin.margolariak"
-    android:versionCode="19"
-    android:versionName="2.0.5" >
+    android:versionCode="24"
+    android:versionName="3.0.3" >
 
     <uses-permission android:name="android.permission.INTERNET" />
     <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>

+ 48 - 86
app/src/main/java/com/ivalentin/margolariak/AlarmReceiver.java

@@ -11,6 +11,7 @@ import android.content.SharedPreferences;
 import android.content.pm.PackageManager;
 import android.database.Cursor;
 import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteDatabaseLockedException;
 import android.graphics.BitmapFactory;
 import android.media.RingtoneManager;
 import android.support.v4.app.NotificationCompat;
@@ -59,11 +60,21 @@ public class AlarmReceiver extends BroadcastReceiver {
 				String o = fu.getOutput().toString();
 
 				//Open database
-				SQLiteDatabase db = context.openOrCreateDatabase(GM.DB.NAME, Activity.MODE_PRIVATE, null);
-				if (db.isReadOnly()){
-					Log.e("NOTIFICATIONS", "Database is locked and in read only mode.");
+				SQLiteDatabase db;
+				try {
+					db = context.openOrCreateDatabase(GM.DB.NAME, Activity.MODE_PRIVATE, null);
+					if (db.isReadOnly()) {
+						Log.e("NOTIFICATIONS", "Database is locked and in read only mode. Not reading new notifications now, but I'll try to sync.");
+						new Sync(context).execute(); // Sync before exiting.
+						return;
+					}
+				}
+				catch(SQLiteDatabaseLockedException ex){
+					Log.e("NOTIFICATIONS", "Database is locked and in read only mode. Not reading new notifications now, but I'll try to sync.");
+					new Sync(context).execute(); // Sync before exiting.
 					return;
 				}
+
 				Cursor cursor;
 
 				//Variables for parsing
@@ -82,12 +93,12 @@ public class AlarmReceiver extends BroadcastReceiver {
 
 					//Extract data
 					id = Integer.valueOf(not.substring(not.indexOf("\"id\":") + 6, not.indexOf("\",")));
-					title_es = not.substring(not.indexOf("\"title_es\":") + 12, not.indexOf("\"", not.indexOf("\"title_es\":") + 13));
-					title_en = not.substring(not.indexOf("\"title_en\":") + 12, not.indexOf("\"", not.indexOf("\"title_en\":") + 13));
-					title_eu = not.substring(not.indexOf("\"title_eu\":") + 12, not.indexOf("\"", not.indexOf("\"title_eu\":") + 13));
-					text_es = not.substring(not.indexOf("\"text_es\":") + 11, not.indexOf("\"", not.indexOf("\"text_es\":") + 12));
-					text_en = not.substring(not.indexOf("\"text_en\":") + 11, not.indexOf("\"", not.indexOf("\"text_en\":") + 12));
-					text_eu = not.substring(not.indexOf("\"text_eu\":") + 11, not.indexOf("\"", not.indexOf("\"text_eu\":") + 12));
+					title_es = decode(not.substring(not.indexOf("\"title_es\":") + 12, not.indexOf("\"", not.indexOf("\"title_es\":") + 13)));
+					title_en = decode(not.substring(not.indexOf("\"title_en\":") + 12, not.indexOf("\"", not.indexOf("\"title_en\":") + 13)));
+					title_eu = decode(not.substring(not.indexOf("\"title_eu\":") + 12, not.indexOf("\"", not.indexOf("\"title_eu\":") + 13)));
+					text_es = decode(not.substring(not.indexOf("\"text_es\":") + 11, not.indexOf("\"", not.indexOf("\"text_es\":") + 12)));
+					text_en = decode(not.substring(not.indexOf("\"text_en\":") + 11, not.indexOf("\"", not.indexOf("\"text_en\":") + 12)));
+					text_eu = decode(not.substring(not.indexOf("\"text_eu\":") + 11, not.indexOf("\"", not.indexOf("\"text_eu\":") + 12)));
 					dtime = not.substring(not.indexOf("\"dtime\":") + 9, not.indexOf("\"", not.indexOf("\"dtime\":") + 10));
 					action = not.substring(not.indexOf("\"action\":") + 10, not.indexOf("\"", not.indexOf("\"action\":") + 11));
 					gm = Integer.valueOf(not.substring(not.indexOf("\"gm\":") + 6, not.indexOf("\"", not.indexOf("\"gm\":") + 7)));
@@ -116,6 +127,9 @@ public class AlarmReceiver extends BroadcastReceiver {
 								break;
 						}
 
+						title = decode(title);
+						text = decode(text);
+
 						//Get the notification manager ready
 						NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
 
@@ -165,83 +179,6 @@ public class AlarmReceiver extends BroadcastReceiver {
 				}
 				db.close();
 
-
-
-
-				//Parse info
-				/*String o = fu.getOutput().toString();
-				while (o.contains("<notification>")){
-					//Get non-language-dependant fields
-					String notification = o.substring(o.indexOf("<notification>") + 14, o.indexOf("</notification>"));
-					String id = notification.substring(notification.indexOf("<id>") + 4, notification.indexOf("</id>"));
-					String action = notification.substring(notification.indexOf("<action>") + 8, notification.indexOf("</action>"));
-
-					//Is the notification seen already?
-					//TODO: Create a db table for this
-
-					//Get data from database
-					SQLiteDatabase db = SQLiteDatabase.openDatabase(context.getDatabasePath(GM.DB.NAME).getAbsolutePath(), null, SQLiteDatabase.NO_LOCALIZED_COLLATORS | SQLiteDatabase.OPEN_READONLY);
-					final Cursor cursor;
-					cursor = db.rawQuery("SELECT id, seen FROM notification WHERE id = " + id + ";", null);
-					if (cursor.getCount() == 0){
-
-					}
-					else {
-
-						if (cursor.getInt(1) == 0) {
-
-
-							String lang = GM.getLang();
-							String title = notification.substring(notification.indexOf("<title_" + lang + ">") + 10, notification.indexOf("</title_" + lang + ">"));
-							String text = notification.substring(notification.indexOf("<text_" + lang + ">") + 9, notification.indexOf("</text_" + lang + ">"));
-
-
-							//Get the notification manager ready
-							NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
-
-							//Variables to create intents for each notification
-							Intent resultIntent;
-							TaskStackBuilder stackBuilder;
-
-							//Send the notification.
-							NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context)
-									.setSmallIcon(R.drawable.ic_notification)
-									.setContentTitle(title)
-									.setAutoCancel(true)
-									.setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.drawable.ic_launcher))
-									.setVibrate((new long[]{400, 400, 400}))
-									.setColor(context.getResources().getColor(R.color.background_notification))
-									.setSubText(context.getString(R.string.app_name))
-									.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
-									.setContentText(text);
-
-							// Creates an intent for an Activity to be launched from the notification.
-							resultIntent = new Intent(context, MainActivity.class);
-							resultIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
-
-							//Set extras depending on type.
-							resultIntent.putExtra(GM.EXTRA.TEXT, text);
-							resultIntent.putExtra(GM.EXTRA.TITLE, title);
-							resultIntent.putExtra(GM.EXTRA.ACTION, action);
-
-							//Add the intent to the notification.
-							stackBuilder = TaskStackBuilder.create(context);
-							stackBuilder.addParentStack(MainActivity.class);
-
-							// Adds the Intent that starts the Activity to the top of the stack.
-							stackBuilder.addNextIntent(resultIntent);
-							PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
-							mBuilder.setContentIntent(resultPendingIntent);
-
-							//Actually send the notification.
-							mNotificationManager.notify(Integer.parseInt(id), mBuilder.build());
-
-							//Mark as notified
-							db.execSQL("UPDATE notification SET seen = 1 WHERE id = " + id);
-						}
-					}
-				o = o.substring(o.indexOf("</notification>") + 15);
-				}*/
 			}
 			catch(NumberFormatException ex) {
 				Log.e("NOTIFICATION", "Error parsing remote file: " + ex.toString());
@@ -255,6 +192,31 @@ public class AlarmReceiver extends BroadcastReceiver {
 		new Sync(context).execute();
     }
 
+		/**
+		 * Decodes unicode characters from a string.
+		 * Useful for JSON encoded strings.
+		 * @param in String to be decoded.
+		 * @return Decoded string.
+		 */
+		static final String decode(final String in){
+			String working = in;
+			int index = working.indexOf("\\u");
+			while(index > -1){
+				int length = working.length();
+					if(index > (length-6))
+						break;
+				int numStart = index + 2;
+				int numFinish = numStart + 4;
+				String substring = working.substring(numStart, numFinish);
+				int number = Integer.parseInt(substring,16);
+				String stringStart = working.substring(0, index);
+				String stringEnd   = working.substring(numFinish);
+				working = stringStart + ((char)number) + stringEnd;
+				index = working.indexOf("\\u");
+			}
+			return working;
+		}
+
     /**
      * Sets a repeating alarm. 
      * When the alarm fires, the app broadcasts an Intent to this WakefulBroadcastReceiver.

+ 10 - 2
app/src/main/java/com/ivalentin/margolariak/HomeLayout.java

@@ -34,6 +34,7 @@ import android.view.MenuItem;
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.view.ViewGroup;
+import android.widget.Button;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.TextView;
@@ -150,6 +151,7 @@ public class HomeLayout extends Fragment implements LocationListener {
 
 		//Views in each row
 		TextView tvRowTitle, tvRowTime, tvRowPlace, tvRowId;
+		Button btSchedule;
 
 		//Assign layouts
 		LinearLayout section, listNow, listNext, now, next, entry;
@@ -159,6 +161,13 @@ public class HomeLayout extends Fragment implements LocationListener {
 			listNext = (LinearLayout) view.findViewById(R.id.ll_home_section_gmschedule_later_list);
 			now = (LinearLayout) view.findViewById(R.id.ll_home_section_gmschedule_now_content);
 			next = (LinearLayout) view.findViewById(R.id.ll_home_section_gmschedule_later_content);
+			btSchedule = (Button) view.findViewById(R.id.bt_home_gm);
+			btSchedule.setOnClickListener(new OnClickListener() {
+				@Override
+				public void onClick(View v) {
+					((MainActivity) getActivity()).loadSection(GM.SECTION.GM_SCHEDULE);
+				}
+			});
 
 		} else {
 			section = (LinearLayout) view.findViewById(R.id.ll_home_section_cityschedule);
@@ -205,8 +214,7 @@ public class HomeLayout extends Fragment implements LocationListener {
 
 			//Set time
 			tvRowTime = (TextView) entry.findViewById(R.id.tv_row_home_schedule_time);
-			String tm = cursorNow.getString(4).substring(cursorNow.getString(4).length() - 8, cursorNow.getString(4).length() - 3);
-			tvRowTime.setText(tm);
+			tvRowTime.setVisibility(View.GONE);
 
 			//Add the view
 			listNow.addView(entry);

+ 1 - 1
app/src/main/java/com/ivalentin/margolariak/MainActivity.java

@@ -243,7 +243,7 @@ public class MainActivity extends Activity {
 
 			case GM.SECTION.SCHEDULE:
 				fragment = new ScheduleLayout();
-				bundle.putInt(GM.SCHEDULE.KEY, GM.SCHEDULE.MARGOLARIAK);
+				bundle.putInt(GM.SCHEDULE.KEY, GM.SCHEDULE.CITY);
 				fragment.setArguments(bundle);
 				title = getString(R.string.menu_lablanca_schedule);
 				shareURL = GM.SHARE.LABLANCA;

+ 13 - 9
app/src/main/java/com/ivalentin/margolariak/ScheduleLayout.java

@@ -55,7 +55,7 @@ public class ScheduleLayout extends Fragment implements OnMapReadyCallback{
 
 	private Bundle bund;
 
-	private final String dates[] = new String[20];
+	private final String dates[] = new String[40];
 	private int dateCount = 0;
 	private int selected = 0;
 
@@ -87,8 +87,6 @@ public class ScheduleLayout extends Fragment implements OnMapReadyCallback{
 		String year = Integer.toString(calendar.get(Calendar.YEAR));
 
 
-
-
 		//Set bundle for the map
 		bund = savedInstanceState;
 		
@@ -104,14 +102,19 @@ public class ScheduleLayout extends Fragment implements OnMapReadyCallback{
 		});
 
 		//Get schedule type
+		TextView title = (TextView) view.findViewById(R.id.tv_schedule_type);
 		Bundle bundle = this.getArguments();
 		schedule = bundle.getInt(GM.SCHEDULE.KEY, GM.SCHEDULE.CITY);
 		
 		//Set the title
-		if (schedule == GM.SCHEDULE.CITY)
+		if (schedule == GM.SCHEDULE.CITY) {
 			((MainActivity) getActivity()).setSectionTitle(view.getContext().getString(R.string.menu_lablanca_schedule));
-		else
+			title.setText(R.string.menu_lablanca_schedule);
+		}
+		else{
 			((MainActivity) getActivity()).setSectionTitle(view.getContext().getString(R.string.menu_lablanca_gm_schedule));
+			title.setText(R.string.menu_lablanca_gm_schedule);
+		}
 		((MainActivity) getActivity()).setShareLink(getString(R.string.share_lablanca), GM.SHARE.LABLANCA);
 
 		//Populate the dates array
@@ -132,10 +135,11 @@ public class ScheduleLayout extends Fragment implements OnMapReadyCallback{
 
 		//Log.e("Cur Date", curDate);
 		while (cursor.moveToNext()){
-			dates[dateCount] = cursor.getString(0);
-			//TODO: Check if some date is of today, and set selected
-			if (curDate.equals(cursor.getString(0))){
-				selected = dateCount;
+			if (dateCount < 40) {
+				dates[dateCount] = cursor.getString(0);
+				if (curDate.equals(cursor.getString(0))) {
+					selected = dateCount;
+				}
 			}
 			dateCount ++;
 		}

+ 52 - 23
app/src/main/java/com/ivalentin/margolariak/Sync.java

@@ -19,6 +19,7 @@ import android.content.SharedPreferences;
 import android.database.Cursor;
 import android.database.DatabaseUtils;
 import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteDatabaseLockedException;
 import android.graphics.Color;
 import android.graphics.drawable.ColorDrawable;
 import android.os.AsyncTask;
@@ -75,7 +76,7 @@ class Sync extends AsyncTask<Void, Void, Void> {
 
 			//Show the dialog and assign the elements on it
 			dialog.show();
-			strings = new String[10];
+			strings = new String[15];
 			strings[0] = myContextRef.getString(R.string.dialog_sync_text_0);
 			strings[1] = myContextRef.getString(R.string.dialog_sync_text_1);
 			strings[2] = myContextRef.getString(R.string.dialog_sync_text_2);
@@ -85,9 +86,14 @@ class Sync extends AsyncTask<Void, Void, Void> {
 			strings[6] = myContextRef.getString(R.string.dialog_sync_text_6);
 			strings[7] = myContextRef.getString(R.string.dialog_sync_text_7);
 			strings[8] = myContextRef.getString(R.string.dialog_sync_text_8);
-			strings[9] = myContextRef.getString(R.string.dialog_sync_text_8); //In case I get a 9;
+			strings[9] = myContextRef.getString(R.string.dialog_sync_text_9);
+			strings[10] = myContextRef.getString(R.string.dialog_sync_text_10);
+			strings[11] = myContextRef.getString(R.string.dialog_sync_text_11);
+			strings[12] = myContextRef.getString(R.string.dialog_sync_text_12);
+			strings[13] = myContextRef.getString(R.string.dialog_sync_text_13);
+			strings[14] = myContextRef.getString(R.string.dialog_sync_text_0); //In case I get a 13;
 			tv = (TextView) dialog.findViewById(R.id.tv_dialog_sync_text);
-			int idx = (int) (Math.random() * 9);
+			int idx = (int) (Math.random() * 13);
 			tv.setText(strings[idx]);
 			doProgress = true;
 
@@ -238,9 +244,9 @@ class Sync extends AsyncTask<Void, Void, Void> {
 	 */
 	protected void onProgressUpdate(Void...progress) {
 		if (doProgress){
-			if (millis + 600 < System.currentTimeMillis()) {
+			if (millis + 900 < System.currentTimeMillis()) {
 				millis = System.currentTimeMillis();
-				int idx = (int) (Math.random() * ((4) + 1));
+				int idx = (int) (Math.random() * 13);
 				tv.setText(strings[idx]);
 			}
 		}
@@ -287,6 +293,7 @@ class Sync extends AsyncTask<Void, Void, Void> {
 	private boolean recreateDb(SQLiteDatabase db) {
 		boolean result = true;
 		try {
+			db.beginTransactionNonExclusive();
 			db.execSQL(GM.DB.QUERY.DROP.ACTIVITY);
 			db.execSQL(GM.DB.QUERY.DROP.ACTIVITY_COMMENT);
 			db.execSQL(GM.DB.QUERY.DROP.ACTIVITY_IMAGE);
@@ -310,8 +317,10 @@ class Sync extends AsyncTask<Void, Void, Void> {
 			db.execSQL(GM.DB.QUERY.DROP.SETTINGS);
 			db.execSQL(GM.DB.QUERY.DROP.SPONSOR);
 			db.execSQL(GM.DB.QUERY.DROP.VERSION);
-			//TODO: Is this really necessary?
-			Thread.sleep(1000);
+			db.setTransactionSuccessful();
+			db.endTransaction();
+			publishProgress();
+			db.beginTransactionNonExclusive();
 			db.execSQL(GM.DB.QUERY.CREATE.ACTIVITY);
 			db.execSQL(GM.DB.QUERY.CREATE.ACTIVITY_COMMENT);
 			db.execSQL(GM.DB.QUERY.CREATE.ACTIVITY_IMAGE);
@@ -335,10 +344,8 @@ class Sync extends AsyncTask<Void, Void, Void> {
 			db.execSQL(GM.DB.QUERY.CREATE.SETTINGS);
 			db.execSQL(GM.DB.QUERY.CREATE.SPONSOR);
 			db.execSQL(GM.DB.QUERY.CREATE.VERSION);
-			//TODO: Is this really necessary?
-			Thread.sleep(1000);
-		} catch (InterruptedException e) {
-			Log.e("SYNC", "Couldn't wait for the database to be recreated: " + e.toString());
+			db.setTransactionSuccessful();
+			db.endTransaction();
 		}
 		catch (Exception ex) {
 			result = false;
@@ -406,6 +413,7 @@ class Sync extends AsyncTask<Void, Void, Void> {
 				keys[totalVersions] = key;
 				values[totalVersions] = value;
 				totalVersions ++;
+				publishProgress();
 			}
 			if (totalVersions > 0 && totalVersions < 99){
 				db.execSQL(GM.DB.QUERY.CREATE.VERSION);
@@ -462,6 +470,7 @@ class Sync extends AsyncTask<Void, Void, Void> {
 					Log.d("SYNC", "End of data string:" + ex.toString());
 					str = "";
 				}
+				publishProgress();
 			}
 		}
 		catch (Exception ex){
@@ -523,6 +532,7 @@ class Sync extends AsyncTask<Void, Void, Void> {
 			}
 
 			editor.apply();
+			publishProgress();
 			Log.d("SYNC", "Settings saved.");
 			return true;
 		}
@@ -595,7 +605,7 @@ class Sync extends AsyncTask<Void, Void, Void> {
 				//Loop trough values
 				for (int j = 0; j < i; j++) {
 
-					//If the value is empty, I dont care what tipe is it, it will be 'null'.
+					//If the value is empty, I don't care what type is it, it will be 'null'.
 					if (values[j].length() == 0) {
 						val = "null";
 						q = q + val + ", ";
@@ -646,6 +656,8 @@ class Sync extends AsyncTask<Void, Void, Void> {
 
 			//Process str for the next loop pass.
 			str = str.substring(str.indexOf("\"}") + 2);
+
+			publishProgress();
 		}
 
 		//If I get to this point, there were no errors, and I can safely execute the queries
@@ -676,19 +688,33 @@ class Sync extends AsyncTask<Void, Void, Void> {
 		String userCode = preferences.getString(GM.DATA.KEY.USER, GM.DATA.DEFAULT.USER);
 
 		//Get database. Stop if it's locked
-		SQLiteDatabase db = myContextRef.openOrCreateDatabase(GM.DB.NAME, Activity.MODE_PRIVATE, null);
-		if (db.isReadOnly()){
+		SQLiteDatabase db;
+		try {
+			db = myContextRef.openOrCreateDatabase(GM.DB.NAME, Activity.MODE_PRIVATE, null);
+			if (db.isReadOnly()) {
+				Log.e("SYNC", "Database is locked and in read only mode. Skipping sync.");
+				return null;
+			}
+		}
+		catch(SQLiteDatabaseLockedException ex){
 			Log.e("SYNC", "Database is locked and in read only mode. Skipping sync.");
 			return null;
 		}
 
+		publishProgress();
+
 		//Get database version
 		Cursor cursor;
-		int dbVersion;
-		cursor = db.rawQuery("SELECT sum(version) AS v FROM version;", null);
-		cursor.moveToFirst();
-		dbVersion = cursor.getInt(0);
-		cursor.close();
+		int dbVersion = 0;
+		try{
+			cursor = db.rawQuery("SELECT sum(version) AS v FROM version;", null);
+			cursor.moveToFirst();
+			dbVersion = cursor.getInt(0);
+			cursor.close();
+		}
+		catch (Exception e){
+			Log.e("SYNC", "Unable to read from table 'version': " + e.toString());
+		}
 
 		URL url;
 		String uri = buildUrl(userCode, dbVersion, fg, GM.getLang());
@@ -716,6 +742,8 @@ class Sync extends AsyncTask<Void, Void, Void> {
 					while ((o = br.readLine()) != null)
 						sb.append(o);
 
+					publishProgress();
+
 					//Get the string with the sync json. (The whole page)
 					String strSync = sb.toString();
 					strSync = strSync.replace(":null", ":\"\"");
@@ -733,11 +761,11 @@ class Sync extends AsyncTask<Void, Void, Void> {
 					String strData = strSync.substring(1, strSync.length() - 1);
 					strData = strData.substring(strData.indexOf("{\"data\":"));
 
+					publishProgress();
+
 					//If the data is correctly parsed and stored, commit changes to the database.
-					db.beginTransaction();
+					db.beginTransactionNonExclusive();
 
-					//TODO: for save version apps, this is not needed, but I have to check it after an app update.
-					//recreateDb(db);
 
 					if (saveVersions(db, strVersion) && saveData(db, strData)){
 						db.setTransactionSuccessful();
@@ -753,6 +781,7 @@ class Sync extends AsyncTask<Void, Void, Void> {
 					Log.e("SYNC", "The server returned an unexpected code (" + httpCode + ") for the url \"" + uri + "\"");
 			}
 
+			publishProgress();
 			urlConnection.disconnect();
 			return null;
 
@@ -774,4 +803,4 @@ class Sync extends AsyncTask<Void, Void, Void> {
 		return null;
     	
 	}
-}
+}

+ 92 - 92
app/src/main/res/layout/activity_main.xml

@@ -90,54 +90,54 @@
 	<!-- The part where the fragments will be loaded -->
 
 	<HorizontalScrollView
-		android:layout_width="wrap_content"
-		android:layout_height="55dp"
 		android:id="@+id/sv_menu"
-		android:scrollIndicators="none"
-		android:requiresFadingEdge="horizontal"
-		android:fadingEdgeLength="80dp"
+		android:layout_width="match_parent"
+		android:layout_height="55dp"
 		android:background="@color/background_menu"
+		android:fadingEdgeLength="80dp"
+		android:requiresFadingEdge="horizontal"
+		android:scrollIndicators="none"
 		tools:ignore="UnusedAttribute">
 
 		<LinearLayout
-			android:orientation="horizontal"
 			android:layout_width="wrap_content"
 			android:layout_height="match_parent"
-			android:layout_marginBottom="1dp">
+			android:layout_marginBottom="1dp"
+			android:orientation="horizontal">
 
 			<RelativeLayout
-				android:orientation="vertical"
+				android:id="@+id/rl_menu_home"
 				android:layout_width="100dp"
 				android:layout_height="match_parent"
-				android:id="@+id/rl_menu_home"
+				android:layout_marginLeft="0.5dp"
 				android:layout_marginRight="0.5dp"
-				android:layout_marginLeft="0.5dp">
+				android:orientation="vertical">
 
 				<TextView
+					android:id="@+id/tv_menu_home"
 					android:layout_width="wrap_content"
 					android:layout_height="wrap_content"
-					android:textAppearance="?android:attr/textAppearanceMedium"
-					android:text="@string/menu_home"
+					android:layout_centerInParent="true"
 					android:layout_gravity="top"
+					android:text="@string/menu_home"
+					android:textAppearance="?android:attr/textAppearanceMedium"
+					android:textColor="@color/menu_entry"
 					android:textSize="15sp"
-					android:layout_centerInParent="true"
-					android:textStyle="bold"
-					android:id="@+id/tv_menu_home"
-					android:textColor="@color/menu_entry"/>
+					android:textStyle="bold"/>
 
 				<ImageView
-					android:layout_width="match_parent"
 					android:id="@+id/iv_menu_home"
-					android:background="@color/menu_selected"
-					android:alpha="1"
-					android:layout_gravity="bottom"
-					android:layout_alignParentStart="false"
+					android:layout_width="match_parent"
+					android:layout_height="7dp"
+					android:layout_alignParentBottom="true"
 					android:layout_alignParentEnd="false"
 					android:layout_alignParentLeft="false"
 					android:layout_alignParentRight="false"
-					android:layout_alignParentBottom="true"
-					tools:ignore="ContentDescription"
-					android:layout_height="7dp"/>
+					android:layout_alignParentStart="false"
+					android:layout_gravity="bottom"
+					android:alpha="1"
+					android:background="@color/menu_selected"
+					tools:ignore="ContentDescription"/>
 			</RelativeLayout>
 
 			<RelativeLayout
@@ -176,139 +176,139 @@
 			</RelativeLayout>
 
 			<RelativeLayout
-				android:orientation="vertical"
+				android:id="@+id/rl_menu_lablanca"
 				android:layout_width="100dp"
 				android:layout_height="match_parent"
-				android:id="@+id/rl_menu_lablanca"
 				android:layout_marginLeft="1dp"
-				android:layout_marginRight="1dp">
+				android:layout_marginRight="1dp"
+				android:orientation="vertical">
 
 				<TextView
+					android:id="@+id/tv_menu_lablanca"
 					android:layout_width="wrap_content"
 					android:layout_height="wrap_content"
-					android:textAppearance="?android:attr/textAppearanceMedium"
-					android:text="@string/menu_lablanca"
-					android:layout_gravity="top"
-					android:textSize="15sp"
 					android:layout_centerInParent="true"
-					android:id="@+id/tv_menu_lablanca"
-					android:textColor="@color/menu_entry"/>
+					android:layout_gravity="top"
+					android:text="@string/menu_lablanca"
+					android:textAppearance="?android:attr/textAppearanceMedium"
+					android:textColor="@color/menu_entry"
+					android:textSize="15sp"/>
 
 				<ImageView
-					android:layout_width="match_parent"
 					android:id="@+id/iv_menu_lablanca"
-					android:background="@color/menu_selected"
-					android:alpha="1"
-					android:layout_gravity="bottom"
-					android:layout_alignParentStart="false"
+					android:layout_width="match_parent"
+					android:layout_height="3dp"
+					android:layout_alignParentBottom="true"
 					android:layout_alignParentEnd="false"
 					android:layout_alignParentLeft="false"
 					android:layout_alignParentRight="false"
-					android:layout_alignParentBottom="true"
-					tools:ignore="ContentDescription"
-					android:layout_height="3dp"/>
+					android:layout_alignParentStart="false"
+					android:layout_gravity="bottom"
+					android:alpha="1"
+					android:background="@color/menu_selected"
+					tools:ignore="ContentDescription"/>
 			</RelativeLayout>
 
 			<RelativeLayout
-				android:orientation="vertical"
+				android:id="@+id/rl_menu_activities"
 				android:layout_width="100dp"
 				android:layout_height="match_parent"
-				android:id="@+id/rl_menu_activities"
 				android:layout_marginLeft="1dp"
-				android:layout_marginRight="1dp">
+				android:layout_marginRight="1dp"
+				android:orientation="vertical">
 
 				<TextView
+					android:id="@+id/tv_menu_activities"
 					android:layout_width="wrap_content"
 					android:layout_height="wrap_content"
-					android:textAppearance="?android:attr/textAppearanceMedium"
-					android:text="@string/menu_activities"
-					android:layout_gravity="top"
-					android:textSize="15sp"
 					android:layout_centerInParent="true"
-					android:id="@+id/tv_menu_activities"
-					android:textColor="@color/menu_entry"/>
+					android:layout_gravity="top"
+					android:text="@string/menu_activities"
+					android:textAppearance="?android:attr/textAppearanceMedium"
+					android:textColor="@color/menu_entry"
+					android:textSize="15sp"/>
 
 				<ImageView
-					android:layout_width="match_parent"
 					android:id="@+id/iv_menu_activities"
-					android:background="@color/menu_selected"
-					android:alpha="1"
-					android:layout_gravity="bottom"
-					android:layout_alignParentStart="false"
+					android:layout_width="match_parent"
+					android:layout_height="3dp"
+					android:layout_alignParentBottom="true"
 					android:layout_alignParentEnd="false"
 					android:layout_alignParentLeft="false"
 					android:layout_alignParentRight="false"
-					android:layout_alignParentBottom="true"
-					tools:ignore="ContentDescription"
-					android:layout_height="3dp"/>
+					android:layout_alignParentStart="false"
+					android:layout_gravity="bottom"
+					android:alpha="1"
+					android:background="@color/menu_selected"
+					tools:ignore="ContentDescription"/>
 			</RelativeLayout>
 
 			<RelativeLayout
-				android:orientation="vertical"
+				android:id="@+id/rl_menu_blog"
 				android:layout_width="100dp"
 				android:layout_height="match_parent"
-				android:id="@+id/rl_menu_blog"
 				android:layout_marginLeft="1dp"
-				android:layout_marginRight="1dp">
+				android:layout_marginRight="1dp"
+				android:orientation="vertical">
 
 				<TextView
+					android:id="@+id/tv_menu_blog"
 					android:layout_width="wrap_content"
 					android:layout_height="wrap_content"
-					android:textAppearance="?android:attr/textAppearanceMedium"
-					android:text="@string/menu_blog"
-					android:layout_gravity="top"
-					android:textSize="15sp"
 					android:layout_centerInParent="true"
-					android:id="@+id/tv_menu_blog"
-					android:textColor="@color/menu_entry"/>
+					android:layout_gravity="top"
+					android:text="@string/menu_blog"
+					android:textAppearance="?android:attr/textAppearanceMedium"
+					android:textColor="@color/menu_entry"
+					android:textSize="15sp"/>
 
 				<ImageView
-					android:layout_width="match_parent"
 					android:id="@+id/iv_menu_blog"
-					android:background="@color/menu_selected"
-					android:alpha="1"
-					android:layout_gravity="bottom"
-					android:layout_alignParentStart="false"
+					android:layout_width="match_parent"
+					android:layout_height="3dp"
+					android:layout_alignParentBottom="true"
 					android:layout_alignParentEnd="false"
 					android:layout_alignParentLeft="false"
 					android:layout_alignParentRight="false"
-					android:layout_alignParentBottom="true"
-					tools:ignore="ContentDescription"
-					android:layout_height="3dp"/>
+					android:layout_alignParentStart="false"
+					android:layout_gravity="bottom"
+					android:alpha="1"
+					android:background="@color/menu_selected"
+					tools:ignore="ContentDescription"/>
 			</RelativeLayout>
 
 			<RelativeLayout
-				android:orientation="vertical"
+				android:id="@+id/rl_menu_gallery"
 				android:layout_width="100dp"
 				android:layout_height="match_parent"
-				android:id="@+id/rl_menu_gallery"
 				android:layout_marginLeft="1dp"
-				android:layout_marginRight="1dp">
+				android:layout_marginRight="1dp"
+				android:orientation="vertical">
 
 				<TextView
+					android:id="@+id/tv_menu_gallery"
 					android:layout_width="wrap_content"
 					android:layout_height="wrap_content"
-					android:textAppearance="?android:attr/textAppearanceMedium"
-					android:text="@string/menu_gallery"
-					android:layout_gravity="top"
-					android:textSize="15sp"
 					android:layout_centerInParent="true"
-					android:id="@+id/tv_menu_gallery"
-					android:textColor="@color/menu_entry"/>
+					android:layout_gravity="top"
+					android:text="@string/menu_gallery"
+					android:textAppearance="?android:attr/textAppearanceMedium"
+					android:textColor="@color/menu_entry"
+					android:textSize="15sp"/>
 
 				<ImageView
-					android:layout_width="match_parent"
 					android:id="@+id/iv_menu_gallery"
-					android:background="@color/menu_selected"
-					android:alpha="1"
-					android:layout_gravity="bottom"
-					android:layout_alignParentStart="false"
+					android:layout_width="match_parent"
+					android:layout_height="3dp"
+					android:layout_alignParentBottom="true"
 					android:layout_alignParentEnd="false"
 					android:layout_alignParentLeft="false"
 					android:layout_alignParentRight="false"
-					android:layout_alignParentBottom="true"
-					tools:ignore="ContentDescription"
-					android:layout_height="3dp"/>
+					android:layout_alignParentStart="false"
+					android:layout_gravity="bottom"
+					android:alpha="1"
+					android:background="@color/menu_selected"
+					tools:ignore="ContentDescription"/>
 			</RelativeLayout>
 
 		</LinearLayout>

+ 52 - 30
app/src/main/res/layout/fragment_layout_home.xml

@@ -85,64 +85,86 @@
 		</LinearLayout>
 
 		<LinearLayout
-			android:orientation="vertical"
+			android:id="@+id/ll_home_section_lablanca"
 			android:layout_width="match_parent"
 			android:layout_height="wrap_content"
-			android:background="@drawable/section"
-			android:id="@+id/ll_home_section_lablanca"
 			android:layout_margin="10dp"
+			android:background="@drawable/section"
+			android:orientation="vertical"
 			android:visibility="gone">
 
 			<TextView
 				android:layout_width="match_parent"
 				android:layout_height="wrap_content"
-				android:textAppearance="?android:attr/textAppearanceLarge"
-				android:text="@string/lablanca_title"
-				android:textStyle="bold"
-				android:textColor="@color/section_title"
+				android:background="@drawable/section_title"
 				android:paddingBottom="4dp"
 				android:paddingEnd="10dp"
 				android:paddingLeft="20dp"
 				android:paddingRight="10dp"
 				android:paddingStart="20dp"
 				android:paddingTop="4dp"
-				android:background="@drawable/section_title"/>
+				android:text="@string/lablanca_title"
+				android:textAppearance="?android:attr/textAppearanceLarge"
+				android:textColor="@color/section_title"
+				android:textStyle="bold"/>
 
 			<LinearLayout
-				android:orientation="horizontal"
 				android:layout_width="match_parent"
 				android:layout_height="match_parent"
+				android:layout_margin="8dp"
 				android:background="@drawable/entry"
-				android:padding="7dp"
-				android:layout_margin="8dp">
+				android:orientation="horizontal"
+				android:padding="7dp">
 
 				<ImageView
-					android:layout_width="wrap_content"
-					android:layout_height="wrap_content"
 					android:id="@+id/iv_home_section_lablanca_image"
-					android:contentDescription="@string/app_cdesc"
-					android:layout_weight=".4"
+					android:layout_width="match_parent"
+					android:layout_height="wrap_content"
 					android:layout_margin="3dp"
+					android:layout_weight=".7"
 					android:adjustViewBounds="true"
-					android:maxWidth="130dp"/>
-
-				<TextView
-					android:layout_width="wrap_content"
-					android:layout_height="wrap_content"
-					android:textAppearance="@android:style/TextAppearance.Medium"
-					android:id="@+id/tv_home_section_lablanca_text"
-					android:layout_weight=".6"
-					android:padding="7dp"
-					android:maxLines="4"/>
+					android:contentDescription="@string/app_cdesc"
+					android:maxWidth="130dp"
+					android:minHeight="105dp"/>
 
-				<ImageView
+				<LinearLayout
 					android:layout_width="match_parent"
-					android:layout_weight="1"
-					android:layout_height="40dp"
-					android:layout_marginTop="-40dp"
-					android:background="@drawable/gradient_v_white"/>
+					android:layout_height="match_parent"
+					android:layout_weight=".3"
+					android:orientation="vertical"
+					>
+
+					<TextView
+						android:id="@+id/tv_home_section_lablanca_text"
+						android:layout_width="match_parent"
+						android:layout_height="80dp"
+						android:maxLines="4"
+						android:padding="7dp"
+						android:textAppearance="@android:style/TextAppearance.Medium"/>
+
+					<ImageView
+						android:id="@+id/imageView6"
+						android:layout_width="match_parent"
+						android:layout_height="40dp"
+						android:layout_marginTop="-40dp"
+						android:background="@drawable/gradient_v_white"/>
+
+					<Button
+						android:id="@+id/bt_home_gm"
+						android:layout_width="match_parent"
+						android:layout_height="50dp"
+						android:layout_marginBottom="40dp"
+						android:layout_marginLeft="7dp"
+						android:layout_marginStart="7dp"
+						android:layout_marginTop="10dp"
+						android:background="@drawable/button_selector"
+						android:text="@string/lablanca_schedule_gm"
+						android:textColor="@color/input_button_color"
+						android:textStyle="bold"/>
+				</LinearLayout>
 
 			</LinearLayout>
+
 		</LinearLayout>
 
 		<LinearLayout

+ 12 - 9
app/src/main/res/layout/fragment_layout_schedule.xml

@@ -17,12 +17,9 @@
         android:layout_margin="7dp">
 
         <TextView
-            android:text="@string/lablanca_schedule_gm"
+            android:id="@+id/tv_schedule_type"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:textAppearance="?android:attr/textAppearanceLarge"
-            android:textStyle="bold"
-            tools:layout_width="match_parent"
             android:background="@drawable/section_title"
             android:paddingBottom="4dp"
             android:paddingEnd="10dp"
@@ -30,7 +27,11 @@
             android:paddingRight="10dp"
             android:paddingStart="20dp"
             android:paddingTop="4dp"
-            android:textColor="@color/section_title"/>
+            android:text="@string/lablanca_schedule_gm"
+            android:textAppearance="?android:attr/textAppearanceLarge"
+            android:textColor="@color/section_title"
+            android:textStyle="bold"
+            tools:layout_width="match_parent"/>
 
         <LinearLayout
             android:layout_width="match_parent"
@@ -130,15 +131,17 @@
             android:id="@+id/sv_schedule"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
+            android:layout_margin="7dp"
+            android:background="@drawable/entry"
             android:orientation="vertical"
-            android:padding="7dp">
+            android:padding="2dp">
 
             <LinearLayout
-                android:orientation="vertical"
                 android:layout_width="match_parent"
                 android:layout_height="match_parent"
-                android:background="@drawable/entry"
-                android:padding="7dp">
+                android:layout_margin="0dp"
+                android:orientation="vertical"
+                >
 
                 <LinearLayout
                     android:id="@+id/ll_schedule_list"

+ 40 - 22
app/src/main/res/layout/row_home_schedule.xml

@@ -1,11 +1,18 @@
 <LinearLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     xmlns:tools="http://schemas.android.com/tools"
     android:layout_width="fill_parent"
     android:layout_height="wrap_content"
-    android:orientation="vertical"
     android:layout_margin="8dp"
-    android:padding="7dp">
+    android:orientation="vertical"
+    android:padding="7dp"
+    android:paddingBottom="7dp"
+    android:paddingEnd="7dp"
+    android:paddingLeft="25dp"
+    android:paddingRight="7dp"
+    android:paddingStart="25dp"
+    android:paddingTop="7dp">
 
     <TextView
         android:id="@+id/tv_row_home_schedule_id"
@@ -14,49 +21,60 @@
         android:visibility="gone"/>
 
     <LinearLayout
-        android:orientation="horizontal"
         android:layout_width="fill_parent"
-        android:layout_height="wrap_content">
+        android:layout_height="wrap_content"
+        android:orientation="horizontal">
 
         <TextView
-            android:id="@+id/tv_row_home_schedule_title"
-            android:layout_width="fill_parent"
+            android:id="@+id/tv_row_home_schedule_time"
+            android:layout_width="75dp"
             android:layout_height="wrap_content"
-            android:textAppearance="@android:style/TextAppearance.Large"
-            android:layout_weight=".3"
-            android:maxLines="2"/>
+            android:minWidth="75dp"
+            android:text="0000"
+            android:textAlignment="textEnd"
+            android:textAppearance="@android:style/TextAppearance.Medium"
+            android:textStyle="bold"/>
+
+        <ImageView
+            android:id="@+id/imageView5"
+            android:layout_width="15dp"
+            android:layout_height="match_parent"
+            android:layout_marginEnd="8dp"
+            android:layout_marginLeft="8dp"
+            android:layout_marginRight="8dp"
+            android:layout_marginStart="8dp"
+            android:adjustViewBounds="true"
+            android:src="@drawable/schedule_point"/>
 
         <TextView
-            android:id="@+id/tv_row_home_schedule_time"
-            android:layout_width="fill_parent"
+            android:id="@+id/tv_row_home_schedule_title"
+            android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_marginStart="20dp"
-            android:textAppearance="@android:style/TextAppearance.Medium"
-            android:minWidth="75dp"
-            android:layout_weight=".7"
-            android:textAlignment="textEnd"/>
+            android:maxLines="2"
+            android:textAppearance="@android:style/TextAppearance.Medium"/>
+
     </LinearLayout>
 
     <LinearLayout
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:layout_marginBottom="25dp"
-        android:layout_marginLeft="15dp"
-        android:layout_marginStart="15dp"
+        android:layout_marginBottom="10dp"
+        android:layout_marginLeft="55dp"
+        android:layout_marginStart="55dp"
         android:layout_marginTop="5dp"
         android:gravity="center_vertical"
         tools:ignore="UseCompoundDrawables">
 
         <ImageView
             android:id="@+id/iv_row_home_schedule_pinpoint"
-            android:layout_width="30dp"
-            android:layout_height="30dp"
+            android:layout_width="20dp"
+            android:layout_height="20dp"
             android:layout_gravity="center_vertical"
             android:adjustViewBounds="true"
             android:contentDescription="@string/app_cdesc"
             android:maxHeight="30dp"
             android:maxWidth="30dp"
-            android:src="@drawable/pinpoint" />
+            android:src="@drawable/pinpoint"/>
 
         <TextView
             android:id="@+id/tv_row_home_schedule_place"

+ 5 - 0
app/src/main/res/values-en/strings.xml

@@ -156,6 +156,11 @@
 	<string name="dialog_sync_text_6">Ari ari ari!</string>
 	<string name="dialog_sync_text_7">Llegando tarde…</string>
 	<string name="dialog_sync_text_8">¿Cabe más gente en el Foro Margolari?</string>
+	<string name="dialog_sync_text_9">Arreglando el tirador de cerveza...</string>
+	<string name="dialog_sync_text_10">Descorchando botellas...</string>
+	<string name="dialog_sync_text_11">Repartiendo pulseras...</string>
+	<string name="dialog_sync_text_12">Pintando las fiestas...</string>
+	<string name="dialog_sync_text_13">Desplegando pancarta...</string>
 	<string name="dialog_sync_failed_title">Synchronization failed</string>
 	<string name="dialog_sync_failed_text">Couldn\'t download content.\n\nMake sure you have a network connection and try again.</string>
 	<string name="dialog_sync_failed_close">Close</string>

+ 5 - 0
app/src/main/res/values-eu-rES/strings.xml

@@ -161,6 +161,11 @@
 	<string name="dialog_sync_text_6">Ari ari ari!</string>
 	<string name="dialog_sync_text_7">Llegando tarde…</string>
 	<string name="dialog_sync_text_8">¿Cabe más gente en el Foro Margolari?</string>
+	<string name="dialog_sync_text_9">Arreglando el tirador de cerveza...</string>
+	<string name="dialog_sync_text_10">Descorchando botellas...</string>
+	<string name="dialog_sync_text_11">Repartiendo pulseras...</string>
+	<string name="dialog_sync_text_12">Pintando las fiestas...</string>
+	<string name="dialog_sync_text_13">Desplegando pancarta...</string>
 	<string name="dialog_sync_failed_text">No se pudierdon descargar los contenidos\n\nAsegúrate de que dispones de conexión a internet e inténtalo de nuevo.</string>
 	<string name="lablanca_nofestivals"><![CDATA[Las Fiestas de La Blanca. Esos días, del 4 al 9 de agosto, en los que Vitoria-Gasteiz se transforma. Se llena de color y alegría, y en cada esquina puedes encontrar actividades y espectáculos. Todos las estamos esperando.\n\nPor desgracia, aún hay que esperar más.\n\nNosotros ya estamos trabajando en ello. Tan pronto como vayamos sabiendo más, aquí iremos publicando nuestro programa y otra información sobre las fiestas. Para ir abriendo boca, dejanos contarte algunas de las claves del plan Margolari de fiestas:]]></string>
 	<string name="lablanca_nofestivals_1_title">Planes que se adaptan a tí:</string>

+ 5 - 0
app/src/main/res/values/strings.xml

@@ -126,6 +126,11 @@
 	<string name="dialog_sync_text_6">Ari ari ari!</string>
 	<string name="dialog_sync_text_7">Llegando tarde…</string>
 	<string name="dialog_sync_text_8">¿Cabe más gente en el Foro Margolari?</string>
+	<string name="dialog_sync_text_9">Arreglando el tirador de cerveza...</string>
+	<string name="dialog_sync_text_10">Descorchando botellas...</string>
+	<string name="dialog_sync_text_11">Repartiendo pulseras...</string>
+	<string name="dialog_sync_text_12">Pintando las fiestas...</string>
+	<string name="dialog_sync_text_13">Desplegando pancarta...</string>
 	<string name="gallery_albums">Albums</string>
 	<string name="gallery_upload">Subir fotos</string>
 	<string name="gallery_upload_button">Subir</string>