I am learning networking from UDACITY, there I came across an app named Quake Report, I wanted to add Swipe to refresh feature in the app but I am not able to get the results I want.
package com.example.android.quakereport;
import android.app.LoaderManager;
import android.content.Context;
import android.content.Intent;
import android.content.Loader;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
public class EarthquakeActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<List<Earthquake>> {
/**
* Constant value for the earthquake loader ID. We can choose any integer.
* This really only comes into play if you're using multiple loaders.
*/
private static final int EARTHQUAKE_LOADER_ID = 1;
// TextView that is displayed when the list is empty
private TextView mEmptyStateTextView;
// progress bar
private ProgressBar progressBar;
public static final String LOG_TAG = EarthquakeActivity.class.getName();
// URL for earthquake data from the USGS dataset
private static final String USGS_REQUEST_URL =
"https://earthquake.usgs.gov/fdsnws/event/1/query?format=geojson&orderby=time&minmag=5&limit=15";
/**
* Adapter for the list of earthquakes
*/
private EarthquakeAdapter mAdapter;
#Override
public Loader<List<Earthquake>> onCreateLoader(int id, Bundle args) {
Log.i(LOG_TAG, "Test: onCreateLoader() called...");
// Create a new loader for the given URL
return new EarthquakeLoader(this, USGS_REQUEST_URL);
}
#Override
public void onLoadFinished(Loader<List<Earthquake>> loader, List<Earthquake> data) {
Log.i(LOG_TAG, "Test: onLoadFinished() called...");
// Clear the adapter of previous earthquake data
mAdapter.clear();
// Hiding the progress bar as the results have been loaded
progressBar.setVisibility(View.GONE);
// Check if Internet Connection is present or not and show text accordingly
ConnectivityManager connManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connManager.getActiveNetworkInfo();
if (networkInfo != null && networkInfo.isConnected()) {
mEmptyStateTextView.setText(R.string.no_earthquakes);
} else {
mEmptyStateTextView.setText(R.string.no_internet_connection);
}
// If there is a valid list of {#link Earthquake}s, then add them to the adapter's
// data set. This will trigger the ListView to update.
if (data != null && !data.isEmpty()) {
mAdapter.addAll(data);
}
}
#Override
public void onLoaderReset(Loader<List<Earthquake>> loader) {
Log.i(LOG_TAG, "Test: onLoaderReset() called...");
// Loader reset, so we can clear out our existing data.
mAdapter.clear();
}
#Override
protected void onCreate(Bundle savedInstanceState) {
Log.i(LOG_TAG, "Test: Earthquake Activity onCreate() called.");
super.onCreate(savedInstanceState);
setContentView(R.layout.earthquake_activity);
// Creating a swipe to refresh feature
final SwipeRefreshLayout pullToRefresh = findViewById(R.id.swipe_refresh);
pullToRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
pullToRefresh.setRefreshing(false);
}
});
// Find a reference to the {#link ListView} in the layout
ListView earthquakeListView = (ListView) findViewById(R.id.list);
// Get a reference to the ConnectivityManager to check state of network connectivity
ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
// Get details on the currently active default data network
NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
// If there is a network connection, fetch data
if (networkInfo != null && networkInfo.isConnected()) {
// Get a reference to the LoaderManager, in order to interact with loaders.
LoaderManager loaderManager = getLoaderManager();
// Initialize the loader. Pass in the int ID constant defined above and pass in null for
// the bundle. Pass in this activity for the LoaderCallbacks parameter (which is valid
// because this activity implements the LoaderCallbacks interface).
// Create a new adapter that takes an empty list of earthquakes as input
Log.i(LOG_TAG, "Test: calling initLoader()...");
loaderManager.initLoader(EARTHQUAKE_LOADER_ID, null, this);
} else {
// Otherwise, display error
// First, hide loading indicator so error message will be visible
progressBar = (ProgressBar) findViewById(R.id.progress_bar);
progressBar.setVisibility(View.GONE);
// Update empty state with no connection error message
mEmptyStateTextView = (TextView) findViewById(R.id.empty_view);
mEmptyStateTextView.setText(R.string.no_internet_connection);
}
mEmptyStateTextView = (TextView) findViewById(R.id.empty_view);
earthquakeListView.setEmptyView(mEmptyStateTextView);
progressBar = (ProgressBar) findViewById(R.id.progress_bar);
mAdapter = new EarthquakeAdapter(this, new ArrayList<Earthquake>());
// Set the adapter on the {#link ListView}
// so the list can be populated in the user interface
earthquakeListView.setAdapter(mAdapter);
// Set an item click listener on the ListView, which sends an intent to a web browser
// to open a website with more information about the selected earthquake.
earthquakeListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
// Find the current earthquake that was clicked on
Earthquake currentEarthquake = mAdapter.getItem(position);
// Convert the String URL into a URI object (to pass into the Intent constructor)
Uri earthquakeUri = Uri.parse(currentEarthquake.getUrl());
// Create a new intent to view the earthquake URI
Intent websiteIntent = new Intent(Intent.ACTION_VIEW, earthquakeUri);
// Send the intent to launch a new activity
startActivity(websiteIntent);
}
});
// EarthquakeAsyncTask task = new EarthquakeAsyncTask();
// task.execute(USGS_REQUEST_URL);
}
/**
* {#link AsyncTask} to perform the network request on a background thread, and then
* update the UI with the list of earthquakes in the response.
* <p>
* AsyncTask has three generic parameters: the input type, a type used for progress updates, and
* an output type. Our task will take a String URL, and return an Earthquake. We won't do
* progress updates, so the second generic is just Void.
* <p>
* We'll only override two of the methods of AsyncTask: doInBackground() and onPostExecute().
* The doInBackground() method runs on a background thread, so it can run long-running code
* (like network activity), without interfering with the responsiveness of the app.
* Then onPostExecute() is passed the result of doInBackground() method, but runs on the
* UI thread, so it can use the produced data to update the UI.
*/
private class EarthquakeAsyncTask extends AsyncTask<String, Void, List<Earthquake>> {
/**
* This method runs on a background thread and performs the network request.
* We should not update the UI from a background thread, so we return a list of
* {#link Earthquake}s as the result.
*/
#Override
protected List<Earthquake> doInBackground(String... urls) {
// Don't perform the request if there are no URLs, or the first URL is null.
if (urls.length < 1 || urls[0] == null) {
return null;
}
List<Earthquake> result = QueryUtils.fetchEarthquakeData(urls[0]);
return result;
}
/**
* This method runs on the main UI thread after the background work has been
* completed. This method receives as input, the return value from the doInBackground()
* method. First we clear out the adapter, to get rid of earthquake data from a previous
* query to USGS. Then we update the adapter with the new list of earthquakes,
* which will trigger the ListView to re-populate its list items.
*/
#Override
protected void onPostExecute(List<Earthquake> data) {
// Clear the adapter of previous earthquake data
mAdapter.clear();
// If there is a valid list of {#link Earthquake}s, then add them to the adapter's
// data set. This will trigger the ListView to update.
if (data != null && !data.isEmpty()) {
mAdapter.addAll(data);
}
}
}
}
I want this app to get data from the given URL whenever the user swipes down, but I am not able to find a way to do it. Can anyone please help me with the code that is to be written in the following code block:
final SwipeRefreshLayout pullToRefresh = findViewById(R.id.swipe_refresh);
pullToRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
pullToRefresh.setRefreshing(false);
}
});
call you methods which responsible for network call inside doRefresh method
Related
I want to route the audio to a bluetooth headset, or similar outputs if connected. i'm using MediaRouter for this purpose as i understand that what intend to do.
Yet i cannot make it work , as it's not discovering my bluetooth headphones, although its paired.
I'll post the code i'm using for the activity.
And i want to ask, for this purpose i have to use bluetooth framework ? as I want to route the audio only, not to deal with connecting or pairing bluetooth devices.
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.util.Log;
import android.view.Display;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.core.view.MenuItemCompat;
import androidx.mediarouter.app.MediaRouteActionProvider;
import androidx.mediarouter.app.MediaRouteControllerDialog;
import androidx.mediarouter.app.MediaRouteControllerDialogFragment;
import androidx.mediarouter.app.MediaRouteDialogFactory;
import androidx.mediarouter.media.MediaControlIntent;
import androidx.mediarouter.media.MediaRouteSelector;
import androidx.mediarouter.media.MediaRouter;
public class MediaRouterPlaybackActivity extends AppCompatActivity {
private MediaRouter mMediaRouter;
// Active Presentation, set to null if no secondary screen is enabled
private SamplePresentation mPresentation;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.media_route);
mTextStatus = findViewById(R.id.textStatus);
Toolbar myToolbar = findViewById(R.id.my_toolbar);
setSupportActionBar(myToolbar);
Log.d("tag", "on create");
// Enable clicks on the 'change color' button
mButton = findViewById(R.id.button1);
mButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
showNextColor();
}
});
// BEGIN_INCLUDE(getMediaRouter)
// Get the MediaRouter service
mMediaRouter = MediaRouter.getInstance(this);
// END_INCLUDE(getMediaRouter)
}
/**
* Implementing a {#link android.media.MediaRouter.Callback} to update the displayed
* {#link android.app.Presentation} when a route is selected, unselected or the
* presentation display has changed. The provided stub implementation
* {#link android.media.MediaRouter.SimpleCallback} is extended and only
* {#link android.media.MediaRouter.SimpleCallback#onRouteSelected(android.media.MediaRouter, int, android.media.MediaRouter.RouteInfo)}
* ,
* {#link android.media.MediaRouter.SimpleCallback#onRouteUnselected(android.media.MediaRouter, int, android.media.MediaRouter.RouteInfo)}
* and
* {#link android.media.MediaRouter.SimpleCallback#onRoutePresentationDisplayChanged(android.media.MediaRouter, android.media.MediaRouter.RouteInfo)}
* are overridden to update the displayed {#link android.app.Presentation} in
* {#link #updatePresentation()}. These callbacks enable or disable the
* second screen presentation based on the routing provided by the
* {#link android.media.MediaRouter} for {#link android.media.MediaRouter#ROUTE_TYPE_LIVE_VIDEO}
* streams. #
*/
private final MediaRouter.Callback mMediaRouterCallback =
new MediaRouter.Callback() {
// BEGIN_INCLUDE(SimpleCallback)
/**
* A new route has been selected as active. Disable the current
* route and enable the new one.
*/
#Override
public void onRouteSelected(#NonNull MediaRouter router, #NonNull MediaRouter.RouteInfo route, int reason) {
Log.d("Media route", "onRouteUnselected: route=" + route);
updatePresentation();
}
/**
* The route has been unselected.
*/
#Override
public void onRouteUnselected(MediaRouter router, MediaRouter.RouteInfo info, int reason) {
Log.d("Media route", "onRouteUnselected: route=" + info);
updatePresentation();
}
/**
* The route's presentation display has changed. This callback
* is called when the presentation has been activated, removed
* or its properties have changed.
*/
#Override
public void onRoutePresentationDisplayChanged(MediaRouter router, MediaRouter.RouteInfo route) {
updatePresentation();
}
// END_INCLUDE(SimpleCallback)
};
/**
* Updates the displayed presentation to enable a secondary screen if it has
* been selected in the {#link android.media.MediaRouter} for the
* {#link android.media.MediaRouter#ROUTE_TYPE_LIVE_VIDEO} type. If no screen has been
* selected by the {#link android.media.MediaRouter}, the current screen is disabled.
* Otherwise a new {#link SamplePresentation} is initialized and shown on
* the secondary screen.
*/
private void updatePresentation() {
// BEGIN_INCLUDE(updatePresentationInit)
// Get the selected route for live video
MediaRouter.RouteInfo selectedRoute = mMediaRouter.getSelectedRoute();
// Get its Display if a valid route has been selected
Display selectedDisplay = selectedRoute.getPresentationDisplay();
// END_INCLUDE(updatePresentationInit)
// BEGIN_INCLUDE(updatePresentationDismiss)
/*
* Dismiss the current presentation if the display has changed or no new
* route has been selected
*/
if (mPresentation != null && mPresentation.getDisplay() != selectedDisplay) {
mPresentation.dismiss();
mPresentation = null;
mButton.setEnabled(false);
mTextStatus.setText("not connected");
}
// END_INCLUDE(updatePresentationDismiss)
// BEGIN_INCLUDE(updatePresentationNew)
/*
* Show a new presentation if the previous one has been dismissed and a
* route has been selected.
*/
if (mPresentation == null && selectedDisplay != null) {
// Initialise a new Presentation for the Display
mPresentation = new SamplePresentation(this, selectedDisplay);
mPresentation.setOnDismissListener(mOnDismissListener);
// Try to show the presentation, this might fail if the display has
// gone away in the mean time
try {
mPresentation.show();
mTextStatus.setText("test");
mButton.setEnabled(true);
showNextColor();
} catch (WindowManager.InvalidDisplayException ex) {
// Couldn't show presentation - display was already removed
mPresentation = null;
}
}
// END_INCLUDE(updatePresentationNew)
}
#Override
protected void onResume() {
super.onResume();
// BEGIN_INCLUDE(addCallback)
// Register a callback for all events related to live video devices
mMediaRouter.addCallback(
new MediaRouteSelector.Builder()
.addControlCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)
.addControlCategory(MediaControlIntent.CATEGORY_LIVE_AUDIO)
.build(),
mMediaRouterCallback, MediaRouter.CALLBACK_FLAG_REQUEST_DISCOVERY
);
// END_INCLUDE(addCallback)
// Show the 'Not connected' status message
mButton.setEnabled(false);
mTextStatus.setText("not connected");
// Update the displays based on the currently active routes
updatePresentation();
}
#Override
protected void onPause() {
super.onPause();
// BEGIN_INCLUDE(onPause)
// Stop listening for changes to media routes.
mMediaRouter.removeCallback(mMediaRouterCallback);
// END_INCLUDE(onPause)
}
#Override
protected void onStop() {
super.onStop();
// BEGIN_INCLUDE(onStop)
// Dismiss the presentation when the activity is not visible.
if (mPresentation != null) {
mPresentation.dismiss();
mPresentation = null;
}
// BEGIN_INCLUDE(onStop)
}
/**
* Inflates the ActionBar or options menu. The menu file defines an item for
* the {#link android.app.MediaRouteActionProvider}, which is registered here for all
* live video devices using {#link android.media.MediaRouter#ROUTE_TYPE_LIVE_VIDEO}.
*/
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu, menu);
// BEGIN_INCLUDE(MediaRouteActionProvider)
// Configure the media router action provider
MenuItem mediaRouteMenuItem = menu.findItem(R.id.menu_media_route);
MediaRouteActionProvider mediaRouteActionProvider =
(MediaRouteActionProvider) MenuItemCompat.getActionProvider(mediaRouteMenuItem);
mediaRouteActionProvider.setAlwaysVisible((true));
mediaRouteActionProvider.setRouteSelector(
new MediaRouteSelector.Builder()
.addControlCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)
.addControlCategory(MediaControlIntent.CATEGORY_LIVE_AUDIO)
.build());
mediaRouteActionProvider.setDialogFactory(new MediaRouteDialogFactory() {
#Override
public MediaRouteControllerDialogFragment onCreateControllerDialogFragment() {
return new MediaRouteControllerDialogFragment() {
#Override
public MediaRouteControllerDialog onCreateControllerDialog(
Context context, Bundle savedInstanceState) {
MediaRouteControllerDialog mControllerDialog = new MediaRouteControllerDialog(MediaRouterPlaybackActivity.this);
return mControllerDialog;
}
};
}
});
// BEGIN_INCLUDE(MediaRouteActionProvider)
return true;
}
/**
* Listens for dismissal of the {#link SamplePresentation} and removes its
* reference.
*/
private final DialogInterface.OnDismissListener mOnDismissListener =
new DialogInterface.OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialog) {
if (dialog == mPresentation) {
mPresentation = null;
}
}
};
// Views used to display status information on the primary screen
private TextView mTextStatus;
private Button mButton;
/**
* Displays the next color on the secondary screen if it is activate.
*/
private void showNextColor() {
}
}```
I working with this example I found in android docs.
Do you might know how to solve it ?
Im not trying to use google cast only to route to bluetooth speakers or headphones.
This is my first question here on stack overflow, so please forgive me for any oversight or formatting errors. This issue seems simple enough, but I am not able to "put the pieces together" for some reason. I am also learning java and android studio as I go, so please forgive and educate on any bad code.
I need to gather data from my barcode scanning app, submit it to a variable, and then pass that variable through my database to fetch information based on the UPC code. I am using the ZXing library for the barcode scanner, with the handleResult method to capture the initial data.
I have the data collected within the SimpleScanner activity, but I can't figure out how to use that variable in a SQlite query. Below are the main classes I am using.
Any help would be appreciated. I can query the entire database just fine, but I need to look up the rows that match the actual item I am scanning. Thanks again!
SimpleScannerActivity.java
package com.example.android.dropr;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.database.Cursor;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.widget.Toast;
import com.google.zxing.Result;
import java.util.ArrayList;
import java.util.List;
import me.dm7.barcodescanner.zxing.ZXingScannerView;
public class SimpleScannerActivity extends MainActivity implements ZXingScannerView.ResultHandler {
private ZXingScannerView mScannerView;
#Override
public void onCreate(Bundle state) {
super.onCreate(state);
mScannerView = new ZXingScannerView(this); // Programmatically initialize the scanner view
setContentView(mScannerView); // Set the scanner view as the content view
}
#Override
public void onResume() {
super.onResume();
mScannerView.setResultHandler(this); // Register ourselves as a handler for scan results.
mScannerView.startCamera(); // Start camera on resume
}
#Override
public void onPause () {
super.onPause();
mScannerView.stopCamera(); // Stop the camera on pause
}
#Override
public void handleResult(Result rawResult) {
String TAG = "Dropr";
/**
* Create Alert Dialog, so that user has time to read the information within.
*/
AlertDialog.Builder scanInfo = new AlertDialog.Builder(this);
String messageContent = "Content - " + rawResult.getText();
String messageFormat = "Format - " + rawResult.getBarcodeFormat().toString() + ".";
scanInfo.setTitle("Scan Information:");
scanInfo.setMessage(messageContent + "\n" + messageFormat);
scanInfo.setCancelable(true);
scanInfo.setPositiveButton(
"OK",
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
// IF you would like to resume scanning, call this method below:
// Handle the data
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
mScannerView.resumeCameraPreview(SimpleScannerActivity.this);
}
}, 1000);
}
});
AlertDialog showInfo = scanInfo.create();
showInfo.show();
// Do something with the result here
Log.v(TAG, rawResult.getText());
Log.v(TAG, rawResult.getBarcodeFormat().toString());
}
}
DatabaseAccess.java
package com.example.android.dropr;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import java.util.ArrayList;
import java.util.List;
public class DatabaseAccess {
private SQLiteOpenHelper openHelper;
private SQLiteDatabase database;
private static DatabaseAccess instance;
private SimpleScannerActivity scannerActivity = new SimpleScannerActivity();
/**
* Private constructor to avoid object creation from outside classes.
*
* #param context
*/
protected DatabaseAccess(Context context) {
this.openHelper = new DatabaseOpenHelper(context);
}
/**
* Return a singleton instance of DatabaseAccess.
*
* #param context
* #return the instance of DatabaseAccess
*/
public static DatabaseAccess getInstance(Context context) {
if (instance == null) {
instance = new DatabaseAccess(context);
}
return instance;
}
/**
* Open the database connection
*/
public void open() {
this.database = openHelper.getWritableDatabase();
}
/**
* Close the database connection
*/
public void close() {
if (database != null) {
this.database.close();
}
}
/**
* Read all quotes from the database.
*
* #return a list of quotes
*/
public List<String> getCodes() {
List<String> list = new ArrayList<>();
Cursor cursor = database.rawQuery("SELECT name, upc14 FROM Barcodes", null);
cursor.moveToFirst();
while (!cursor.isAfterLast()) {
list.add(cursor.getString(0));
list.add(cursor.getString(1));
cursor.moveToNext();
}
cursor.close();
return list;
}
}
I finally came up with a solution, thanks to #muratgu! I created another method that creates and stores a variable for the scanned data, and passes the variable through a query.
/**
* read a single record from the database the matches the UPC-A code scanned.
* if there is no match, do nothing.
* #param rawContent
* #return a brand name based on the matching UPC-A code that was scanned.
*/
public String getInfo(String rawContent) {
String TAG = "Getinfo():";
String content = "00" + rawContent;
String brandName = "";
Cursor cursor = database.rawQuery("SELECT name, upc12 from Barcodes WHERE '" + content + "' = upc12", null);
if(cursor.getCount() > 0) {
cursor.moveToFirst();
brandName = cursor.getString(cursor.getColumnIndex("name"));
cursor.close();
} else {
Log.v(TAG, "uh oh, something went wrong in the if loop! ");
}
return brandName;
}
This method gets called in the SimpleScannerActivity.java file, where the scanned data can be passed through the variable. The method returns the name of the item, which is then placed in the dialog box. Exactly what I needed.
Thanks again, #muratgu! you gave me enough information that I could solve the problem myself. I just had to think on it for a bit!
First off, I first laid eyes on Java three weeks ago so bear with me if this code is terrible. It's an assignment for school that I am to build on a prototyped app and give it a UI, so the Adapter is basically all I've done to this.
My problem being that as soon as I touch the scroll, I get thrown to the bottom of the list and can't scroll back up without getting pushed back down.
/**
* VaxjoWeather.java
* Created: May 9, 2010
* Jonas Lundberg, LnU
*/
package dv106.weather;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringWriter;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;
import android.app.ListActivity;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
/**
* This is a first prototype for a weather app. It is currently
* only downloading weather data for Växjo.
*
* This activity downloads weather data and constructs a WeatherReport,
* a data structure containing weather data for a number of periods ahead.
*
* The WeatherHandler is a SAX parser for the weather reports
* (forecast.xml) produced by www.yr.no. The handler constructs
* a WeatherReport containing meta data for a given location
* (e.g. city, country, last updated, next update) and a sequence
* of WeatherForecasts.
* Each WeatherForecast represents a forecast (weather, rain, wind, etc)
* for a given time period.
*
* The next task is to construct a list based GUI where each row
* displays the weather data for a single period.
*
*
* #author jlnmsi
*
*/
public class VaxjoWeather extends ListActivity {
//private InputStream input;
private WeatherReport report = null;
//private ArrayList<WeatherForecast> forecastList = new ArrayList<WeatherForecast>();
private WeatherAdapter adapter;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
adapter = new WeatherAdapter(this);
setListAdapter(adapter);
//getListView().setTranscriptMode(ListView.TRANSCRIPT_MODE_DISABLED);
try {
URL url = new URL("http://www.yr.no/sted/Sverige/Kronoberg/V%E4xj%F6/forecast.xml");
AsyncTask task = new WeatherRetriever().execute(url);
} catch (IOException ioe ) {
ioe.printStackTrace();
}
//adapter.notifyDataSetChanged();
}
private void PrintReportToConsole() {
if (this.report != null) {
/* Print location meta data */
//System.out.println(report);
/* Print forecasts */
int count = 0;
for (WeatherForecast forecast : report) {
count++;
adapter.add(forecast);
}
}
else {
System.out.println("Weather report has not been loaded.");
}
//adapter.notifyDataSetChanged();
}
private class WeatherRetriever extends AsyncTask<URL, Void, WeatherReport> {
protected WeatherReport doInBackground(URL... urls) {
try {
return WeatherHandler.getWeatherReport(urls[0]);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
protected void onProgressUpdate(Void... progress) {
}
protected void onPostExecute(WeatherReport result) {
report = result;
PrintReportToConsole();
}
}
// custom ArrayAdpater to show, weather icon, temperature, and precipation.
class WeatherAdapter extends ArrayAdapter<WeatherForecast> {
public WeatherAdapter(Context context) {
super(context,R.layout.forecast);
}
#Override // Called when updating the ListView
public View getView(int position, View convertView, ViewGroup parent) {
View row;
if (convertView == null) { // Create new row view object
LayoutInflater inflater = getLayoutInflater();
row = inflater.inflate(R.layout.forecast,parent,false);
}
else // reuse old row view to save time/battery
row = convertView;
// TextView for Temperature
TextView temperature = (TextView)row.findViewById(R.id.temperature);
temperature.setText(Integer.toString(this.getItem(position).getTemp())+" °C");
// TextView for out Precipation.
TextView precipation = (TextView)row.findViewById(R.id.rain);
precipation.setText(String.valueOf(this.getItem(position).getRain())+" mm");
// Image Icon for forecast.
ImageView icon = (ImageView)row.findViewById(R.id.icon);
String iconPath = "ic_";
if (this.getItem(position).getWeatherCode() <= 9){
iconPath = iconPath+"0"+(Integer.toString(this.getItem(position).getWeatherCode()));
}
else {
iconPath = iconPath+(Integer.toString(this.getItem(position).getWeatherCode()));
}
int resId = getResources().getIdentifier(iconPath, "drawable", getPackageName());
// If the resource ID is invalid, as in the image not existing, we'll add the postfix for periods.
if (resId == 0){
// Set the icon image source dependent on period code given.
if(this.getItem(position).getPeriodCode() == 3){
iconPath = iconPath +"n";
}
else if (this.getItem(position).getPeriodCode() == 2){
iconPath = iconPath +"d";
}
else {
iconPath = iconPath +"m";
}
resId = getResources().getIdentifier(iconPath, "drawable", getPackageName());
icon.setImageResource(resId);
}
// Or if everything checked out, we'll just run with the resource ID and find our Icon.
else {
icon.setImageResource(resId);
}
return row;
}
}
}
I tried applying another standard arrayadapter and actually got the same unwanted scrolling results, so I got no idea what part it is I got issues with.
Way to do it is:
1: Place ListView in main.xml
2: In your Activity Make object of ListView like so -> private ListView listView; in onCreate connect it to the main.xml like this, listView = (ListView) R.id.listView1; // whatever it is called
3: next create an ArrayList:-> private ArrayList arrayWeather = new ArrayList();
4: fill the arraylist with weather data then finally create object of class you created and make it use your arraylist to display data.
Example:
public class ListUser extends BaseAdapter{
#Override
public int getCount() {
// TODO Auto-generated method stub
return arraylistData.size(); // the arraylist u created
}
#Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return arraylistData.get(position);
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return arraylistData.size();
}
#Override
public View getView(final int position, View v, ViewGroup parent) {
if(v == null){
LayoutInflater lf = (LayoutInflater) BuyPets.this.getSystemService( Context.LAYOUT_INFLATER_SERVICE);
v = lf.inflate(R.layout.forecast, null);
}
// setup here, done
return v;
}
}
Solution was found and apparently it had nothing to do with my code. Class suggested we'd use Intel x86 instead of ARM for our emulators. Running it with ARM scrolling work just as expected.
When I search for a value in my list of names, it returns the corresponding value. But when I delete this value, my ListView does not return all the names on the list again, they disappear. How to solve this? Any idea?
Code of TabelaActivity.java:
package com.akzonobel.malote.tabela;
import com.akzonobel.malote.R;
import android.app.Activity;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.widget.EditText;
import android.widget.ListView;
/*
* Very basic Activity, the only things it does
* are get the ListView reference from our layout.
* Create an Adapter, set the Adapter to the ListView
* and handle the onItemClick events for when the user
* clicks on a row.
*/
public class TabelaActivity extends Activity {
EditText inputSearch;
CSVAdapter mAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tabela);
//Lookup our ListView
ListView mList = (ListView)findViewById(R.id.mList);
inputSearch = (EditText) findViewById(R.id.inputSearch);
//Create Adapter. The second parameter is required by ArrayAdapter
//which our Adapter extends. In this example though it is unused,
//so we'll pass it a "dummy" value of -1.
mAdapter = new CSVAdapter(this, -1);
//attach our Adapter to the ListView. This will populate all of the rows.
mList.setAdapter(mAdapter);
/*
* This listener will get a callback whenever the user clicks on a row.
* The pos parameter will tell us which row got clicked.
*
* For now we'll just show a Toast with the state capital for the state that was clicked.
*/
inputSearch.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence cs, int arg1, int arg2, int arg3) {
// When user changed the Text
TabelaActivity.this.mAdapter.getFilter().filter(cs);
}
#Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
int arg3) {
// TODO Auto-generated method stub
}
#Override
public void afterTextChanged(Editable arg0) {
// TODO Auto-generated method stub
}
});
}
}
Code of CSVAdapter.java:
package com.akzonobel.malote.tabela;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Color;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Filter;
import android.widget.TextView;
/*
* Very basic Custom Adapter that takes state name,capital pairs out of a csv
* file from the assets and uses those values to build a List of State objects.
* Overrides the default getView() method to return a TextView with the state name.
*
* ArrayAdapter - a type of Adapter that works a lot like ArrayList.
*/
#SuppressLint("DefaultLocale") public class CSVAdapter extends ArrayAdapter<State>{
private List<State> filteredModelItemsArray;
private Filter filter;
Context ctx;
//We must accept the textViewResourceId parameter, but it will be unused
//for the purposes of this example.
public CSVAdapter(Context context, int textViewResourceId) {
super(context, textViewResourceId);
//Store a reference to the Context so we can use it to load a file from Assets.
this.ctx = context;
//Load the data.
loadArrayFromFile();
}
#Override
public Filter getFilter() {
if (filter == null){
filter = new ModelFilter();
}
return filter;
}
/*
* getView() is the method responsible for building a View out of a some data that represents
* one row within the ListView. For this example our row will be a single TextView that
* gets populated with the state name.
* (non-Javadoc)
* #see android.widget.ArrayAdapter#getView(int, android.view.View, android.view.ViewGroup)
*/
#Override
public View getView(final int pos, View convertView, final ViewGroup parent){
/*
* Using convertView is important. The system will pass back Views that have been
* created but scrolled off of the top (or bottom) of the screen, and thus are no
* longer being shown on the screen. Since they are unused, we can "recycle" them
* instead of creating a new View object for every row, which would be wasteful,
* and lead to poor performance. The diference may not be noticeable in this
* small example. But with larger more complex projects it will make a significant
* improvement by recycling Views rather than creating new ones for each row.
*/
TextView mView = (TextView)convertView;
//If convertView was null then we have to create a new TextView.
//If it was not null then we'll re-use it by setting the appropriate
//text String to it.
if(null == mView){
mView = new TextView(parent.getContext());
mView.setTextSize(19);
mView.setTextColor(Color.WHITE);
}
//Set the state name as the text.
mView.setText(getItem(pos).getName());
//We could handle the row clicks from here. But instead
//we'll use the ListView.OnItemClickListener from inside
//of MainActivity, which provides some benefits over doing it here.
return mView;
}
/*
* Helper method that loads the data from the states.csv and builds
* each csv row into a State object which then gets added to the Adapter.
*/
private void loadArrayFromFile(){
try {
// Get input stream and Buffered Reader for our data file.
InputStream is = ctx.getAssets().open("states.csv");
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
String line;
//Read each line
while ((line = reader.readLine()) != null) {
//Create a State object for this row's data.
State cur = new State();
cur.setName(line);
//Add the State object to the ArrayList (in this case we are the ArrayList).
this.add(cur);
}
} catch (IOException e) {
e.printStackTrace();
}
}
private class ModelFilter extends Filter
{
#Override
protected FilterResults performFiltering(CharSequence constraint) {
constraint = constraint.toString().toLowerCase();
FilterResults result = new FilterResults();
if(constraint != null && constraint.toString().length() > 0)
{
ArrayList<State> filteredItems = new ArrayList<State>();
for(int i = 0, l = getCount(); i < l; i++)
{
State m = getItem(i);
if(m.getName().toLowerCase().contains(constraint))
filteredItems.add(m);
}
result.count = filteredItems.size();
result.values = filteredItems;
}
else
{
ArrayList<State> allItems = new ArrayList<State>();
for(int i = 0, l = getCount(); i < l; i++)
{
State m = getItem(i);
allItems.add(m);
}
synchronized(this)
{
result.values = allItems;
result.count = allItems.size();
}
}
return result;
}
#SuppressWarnings("unchecked")
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
filteredModelItemsArray = (ArrayList<State>)results.values;
notifyDataSetChanged();
clear();
for(int i = 0, l = filteredModelItemsArray.size(); i < l; i++)
add(filteredModelItemsArray.get(i));
notifyDataSetInvalidated();
}
}
}
Code of State.java:
package com.akzonobel.malote.tabela;
/*
* Basic Data class to hold a state name and the state capital.
*/
public class State {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
This is a fairly old bug that's never been addressed by Android. It was first reported here, Issue 9666, then closed and reopened as Issue 69179. I wouldn't hold my breath on it being fixed anytime soon. If you're curious to read more on the details of why, I wrote a small blog post talking about it.
More or less, if you want to filter your data and also add, remove, update, etc portions of it...you'll need to extend BaseAdapter and write your own solution. Or save yourself some time and take advantage of my frustrations in doing that some many times over and over that I just threw it all into an opensource library. Solves all the filtering bugs and then some: Advanced-Adapters.
I have developed my first android application.
What that application does: I update mysql database with new results on the website and the android application fetches the same data from mysql. I am using JSON.
What i want it to do: I want it to notify user that the results have been updated. It can bee a timely notification or the normal one. It does not matter. I just want the user to know about it as soon as i update database.
Code for your reference:
1) Java code that displays results inside the application.
package in.thespl.spl.notifications;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import org.apache.http.NameValuePair;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.app.ListActivity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView;
public class AllResultsActivity extends ListActivity {
// Progress Dialog
private ProgressDialog pDialog;
// Creating JSON Parser object
JSONParser jParser = new JSONParser();
ArrayList<HashMap<String, String>> productsList;
// url to get all products list
private static String url_all_products = "http://mydomain.in/fetchresult.php";
// JSON Node names
private static final String TAG_SUCCESS = "success";
private static final String TAG_PRODUCTS = "result";
private static final String TAG_PID = "rid";
private static final String TAG_NAME = "rname";
private static final String TAG_INFO = "rinfo";
// products JSONArray
JSONArray products = null;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.all_products);
// Hashmap for ListView
productsList = new ArrayList<HashMap<String, String>>();
// Loading products in Background Thread
new LoadAllProducts().execute();
// Get listview
ListView lv = getListView();
// on seleting single product
// launching Edit Product Screen
lv.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
// getting values from selected ListItem
String pid = ((TextView) view.findViewById(R.id.rid)).getText()
.toString();
// Starting new intent
Intent in = new Intent(getApplicationContext(),
AllResultsActivity.class);
// sending pid to next activity
in.putExtra(TAG_PID, pid);
// starting new activity and expecting some response back
startActivityForResult(in, 100);
}
});
}
// Response from Edit Product Activity
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// if result code 100
if (resultCode == 100) {
// if result code 100 is received
// means user edited/deleted product
// reload this screen again
Intent intent = getIntent();
finish();
startActivity(intent);
}
}
/**
* Background Async Task to Load all product by making HTTP Request
* */
class LoadAllProducts extends AsyncTask<String, String, String> {
/**
* Before starting background thread Show Progress Dialog
* */
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(AllResultsActivity.this);
pDialog.setMessage("Loading results. Please wait...");
pDialog.setIndeterminate(false);
pDialog.setCancelable(false);
pDialog.show();
}
/**
* getting All products from url
* */
protected String doInBackground(String... args) {
// Building Parameters
List<NameValuePair> params = new ArrayList<NameValuePair>();
// getting JSON string from URL
JSONObject json = jParser.makeHttpRequest(url_all_products, "GET", params);
// Check your log cat for JSON reponse
Log.d("All Products: ", json.toString());
try {
// Checking for SUCCESS TAG
int success = json.getInt(TAG_SUCCESS);
if (success == 1) {
// products found
// Getting Array of Products
products = json.getJSONArray(TAG_PRODUCTS);
// looping through All Products
for (int i = 0; i < products.length(); i++) {
JSONObject c = products.getJSONObject(i);
// Storing each json item in variable
String id = c.getString(TAG_PID);
String name = c.getString(TAG_NAME);
String info = c.getString(TAG_INFO);
// creating new HashMap
HashMap<String, String> map = new HashMap<String, String>();
// adding each child node to HashMap key => value
map.put(TAG_PID, id);
map.put(TAG_NAME, name);
map.put(TAG_INFO, info);
// adding HashList to ArrayList
productsList.add(map);
}
} else {
// no products found
// Launch Add New product Activity
// Intent i = new Intent(getApplicationContext(),
// AllResultsActivity.class);
// Closing all previous activities
//i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
// startActivity(i);
}
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
/**
* After completing background task Dismiss the progress dialog
* **/
protected void onPostExecute(String file_url) {
// dismiss the dialog after getting all products
pDialog.dismiss();
// updating UI from Background Thread
runOnUiThread(new Runnable() {
public void run() {
/**
* Updating parsed JSON data into ListView
* */
ListAdapter adapter = new SimpleAdapter(
AllResultsActivity.this, productsList,
R.layout.list_item, new String[] { TAG_PID,
TAG_NAME, TAG_INFO },
new int[] { R.id.rid, R.id.rname, R.id.rinfo});
// updating listview
setListAdapter(adapter);
}
});
}
}
}
Any idea how to add a notification feature in this?
You have multiple ways to do that.
First way is to poll the server to ask for update.
This solution isn't really efficient and lot of params are had to choose:
Time to update-> will affect battery and reactivity.
Second way is to use Google Cloud Messaging. It provides a solution to push data from server to user. It's really simple to implement. (took me some hours).
Android documentation.
http://developer.android.com/guide/google/gcm/index.html
This second way optimizes battery and you could receive push even if your app is off.
Choose the way it's better for your needs.
Hope it helps you.