Page Menu
Home
GitPull.it
Search
Configure Global Search
Log In
Files
F13209936
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Flag For Later
Size
39 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 7769bd0..24ba670 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -1,104 +1,105 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="it.reyboz.bustorino"
android:versionCode="22"
android:versionName="1.8.7">
<uses-sdk
android:minSdkVersion="9"
android:targetSdkVersion="23"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
+ <uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme">
<activity
android:name=".ActivityMain"
android:label="@string/app_name"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data
android:host="www.gtt.to.it"
android:pathPrefix="/cms/percorari/arrivi"
android:scheme="http"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data
android:host="gtt.to.it"
android:pathPrefix="/cms/percorari/arrivi"
android:scheme="http"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data
android:host="m.gtt.to.it"
android:pathPrefix="/m/it/arrivi.jsp"
android:scheme="http"/>
</intent-filter>
</activity>
<activity
android:name=".ActivityAbout"
android:label="@string/about"
android:parentActivityName=".ActivityMain"
android:theme="@style/AboutTheme">
<!-- API < 16: -->
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".ActivityMain"/>
</activity>
<activity
android:name=".ActivityFavorites"
android:label="@string/title_activity_favorites"
android:parentActivityName=".ActivityMain"
android:theme="@style/FavTheme">
<!-- API < 16: -->
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".ActivityMain"/>
</activity>
<provider
android:name=".middleware.AppDataProvider"
android:authorities="it.reyboz.bustorino.provider"
android:enabled="true"
android:exported="false">
</provider>
<service
android:name=".middleware.DatabaseUpdateService"
android:exported="false">
</service>
</application>
</manifest>
diff --git a/src/it/reyboz/bustorino/ActivityMain.java b/src/it/reyboz/bustorino/ActivityMain.java
index 8aeb737..c6b3840 100644
--- a/src/it/reyboz/bustorino/ActivityMain.java
+++ b/src/it/reyboz/bustorino/ActivityMain.java
@@ -1,583 +1,594 @@
/*
BusTO - Arrival times for Turin public transports.
Copyright (C) 2014 Valerio Bozzolan
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package it.reyboz.bustorino;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
+import android.location.LocationManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.NavUtils;
import android.support.v4.widget.SwipeRefreshLayout;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.*;
import com.google.zxing.integration.android.IntentIntegrator;
import com.google.zxing.integration.android.IntentResult;
//import com.melnykov.fab.FloatingActionButton;
import android.support.design.widget.FloatingActionButton;
import it.reyboz.bustorino.backend.ArrivalsFetcher;
import it.reyboz.bustorino.backend.FiveTScraperFetcher;
import it.reyboz.bustorino.backend.FiveTStopsFetcher;
import it.reyboz.bustorino.backend.GTTJSONFetcher;
import it.reyboz.bustorino.backend.GTTStopsFetcher;
import it.reyboz.bustorino.backend.StopsFinderByName;
import it.reyboz.bustorino.fragments.FragmentHelper;
import it.reyboz.bustorino.fragments.ResultListFragment;
import it.reyboz.bustorino.middleware.*;
public class ActivityMain extends GeneralActivity implements ResultListFragment.ResultFragmentListener {
/*
* Layout elements
*/
private EditText busStopSearchByIDEditText;
private EditText busStopSearchByNameEditText;
private ProgressBar progressBar;
private TextView howDoesItWorkTextView;
private Button hideHintButton;
private MenuItem actionHelpMenuItem;
private SwipeRefreshLayout swipeRefreshLayout;
private FloatingActionButton floatingActionButton;
private FragmentManager framan;
/*
* Search mode
*/
private static final int SEARCH_BY_NAME = 0;
private static final int SEARCH_BY_ID = 1;
private static final int SEARCH_BY_ROUTE = 2; // TODO: implement this (bug #1512948)
private int searchMode;
/*
* Options
*/
private final String OPTION_SHOW_LEGEND = "show_legend";
private final String LOCATION_PERMISSION_GIVEN = "loc_permission";
/* // useful for testing:
public class MockFetcher implements ArrivalsFetcher {
@Override
public Palina ReadArrivalTimesAll(String routeID, AtomicReference<result> res) {
SystemClock.sleep(5000);
res.set(result.SERVER_ERROR);
return new Palina();
}
}
private ArrivalsFetcher[] ArrivalFetchers = {new MockFetcher(), new MockFetcher(), new MockFetcher(), new MockFetcher(), new MockFetcher()};*/
private RecursionHelper<ArrivalsFetcher> ArrivalFetchersRecursionHelper = new RecursionHelper<>(new ArrivalsFetcher[] {new GTTJSONFetcher(), new FiveTScraperFetcher()});
private RecursionHelper<StopsFinderByName> StopsFindersByNameRecursionHelper = new RecursionHelper<>(new StopsFinderByName[] {new GTTStopsFetcher(), new FiveTStopsFetcher()});
private StopsDB stopsDB;
private UserDB userDB;
private FragmentHelper fh;
private GPSLocationAdapter locationHandler;
///////////////////////////////// EVENT HANDLERS ///////////////////////////////////////////////
/*
* @see swipeRefreshLayout
*/
private Handler handler = new Handler();
private final Runnable refreshing = new Runnable() {
public void run() {
new AsyncDataDownload(AsyncDataDownload.RequestType.ARRIVALS,fh).execute();
}
};
//// MAIN METHOD ///
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
framan = getSupportFragmentManager();
this.stopsDB = new StopsDB(getApplicationContext());
this.userDB = new UserDB(getApplicationContext());
setContentView(R.layout.activity_main);
busStopSearchByIDEditText = (EditText) findViewById(R.id.busStopSearchByIDEditText);
busStopSearchByNameEditText = (EditText) findViewById(R.id.busStopSearchByNameEditText);
progressBar = (ProgressBar) findViewById(R.id.progressBar);
howDoesItWorkTextView = (TextView) findViewById(R.id.howDoesItWorkTextView);
hideHintButton = (Button) findViewById(R.id.hideHintButton);
swipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.listRefreshLayout);
floatingActionButton = (FloatingActionButton) findViewById(R.id.floatingActionButton);
framan.addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
@Override
public void onBackStackChanged() {
Log.d("MainActivity, BusTO", "BACK STACK CHANGED");
}
});
busStopSearchByIDEditText.setSelectAllOnFocus(true);
busStopSearchByIDEditText
.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId,
KeyEvent event) {
// IME_ACTION_SEARCH alphabetical option
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
onSearchClick(v);
return true;
}
return false;
}
});
busStopSearchByNameEditText
.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId,
KeyEvent event) {
// IME_ACTION_SEARCH alphabetical option
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
onSearchClick(v);
return true;
}
return false;
}
});
// Called when the layout is pulled down
swipeRefreshLayout
.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
handler.post(refreshing);
}
});
/**
* @author Marco Gagino!!!
*/
//swipeRefreshLayout.setColorSchemeColors(R.color.blue_500, R.color.orange_500); // setColorScheme is deprecated, setColorSchemeColors isn't
swipeRefreshLayout.setColorSchemeResources(R.color.blue_500,R.color.orange_500);
fh = new FragmentHelper(this,R.id.listRefreshLayout,R.id.resultFrame,FragmentHelper.NO_FRAME);
setSearchModeBusStopID();
//---------------------------- START INTENT CHECK QUEUE ------------------------------------
// Intercept calls from URL intent
boolean tryedFromIntent = false;
String busStopID = null;
String busStopDisplayName = null;
Uri data = getIntent().getData();
if (data != null) {
busStopID = getBusStopIDFromUri(data);
tryedFromIntent = true;
}
// Intercept calls from other activities
if (!tryedFromIntent) {
Bundle b = getIntent().getExtras();
if (b != null) {
busStopID = b.getString("bus-stop-ID");
busStopDisplayName = b.getString("bus-stop-display-name");
/**
* I'm not very sure if you are coming from an Intent.
* Some launchers work in strange ways.
*/
tryedFromIntent = busStopID != null;
}
}
//---------------------------- END INTENT CHECK QUEUE --------------------------------------
if (busStopID == null) {
// Show keyboard if can't start from intent
showKeyboard();
// You haven't obtained anything... from an intent?
if (tryedFromIntent) {
// This shows a luser warning
ArrivalFetchersRecursionHelper.reset();
Toast.makeText(getApplicationContext(),
R.string.insert_bus_stop_number_error, Toast.LENGTH_SHORT).show();
}
} else {
// If you are here an intent has worked successfully
setBusStopSearchByIDEditText(busStopID);
/*
//THIS PART SHOULDN'T BE NECESSARY SINCE THE LAST SUCCESSFULLY SEARCHED BUS
// STOP IS ADDED AUTOMATICALLY
Stop nextStop = new Stop(busStopID);
// forcing it as user name even though it could be standard name, it doesn't really matter
nextStop.setStopUserName(busStopDisplayName);
//set stop as last succe
fh.setLastSuccessfullySearchedBusStop(nextStop);
*/
createFragmentForStop(busStopID);
}
//Try (hopefully) database update
//TODO: Start the service in foreground, check last time it ran before
DatabaseUpdateService.startDBUpdate(getApplicationContext());
- assertLocationPermissions();
+ if(getOption(LOCATION_PERMISSION_GIVEN,false)==false){
+ assertLocationPermissions();
+ }
locationHandler = new GPSLocationAdapter(getApplicationContext());
-
+ LocationManager locationManager = (LocationManager)
+ getSystemService(Context.LOCATION_SERVICE);
+ try {
+ locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 5000, 10, locationHandler);
+ } catch (SecurityException ec){
+ //ignored
+ Log.w("Busto","Position request failed even though user accepted permission: "+ec.getMessage());
+ }
Log.d("MainActivity", "Created");
}
/**
* Reload bus stop timetable when it's fulled resumed from background.
*/
@Override
protected void onPostResume() {
super.onPostResume();
Log.d("ActivityMain", "onPostResume fired. Last successfully bus stop ID: " + fh.getLastSuccessfullySearchedBusStop());
if (searchMode == SEARCH_BY_ID && fh.getLastSuccessfullySearchedBusStop() != null) {
setBusStopSearchByIDEditText(fh.getLastSuccessfullySearchedBusStop().ID);
//new asyncWgetBusStopFromBusStopID(lastSuccessfullySearchedBusStop.ID, ArrivalFetchersRecursionHelper, lastSuccessfullySearchedBusStop);
new AsyncDataDownload(AsyncDataDownload.RequestType.ARRIVALS,fh).execute();
} else {
//we have new activity or we don't have a new searched stop.
//Let's search stops nearby
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
actionHelpMenuItem = menu.findItem(R.id.action_help);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
switch (item.getItemId()) {
case android.R.id.home:
// Respond to the action bar's Up/Home button
NavUtils.navigateUpFromSameTask(this);
return true;
case R.id.action_help:
showHints();
return true;
case R.id.action_favorites:
startActivity(new Intent(ActivityMain.this, ActivityFavorites.class));
return true;
case R.id.action_about:
startActivity(new Intent(ActivityMain.this, ActivityAbout.class));
return true;
case R.id.action_news:
openIceweasel("http://blog.reyboz.it/tag/busto/");
return true;
case R.id.action_bugs:
openIceweasel("https://bugs.launchpad.net/bus-torino");
return true;
case R.id.action_source:
openIceweasel("https://code.launchpad.net/bus-torino");
return true;
case R.id.action_licence:
openIceweasel("http://www.gnu.org/licenses/gpl-3.0.html");
return true;
case R.id.action_author:
openIceweasel("http://boz.reyboz.it?lovebusto");
return true;
}
return super.onOptionsItemSelected(item);
}
/**
* OK this is pure shit
*
* @param v View clicked
*/
public void onSearchClick(View v) {
if (searchMode == SEARCH_BY_ID) {
String busStopID = busStopSearchByIDEditText.getText().toString();
//OLD ASYNCTASK
//new asyncWgetBusStopFromBusStopID(busStopID, ArrivalFetchersRecursionHelper, lastSuccessfullySearchedBusStop);
if(busStopID == null || busStopID.length() <= 0) {
showMessage(R.string.insert_bus_stop_number_error);
toggleSpinner(false);
} else
new AsyncDataDownload(AsyncDataDownload.RequestType.ARRIVALS,fh).execute(busStopID);
} else { // searchMode == SEARCH_BY_NAME
String query = busStopSearchByNameEditText.getText().toString();
//new asyncWgetBusStopSuggestions(query, stopsDB, StopsFindersByNameRecursionHelper);
new AsyncDataDownload(AsyncDataDownload.RequestType.STOPS,fh).execute(query);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
switch (requestCode){
case PERMISSION_REQUEST_POSITION:
if(grantResults.length>0 && grantResults[0]==PackageManager.PERMISSION_GRANTED){
setOption(LOCATION_PERMISSION_GIVEN,true);
+ locationHandler.startRequestingPosition();
} else {
//permission denied
setOption(LOCATION_PERMISSION_GIVEN,false);
}
//add other cases for permissions
}
}
@Override
public void createFragmentForStop(String ID) {
//new asyncWgetBusStopFromBusStopID(ID, ArrivalFetchersRecursionHelper,lastSuccessfullySearchedBusStop);
if(ID == null || ID.length() <= 0) {
// we're still in UI thread, no need to mess with Progress
showMessage(R.string.insert_bus_stop_number_error);
toggleSpinner(false);
} else
new AsyncDataDownload(AsyncDataDownload.RequestType.ARRIVALS,fh).execute(ID);
}
/**
* QR scan button clicked
*
* @param v View QRButton clicked
*/
public void onQRButtonClick(View v) {
IntentIntegrator integrator = new IntentIntegrator(this);
integrator.initiateScan();
}
/**
* Receive the Barcode Scanner Intent
*
*/
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent);
Uri uri;
try {
uri = Uri.parse(scanResult != null ? scanResult.getContents() : null); // this apparently prevents NullPointerException. Somehow.
} catch (NullPointerException e) {
Toast.makeText(getApplicationContext(),
R.string.no_qrcode, Toast.LENGTH_SHORT).show();
return;
}
String busStopID = getBusStopIDFromUri(uri);
busStopSearchByIDEditText.setText(busStopID);
createFragmentForStop(busStopID);
}
public void onHideHint(View v) {
hideHints();
setOption(OPTION_SHOW_LEGEND, false);
}
public void onToggleKeyboardLayout(View v) {
if (searchMode == SEARCH_BY_NAME) {
setSearchModeBusStopID();
if (busStopSearchByIDEditText.requestFocus()) {
showKeyboard();
}
} else { // searchMode == SEARCH_BY_ID
setSearchModeBusStopName();
if (busStopSearchByNameEditText.requestFocus()) {
showKeyboard();
}
}
}
///////////////////////////////// OTHER STUFF //////////////////////////////////////////////////
@Override
public void addLastStopToFavorites() {
if(fh.getLastSuccessfullySearchedBusStop() != null) {
new AsyncAddToFavorites(this).execute(fh.getLastSuccessfullySearchedBusStop());
}
}
////////////////////////////////////// GUI HELPERS /////////////////////////////////////////////
@Override
public void showKeyboard() {
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
View view = searchMode == SEARCH_BY_ID ? busStopSearchByIDEditText : busStopSearchByNameEditText;
imm.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT);
}
@Override
public void showMessage(int messageID) {
Toast.makeText(getApplicationContext(), messageID, Toast.LENGTH_SHORT).show();
}
private void setSearchModeBusStopID() {
searchMode = SEARCH_BY_ID;
busStopSearchByNameEditText.setVisibility(View.GONE);
busStopSearchByNameEditText.setText("");
busStopSearchByIDEditText.setVisibility(View.VISIBLE);
floatingActionButton.setImageResource(R.drawable.alphabetical);
}
private void setSearchModeBusStopName() {
searchMode = SEARCH_BY_NAME;
busStopSearchByIDEditText.setVisibility(View.GONE);
busStopSearchByIDEditText.setText("");
busStopSearchByNameEditText.setVisibility(View.VISIBLE);
floatingActionButton.setImageResource(R.drawable.numeric);
}
/**
* Having that cursor at the left of the edit text makes me cancer.
* @param busStopID bus stop ID
*/
private void setBusStopSearchByIDEditText(String busStopID) {
busStopSearchByIDEditText.setText(busStopID);
busStopSearchByIDEditText.setSelection(busStopID.length());
}
private void showHints() {
howDoesItWorkTextView.setVisibility(View.VISIBLE);
hideHintButton.setVisibility(View.VISIBLE);
actionHelpMenuItem.setVisible(false);
}
private void hideHints() {
howDoesItWorkTextView.setVisibility(View.GONE);
hideHintButton.setVisibility(View.GONE);
actionHelpMenuItem.setVisible(true);
}
//TODO: toggle spinner from mainActivity
@Override
public void toggleSpinner(boolean enable) {
if (enable) {
//already set by the RefreshListener when needed
//swipeRefreshLayout.setRefreshing(true);
progressBar.setVisibility(View.VISIBLE);
} else {
swipeRefreshLayout.setRefreshing(false);
progressBar.setVisibility(View.GONE);
}
}
private void prepareGUIForBusLines() {
swipeRefreshLayout.setEnabled(true);
swipeRefreshLayout.setVisibility(View.VISIBLE);
actionHelpMenuItem.setVisible(true);
}
private void prepareGUIForBusStops() {
swipeRefreshLayout.setEnabled(false);
swipeRefreshLayout.setVisibility(View.VISIBLE);
actionHelpMenuItem.setVisible(false);
}
/**
* This provides a temporary fix to make the transition
* to a single asynctask go smoother
* @param fragmentType the type of fragment created
*/
@Override
public void readyGUIfor(String fragmentType) {
hideKeyboard();
if(fragmentType==null) Log.e("ActivityMain","Problem with fragmentType");
else
switch (fragmentType){
case ResultListFragment.TYPE_LINES:
prepareGUIForBusLines();
if (getOption(OPTION_SHOW_LEGEND, true)) {
showHints();
}
break;
case ResultListFragment.TYPE_STOPS:
prepareGUIForBusStops();
break;
default:
Log.e("BusTO Activity","Called readyGUI with unsupported type of Fragment");
return;
}
// Shows hints
}
/**
* Open an URL in the default browser.
*
* @param url URL
*/
public void openIceweasel(String url) {
Intent browserIntent1 = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(browserIntent1);
}
///////////////////// INTENT HELPER ////////////////////////////////////////////////////////////
/**
* Try to extract the bus stop ID from a URi
*
* @param uri The URL
* @return bus stop ID or null
*/
public static String getBusStopIDFromUri(Uri uri) {
String busStopID;
// everithing catches fire when passing null to a switch.
String host = uri.getHost();
if(host == null) {
Log.e("ActivityMain", "Not an URL: " + uri);
return null;
}
switch(host) {
case "m.gtt.to.it":
// http://m.gtt.to.it/m/it/arrivi.jsp?n=1254
busStopID = uri.getQueryParameter("n");
if (busStopID == null) {
Log.e("ActivityMain", "Expected ?n from: " + uri);
}
break;
case "www.gtt.to.it":
case "gtt.to.it":
// http://www.gtt.to.it/cms/percorari/arrivi?palina=1254
busStopID = uri.getQueryParameter("palina");
if (busStopID == null) {
Log.e("ActivityMain", "Expected ?palina from: " + uri);
}
break;
default:
Log.e("ActivityMain", "Unexpected intent URL: " + uri);
busStopID = null;
}
return busStopID;
}
}
\ No newline at end of file
diff --git a/src/it/reyboz/bustorino/middleware/DatabaseUpdateService.java b/src/it/reyboz/bustorino/middleware/DatabaseUpdateService.java
index 9653bb6..92a78ce 100644
--- a/src/it/reyboz/bustorino/middleware/DatabaseUpdateService.java
+++ b/src/it/reyboz/bustorino/middleware/DatabaseUpdateService.java
@@ -1,225 +1,228 @@
/*
BusTO (middleware)
Copyright (C) 2018 Fabio Mazza
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package it.reyboz.bustorino.middleware;
import android.app.IntentService;
import android.content.*;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.util.Log;
import it.reyboz.bustorino.R;
import it.reyboz.bustorino.backend.Fetcher;
import it.reyboz.bustorino.backend.FiveTAPIFetcher;
import it.reyboz.bustorino.backend.Route;
import it.reyboz.bustorino.backend.Stop;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicReference;
import static it.reyboz.bustorino.middleware.NextGenDB.Contract.*;
/**
* An {@link IntentService} subclass for handling asynchronous task requests in
* a service on a separate handler thread.
*/
public class DatabaseUpdateService extends IntentService {
// IntentService can perform, e.g. ACTION_FETCH_NEW_ITEMS
private static final String ACTION_UPDATE = "it.reyboz.bustorino.middleware.action.UPDATE_DB";
private static final String DB_VERSION = "NextGenDB.GTTVersion";
private static final String DEBUG_TAG = "DatabaseService_BusTO";
// TODO: Rename parameters
private static final String TRIAL = "it.reyboz.bustorino.middleware.extra.TRIAL";
private static final int MAX_TRIALS = 5;
public DatabaseUpdateService() {
super("DatabaseUpdateService");
}
private int updateTrial;
/**
* Starts this service to perform action Foo with the given parameters. If
* the service is already performing a task this action will be queued.
*
* @see IntentService
*/
public static void startDBUpdate(Context context) {
startDBUpdate(context,0);
}
public static void startDBUpdate(Context con, int trial){
Intent intent = new Intent(con, DatabaseUpdateService.class);
intent.setAction(ACTION_UPDATE);
intent.putExtra(TRIAL,trial);
con.startService(intent);
}
@Override
protected void onHandleIntent(Intent intent) {
if (intent != null) {
final String action = intent.getAction();
if (ACTION_UPDATE.equals(action)) {
Log.d(DEBUG_TAG,"Started action update");
SharedPreferences shPr = getSharedPreferences(getString(R.string.mainSharedPreferences),MODE_PRIVATE);
int versionDB = shPr.getInt(DB_VERSION,-1);
final int trial = intent.getIntExtra(TRIAL,-1);
updateTrial = trial;
int newVersion = getNewVersion(trial);
Log.d(DEBUG_TAG,"newDBVersion: "+newVersion+" oldVersion: "+versionDB);
if(versionDB==-1 || newVersion>versionDB){
Log.d(DEBUG_TAG,"Downloading the bus stops info");
final AtomicReference<Fetcher.result> gres = new AtomicReference<>();
- getContentResolver().delete(Uri.parse("content://"+AppDataProvider.AUTHORITY+"/stops"),null,null);
if(!performDBUpdate(gres)) restartDBUpdateifPossible(trial,gres);
/*switch (gres.get()){
case SERVER_ERROR:
restartDBUpdateifPossible(trial);
break;
case PARSER_ERROR:
break;
case EMPTY_RESULT_SET:
break;
case QUERY_TOO_SHORT:
break;
case SERVER_ERROR_404:
break;
}*/
else {
SharedPreferences.Editor ed = shPr.edit();
ed.putInt(DB_VERSION,newVersion);
// BY COMMENTING THIS, THE APP WILL CONTINUOUSLY UPDATE THE DATABASE
ed.apply();
}
} else {
Log.d(DEBUG_TAG,"No update needed");
}
Log.d(DEBUG_TAG,"Finished update");
}
}
}
public boolean performDBUpdate(AtomicReference<Fetcher.result> gres){
final FiveTAPIFetcher f = new FiveTAPIFetcher();
final ArrayList<Stop> stops = f.getAllStopsFromGTT(gres);
//final ArrayList<ContentProviderOperation> cpOp = new ArrayList<>();
if(gres.get()!= Fetcher.result.OK){
Log.w(DEBUG_TAG,"Something went wrong downloading");
return false;
}
final NextGenDB dbHelp = new NextGenDB(getApplicationContext());
final SQLiteDatabase db = dbHelp.getWritableDatabase();
//Empty the needed tables
db.beginTransaction();
- db.execSQL("DELETE FROM "+StopsTable.TABLE_NAME);
- db.delete(LinesTable.TABLE_NAME,null,null);
+ //db.execSQL("DELETE FROM "+StopsTable.TABLE_NAME);
+ //db.delete(LinesTable.TABLE_NAME,null,null);
//put new data
long startTime = System.currentTimeMillis();
Log.d(DEBUG_TAG,"Inserting "+stops.size()+" stops");
for (final Stop s : stops) {
final ContentValues cv = new ContentValues();
cv.put(StopsTable.COL_ID, s.ID);
cv.put(StopsTable.COL_NAME, s.getStopDefaultName());
if (s.location != null)
cv.put(StopsTable.COL_LOCATION, s.location);
cv.put(StopsTable.COL_LAT, s.getLatitude());
cv.put(StopsTable.COL_LONG, s.getLongitude());
if (s.getAbsurdGTTPlaceName() != null) cv.put(StopsTable.COL_PLACE, s.getAbsurdGTTPlaceName());
cv.put(StopsTable.COL_LINES_STOPPING, s.routesThatStopHereToString());
if (s.type != null) cv.put(StopsTable.COL_TYPE, s.type.getCode());
//Log.d(DEBUG_TAG,cv.toString());
//cpOp.add(ContentProviderOperation.newInsert(uritobeused).withValues(cv).build());
//valuesArr[i] = cv;
- db.insert(StopsTable.TABLE_NAME, null, cv);
+ db.replace(StopsTable.TABLE_NAME,null,cv);
}
db.setTransactionSuccessful();
db.endTransaction();
long endTime = System.currentTimeMillis();
Log.d(DEBUG_TAG,"Inserting stops took: "+((double) (endTime-startTime)/1000)+" s");
final ArrayList<Route> routes = f.getAllLinesFromGTT(gres);
if(routes==null){
Log.w(DEBUG_TAG,"Something went wrong downloading the lines");
return false;
}
db.beginTransaction();
startTime = System.currentTimeMillis();
for (Route r: routes){
final ContentValues cv = new ContentValues();
cv.put(LinesTable.COLUMN_NAME,r.name);
switch (r.type){
case BUS:
cv.put(LinesTable.COLUMN_TYPE,"URBANO");
break;
case RAILWAY:
cv.put(LinesTable.COLUMN_TYPE,"FERROVIA");
break;
case LONG_DISTANCE_BUS:
cv.put(LinesTable.COLUMN_TYPE,"EXTRA");
break;
}
cv.put(LinesTable.COLUMN_DESCRIPTION,r.description);
- db.insert(LinesTable.TABLE_NAME,null,cv);
+ //db.insert(LinesTable.TABLE_NAME,null,cv);
+ int rows = db.update(LinesTable.TABLE_NAME,cv,LinesTable.COLUMN_NAME+" = ?",new String[]{r.name});
+ if(rows<1){ //we haven't changed anything
+ db.insert(LinesTable.TABLE_NAME,null,cv);
+ }
}
db.setTransactionSuccessful();
db.endTransaction();
endTime = System.currentTimeMillis();
Log.d(DEBUG_TAG,"Inserting lines took: "+((double) (endTime-startTime)/1000)+" s");
return true;
}
private int getNewVersion(int trial){
AtomicReference<Fetcher.result> gres = new AtomicReference<>();
String networkRequest = FiveTAPIFetcher.performAPIRequest(FiveTAPIFetcher.QueryType.STOPS_VERSION,null,gres);
if(networkRequest == null){
restartDBUpdateifPossible(trial,gres);
return -2;
}
boolean needed;
try {
JSONObject resp = new JSONObject(networkRequest);
return resp.getInt("id");
} catch (JSONException e) {
e.printStackTrace();
Log.e(DEBUG_TAG,"Error: wrong JSON response\nResponse:\t"+networkRequest);
return -2;
}
}
private void restartDBUpdateifPossible(int currentTrial,AtomicReference<Fetcher.result> res){
if (currentTrial<MAX_TRIALS && res.get()!= Fetcher.result.PARSER_ERROR){
Log.d(DEBUG_TAG,"Update failed, starting new trial ("+currentTrial+")");
startDBUpdate(getApplicationContext(),++currentTrial);
}
}
}
diff --git a/src/it/reyboz/bustorino/middleware/GPSLocationAdapter.java b/src/it/reyboz/bustorino/middleware/GPSLocationAdapter.java
index 59ae17a..e849147 100644
--- a/src/it/reyboz/bustorino/middleware/GPSLocationAdapter.java
+++ b/src/it/reyboz/bustorino/middleware/GPSLocationAdapter.java
@@ -1,48 +1,55 @@
package it.reyboz.bustorino.middleware;
import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Looper;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
+import android.util.Log;
public class GPSLocationAdapter implements LocationListener {
private Context con;
private LocationManager locMan;
public GPSLocationAdapter(Context con) {
this.con = con;
locMan = (LocationManager) con.getSystemService(Context.LOCATION_SERVICE);
}
- public void requestPosition(){
-
+ public boolean startRequestingPosition(){
+ try {
+ locMan.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 10, this);
+ return true;
+ } catch (SecurityException exc){
+ exc.printStackTrace();
+ return false;
+ }
}
@Override
public void onLocationChanged(Location location) {
-
+ Log.d("GPSLocationListener","found location:\nlat: "+location.getLatitude()+" lon: "+location.getLongitude()+"\naccuracy: "+location.getAccuracy());
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
@Override
public void onProviderEnabled(String provider) {
-
+ startRequestingPosition();
}
@Override
public void onProviderDisabled(String provider) {
-
+ locMan.removeUpdates(this);
}
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Wed, Apr 22, 15:03 (1 d, 21 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1862827
Default Alt Text
(39 KB)
Attached To
Mode
R28 Libre BusTO staging area
Attached
Detach File
Event Timeline
Log In to Comment