I am able to successfully download all files from aws s3 bucket, so when I click on the particular list item the list item gets download. But, I want all s3 bucket item automatically download when activity is launched.
/**
* DownloadSelectionActivity displays a list of files in the bucket. Users can
* select a file to download.
*/
public class DownloadSelectionActivity extends ListActivity {
// The S3 client used for getting the list of objects in the bucket
private AmazonS3Client s3;
// An adapter to show the objects
private SimpleAdapter simpleAdapter;
private ArrayList<HashMap<String, Object>> transferRecordMaps;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_download_selection);
initData();
initUI();
}
#Override
protected void onResume() {
super.onResume();
// Refresh the file list.
new GetFileListTask().execute();
}
private void initData() {
// Gets the default S3 client.
s3 = Util.getS3Client(DownloadSelectionActivity.this);
transferRecordMaps = new ArrayList<HashMap<String, Object>>();
}
private void initUI() {
simpleAdapter = new SimpleAdapter(this, transferRecordMaps,
R.layout.bucket_item, new String[] {
"key"
},
new int[] {
R.id.key
});
simpleAdapter.setViewBinder(new ViewBinder() {
#Override
public boolean setViewValue(View view, Object data,
String textRepresentation) {
switch (view.getId()) {
case R.id.key:
TextView fileName = (TextView) view;
fileName.setText((String) data);
return true;
}
return false;
}
});
// When an item is selected, finish the activity and pass back the S3
// key associated with the object selected
getListView().setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(final AdapterView<?> adapterView, View view, int pos, long id) {
Intent intent = new Intent();
intent.putExtra("key", (String) transferRecordMaps.get(pos).get("key"));
setResult(RESULT_OK, intent);
finish();
}
});
}
/**
* This async task queries S3 for all files in the given bucket so that they
* can be displayed on the screen
*/
private class GetFileListTask extends AsyncTask<Void, Void, Void> {
// The list of objects we find in the S3 bucket
private List<S3ObjectSummary> s3ObjList;
// A dialog to let the user know we are retrieving the files
private ProgressDialog dialog;
#Override
protected void onPreExecute() {
dialog = ProgressDialog.show(DownloadSelectionActivity.this,
getString(R.string.refreshing),
getString(R.string.please_wait));
}
#Override
protected Void doInBackground(Void... inputs) {
// Queries files in the bucket from S3.
s3ObjList = s3.listObjects(Constants.BUCKET_NAME).getObjectSummaries();
transferRecordMaps.clear();
for (S3ObjectSummary summary : s3ObjList) {
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("key", summary.getKey());
transferRecordMaps.add(map);
}
return null;
}
#Override
protected void onPostExecute(Void result) {
dialog.dismiss();
simpleAdapter.notifyDataSetChanged();
}
}
}
You already have the list of objects in the bucket, you could just iterate through the list and download each one when the list operation has completed. It might be easier to handle the transfers (allowing pause/resume, checking status, ect...) using the Transfer Utility, which is a high level utility on top of the standard S3 Client.
A guide for the Transfer Utility can be found here (http://docs.aws.amazon.com/mobile/sdkforandroid/developerguide/s3transferutility.html)
Related
I have a ListView which I populate with data from DataStore or from my local database.
I am checking some condition that will determine whether I will fetch data from the DataStore or database. When I fetch from the database the ListView automatically refreshes itself, but when I fetch from the DataStore it does not. I then have to click my TextView, which is below ListView, and when I click it the soft keyboard appears and then my ListView is populated with data from DataStore.
My activity that has the ListView:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_xyz);
list_View = (ListView) findViewById(R.id.data_listView);
list_View.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
list_View.setMultiChoiceModeListener(new Selector());
adapter = new MyAdapter(context,Long.valueOf(id),isOnline());
list_View.setAdapter(adapter);
list_View.setSelection(adapter.getCount() - 1);
adapter.registerDataSetObserver(new DataSetObserver() {
#Override
public void onChanged() {
super.onChanged();
list_View.setSelection(adapter.getCount() - 1);
}
LoadDataTask ldt = new LoadDataTask();
ldt.execute("123456789");
}
private void loadDataFromDataStore(final Long contactId){
final ArrayList<Data> data = new ArrayList<>();;
d("loadingdataFromDatasore");
GetDataTask task = new GetDataTask(new ApiTask.ResultListener() {
#Override
public void successHook(Object o) {
if (o instanceof GetDataResponse) {
GetDataResponse res = (GetDataResponse) o;
if (res.getData() != null && res.getData().getItems() != null) {
for (ListDataItem i : res.getData().getItems()) {
Data dp = new Data(i.getPosition(), i.getMessage(), i.getDateCreated(),i.getMessageId(),1);
adapter.addFromOtherThread(dp);
}
}
d("Messages loaded from server: " + adapter.getCount());
}
}
}
public class LoadDataTask extends AsyncTask<String,String,Void> {
#Override
protected Void doInBackground(String... params){
if(isOnline && isFirstTime){
loadDataFromDataStore(Long.valueOf(params[0]));
}else{
//load from database
}
return null;
}
#Override
protected void onPostExecute(Void v){
adapter.notifyDataSetChanged();
}
}
My adapter class that extends BaseAdapter (I have removed unnecessary code for this question):
public class DataAdapter extends BaseAdapter {
private ArrayList<Data>data_list;
public DataAdapter(){
data_list = new ArrayList<>();
}
public void addFromOtherThread(Data object) {
data_list.add(object);
}
What am I missing that is making listview not to automatically refresh itself even after calling notifyDatasetChanged()?
change :
#Override
protected void onPostExecute(Void v){
adapter.notifyDataSetChanged();
}
}
to:
#Override
protected void onPostExecute(Void v){
adapter.notifyDataSetChanged();
list_View.setAdapter(adapter);
}
}
Let me know if more clarification is required by commenting below.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_xyz);
list_View = (ListView) findViewById(R.id.data_listView);
list_View.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
list_View.setMultiChoiceModeListener(new Selector());
adapter = new MyAdapter(context,Long.valueOf(id),isOnline());
list_View.setAdapter(adapter);
list_View.setSelection(adapter.getCount() - 1);
adapter.registerDataSetObserver(new DataSetObserver() {
#Override
public void onChanged() {
super.onChanged();
list_View.setSelection(adapter.getCount() - 1);
}
loadDataFromDataStore("123456789")
}
private void loadDataFromDataStore(final Long contactId){
final ArrayList<Data> data = new ArrayList<>();;
d("loadingdataFromDatasore");
new GetDataTask(new ApiTask.ResultListener() {
#Override
public void successHook(Object o) {
if (o instanceof GetDataResponse) {
GetDataResponse res = (GetDataResponse) o;
if (res.getData() != null && res.getData().getItems() != null) {
for (ListDataItem i : res.getData().getItems()) {
Data dp = new Data(i.getPosition(), i.getMessage(), i.getDateCreated(),i.getMessageId(),1);
adapter.addFromOtherThread(dp);
}
}
d("Messages loaded from server: " + adapter.getCount());
adapter.notifyDatasetChanges();
}
}
}.execute();
}
GetDataTask should work on background internally you don't need to starts a AsyncTask from here.
If you want to use AsyncTask then your AsyncTask should wait for the result from GetDataTask which it is not doing in your code implementation.
I don't know which kind of framework you are using to making api call but your implementation seems to look wrong.
I have write the code on assumption bases if your GetDataTask is a AsyncTask or some background processor it will work perfectly.
My app requires to parse a XML file when the activity is launched. So, I use an Asynctask to parse the XML.
After parsing the XML file, I get the count of number of test-cases in the XML in doInBackground() method, and I use the variable alTestCaseList to keep this count.
Later in onPostExecute() method, I set the ArrayAdapter and register the click listener for the list.
However, when I click any testcase from the list, I'm supposed to parse the test-case entries from the XML again.
So I believe for this I'll have to use an AsyncTask again. So do I start another AsyncTask for onPostExecute() method of first AsyncTask?
Is there any other neat way of doing this?
I tried to put setOnItemClickListener() in onCreate() method, but it resulted in fatal exception with the message: "setOnItemClickListener(android.widget.AdapterView$OnItemClickListener) on a null object reference"........
Kindly give your suggestion.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_testcases);
xmlHelp = new XmlHelper();
ConfigParser confParser = new ConfigParser();
confParser.execute();
}
private class ConfigParser extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
alTestCaseList = xmlHelp.getNumberOfNodes();
return null;
}
#Override
protected void onPostExecute(Void v) {
testCasesListView = (ListView) findViewById(R.id.lstTestCases);
arrayAdapter = new ArrayAdapter(TestCasesActivity.this, android.R.layout.simple_list_item_1, alTestCaseList);
testCasesListView.setAdapter(arrayAdapter);
testCasesListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapter, View v, int position, long arg3) {
String value = (String) adapter.getItemAtPosition(position);
Log.d("QcTool", "Selected: " + value);
}
});
}
}
Here is my take on the solution. Pass your data as an argument to the task and notify the adapter when you get the list.
See the comments for further explanation. Note that this approach does not handle issues that AsyncTask's typically come with is situations such as configuration changes.
You can then create another ParseXmlTask class which can be called in your OnItemClicked method
private ListView testCasesListView;
private ArrayAdapter arrayAdapter;
private List<String> testCasesList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_testcases);
//Init the list - it's empty but your task will fill it.
testCasesList = new ArrayList<>();
//Init your listView
testCasesListView = (ListView) findViewById(R.id.lstTestCases);
//Add adapter to the listView
arrayAdapter = new ArrayAdapter(TestCasesActivity.this, android.R.layout.simple_list_item_1, alTestCaseList);
//Add your click event
testCasesListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapter, View v, int position, long arg3) {
//When clicked, do something awesome
String value = (String) adapter.getItemAtPosition(position);
Log.d("QcTool", "Selected: " + value);
//Create and start parseXmlTask here
}
});
xmlHelp = new XmlHelper();
//Pass in your callback as an argument
ConfigParserTask confParser = new ConfigParserTask(new OnConfigParserTaskCompleted(){
public void onConfigParserTaskCompleted(List<String> result){
//Simply refresh the list
testCasesList.clear();
testCasesList.addAll(result);
//Let the adapter know that the list has changed
//Then update the list view
arrayAdapter.notifyDataSetChanged();
}
});
confParser.execute(xmlHelp);
}
//It's better to pass in the info to the task as arguments than it is to rely on
//field variables
private class ConfigParserTask extends AsyncTask<XmlHelper, Void, List<String>> {
private OnConfigParserTaskCompleted listener;
public ConfigParser(OnConfigParserTaskCompleted listener){
this.listener = listener;
}
#Override
protected Void doInBackground(XmlHelper... params) {
//Do what you need to in the background
//Get your nodes then return it here
List<String> nodes = params[0].getNumberOfNodes();
return nodes;
}
#Override
protected void onPostExecute(List<String> result) {
//pass the result to the callback
listener.onConfigParserTaskCompleted(result);
}
}
//Callback to let your activity/fragment know when
//the task is complete
public interface OnConfigParserTaskCompleted{
public void onConfigParserTaskCompleted(List<String> result);
}
You can do something like this using AsyncTasks
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_testcases);
testCasesListView = (ListView) findViewById(R.id.lstTestCases);
testCasesListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapter, View v, int position, long arg3) {
String value = (String) adapter.getItemAtPosition(position);
Log.d("QcTool", "Selected: " + value);
ParserNodeTask nodeTask = new ParserNodeTask();
nodeTask.execute(value);
}
});
xmlHelp = new XmlHelper();
ParserNumberOfNodesTask numberOfNodesTask = new ParserNumberOfNodesTask();
numberOfNodesTask.execute();
}
private class ParserNumberOfNodesTask extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
alTestCaseList = xmlHelp.getNumberOfNodes();
return null;
}
#Override
protected void onPostExecute(Void v) {
arrayAdapter = new ArrayAdapter(TestCasesActivity.this, android.R.layout.simple_list_item_1, alTestCaseList);
testCasesListView.setAdapter(arrayAdapter);
}
}
private class ParserNodeTask extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(String... params) {
String value = params[0];
//TODO : parse the selected node
}
#Override
protected void onPostExecute(Void v) {
//TODO: dunno what you need to do later
}
}
Though AsyncTasks are not ideal for this for many reasons (but easier to implement). You should maybe take a look on to Loaders or Services (i.e https://stackoverflow.com/a/6957909/665823)
I am programming a messaging app and I want to add users in a group. However, when a list of users pops up and I select one from the list, it doesn't pass the string (the username) to the other activity. All I get is an empty list.
Here is my code:
First Activity = Sending data (usernames from list) through putExtra()
public class ListUsersActivity extends Activity {
private String currentUserId;
private ArrayAdapter<String> namesArrayAdapter;
private ArrayList<String> names;
private ListView usersListView;
private Button logoutButton;
private ProgressDialog progressDialog;
private BroadcastReceiver receiver = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list_users);
Parse.initialize(this, "embpZ0spRUv5XwDgI23innll1sgHg0KZNiKzg6kl", "LPsU4UffPeqFXkQB1GfLCIJ4kvg20llPgbOnLise");
currentUserId = ParseUser.getCurrentUser().getObjectId();
names = new ArrayList<>();
ParseQuery<ParseUser> query = ParseUser.getQuery();
query.whereNotEqualTo("objectId", currentUserId);
query.findInBackground(new FindCallback<ParseUser>() {
public void done(List<ParseUser> userList, com.parse.ParseException e) {
if (e == null) {
for (int i=0; i<userList.size(); i++) {
names.add(userList.get(i).getUsername().toString());
}
usersListView = (ListView)findViewById(R.id.usersListView);
namesArrayAdapter =
new ArrayAdapter<String>(getApplicationContext(),
R.layout.user_list_item, names);
usersListView.setAdapter(namesArrayAdapter);
usersListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> a, View v, int i, long l) {
Intent goBackToAddPoolIntent = new Intent(ListUsersActivity.this, addNewPoolActivity.class);
addNewPoolActivity checker = new addNewPoolActivity();
checker.checkIfUserIsSelected(usersListView.getItemAtPosition(i).toString());
goBackToAddPoolIntent.putExtra("username", usersListView.getItemAtPosition(i).toString());
startActivity(goBackToAddPoolIntent);
}
});
} else {
Toast.makeText(getApplicationContext(),
"Error loading user list",
Toast.LENGTH_LONG).show();
}
}
});
}
Second Activity = Receiving data from putExtra()
public class addNewPoolActivity extends Activity {
private static ArrayList<String> addedUsers;
private ArrayAdapter <String> addedUserAdapter;
private boolean userIsSelected;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_new_pool);
Button addMembers = (Button) findViewById(R.id.bAddMembers);
addedUsers = new ArrayList<>();
//addedUsers.add("Group Members");
addMembers.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent showUsersToSelect = new Intent(addNewPoolActivity.this, ListUsersActivity.class);
startActivity(showUsersToSelect);
}
});
ListView addedUsersList = (ListView) findViewById(R.id.addedUsersListView);
addedUserAdapter = new ArrayAdapter<>(this, R.layout.user_list_item, addedUsers);
addedUsersList.setAdapter(addedUserAdapter);
if(userIsSelected){
Bundle extras = getIntent().getExtras();
addedUsers.add(extras.getString("username"));
}
}
public void checkIfUserIsSelected(String user){
if (user!=null){
userIsSelected = true;
}else{
userIsSelected = false;
}
}
Since the default value for a boolean is false, the code is never called because
if(userIsSelected){
will always evaluate to false since you have declared the varaible as
private boolean userIsSelected;
and the first snippet here is in onCreate() so it will only run the first time the Activity is created.
Maybe you are wanting to call checkIfUserIsSelected(someUser) before that code but without more context of what you hope to accomplish, it's hard to say.
Possibly, you want to use startActivityForResult() in some way?
In addition to #codeMagic 's answer (Since your boolean value is false, it won't call the statement that you are adding the new data). It's also because of you parse the Data "username" after you setAdapter of your ListView. So basically you are setting the data, and then trying to add the new data you parsed to the list. Either you need to do it before setting your data set to your adapter, or call addedUsersAdapter.notifyDataSetChanged() to refresh your listView's data set.
addedUserAdapter = new ArrayAdapter<>(this, R.layout.user_list_item, addedUsers);
addedUsersList.setAdapter(addedUserAdapter);
Bundle extras = getIntent().getExtras();
// Check if the username has been sent to this Activity.
if(extras != null && extras.containsKey("username")){
addedUsers.add(extras.getString("username"));
// Refresh Your Data Set
addedUserAdapter.notifyDataSetChanged();
}
I'm trying to achieve the following:
Screen 1 shows list data from server
User presses "+" button on top right to add a new item
Screen 2 shows with text field
User enters data and clicks save
Now I want to go back to Screen 1 and refresh the list from server so that the newly added item shows up
I'm having problems achieving point 5 above. This is what I have so far:
I have an AyncTask like following:
public class MyActivity extends SherlockListActivity {
ArrayList<HashMap<String, String>> taskList;
//this grabs data from server and loads it in ArrayList
protected void loadList() {
taskList = new ArrayList<HashMap<String, String>>();
final RestAdapter restAdapter = new RestAdapter.Builder().setServer("http://10.0.2.2:8080").build();
final TaskService apiManager = restAdapter.create(TaskService.class);
final Task task = apiManager.getTask("someuser", task_id);
for (Item item : task.getItems()) {
String t_id = t.getId()+"";
String name = t.getName();
HashMap<String, String> map = new HashMap<String, String>();
map.put("act_id", act_id);
map.put("t_id", t_id);
map.put("t_name", name);
taskList.add(map);
}
}
public void onCreate (Bundle b) {
new LoadItems().execute();
}
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getTitle().equals("Create")) {
Intent create = new Intent(getApplicationContext(), CreateTask.class);
startActivityForResult(create, 1);
return true;
}
return true;
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 1) {
//item got added now load again from server
if (resultCode == RESULT_OK) {
String result = data.getStringExtra("result");
new UpdateItems.execute();
adapter.notifyDataSetChanged();
}
}
}
class UpdateItems extends AsyncTask<String, String, String> {
protected String doInBackground(String... args) {
loadList();
return null;
}
}
class LoadItems extends AsyncTask<String, String, String> {
protected String doInBackground(String... args) {
loadList();
}
protected void onPostExecute(String file_url) {
adapter = new SimpleAdapter(
MyActivity.class, taskList,
R.layout.list_item_rec, new String[] { "act_id", "t_id", "t_name"}, new int[] {
R.id.act_id, R.id.t_id,R.id.t_name });
setListAdapter(adapter);
}
}
Question
How can I reload the data from the server in onActivityResult. Based on above, what I'm doing is creating another AynchTask only for loading the data again and then calling notifyDataSetChanged(). This doesn't seem to be working.
Is my process wrong? Is there a better way to do this? I am stumped....
You have to reload the data in UpdateItems onPostExecute() method..because you are loading data in AsynchTask it loads data in another thread and updating the ListView but the list is not loaded at that time..so change your AsynchTask like this..
class UpdateItems extends AsyncTask<String, String, String> {
protected String doInBackground(String... args) {
loadList();
return null;
}
#Override
protected void onPostExecute(String result) {
adapter.notifyDataSetChanged();
}
}
and remove this line adapter.notifyDataSetChanged() in onActivityResult()
in my app im using gridview
when in portrait mode it shows one column.
in landscape mode new layout defined to show 2 column.
this is how the app works..
when app is launched, progress dialog is called to load website name from sqlite database and async is used to load website from sqlite db. the progress dialog is dismissed after the gridview is inflated.
now after loading the website name into gridview the screen orientation changes, it restarts the progress dialog.
i know that on screen orientation change the ondestroy() and then oncreate() are called.
this is my app's src code.
public class RSSReaderActivity extends Activity {
private ProgressDialog pDialog;
ArrayList<HashMap<String, String>> rssFeedList;
RSSParser rssParser = new RSSParser();
RSSFeed rssFeed;
Button add_rss;
// array to trace sqlite ids
String[] sqliteIds;
public static String TAG_ID = "id";
public static String TAG_TITLE = "title";
public static String TAG_LINK = "link";
GridView gridview;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.site_list);
add_rss = (Button) findViewById(R.id.add_rss);
gridview = (GridView) findViewById(R.id.gridview);
rssFeedList = new ArrayList<HashMap<String, String>>();
new loadStoreSites().execute();
gridview.setOnItemClickListener(new OnItemClickListener() {
...
...
);
add_rss.setOnClickListener(new View.OnClickListener() {
...
...
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// if result code 100
if (resultCode == 100) {
// reload this screen again
Intent intent = getIntent();
finish();
startActivity(intent);
}
}
class loadStoreSites extends AsyncTask<String, String, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
...
...
}
#Override
protected String doInBackground(String... args) {
// updating UI from Background Thread
runOnUiThread(new Runnable() {
public void run() {
RSSDatabaseHandler rssDb = new RSSDatabaseHandler(getApplicationContext());
// listing all websites from SQLite
List<WebSite> siteList = rssDb.getAllSites();
sqliteIds = new String[siteList.size()];
// loop through each website
for (int i = 0; i < siteList.size(); i++) {
WebSite s = siteList.get(i);
// creating new HashMap
HashMap<String, String> map = new HashMap<String, String>();
// adding each child node to HashMap key => value
map.put(TAG_ID, s.getId().toString());
map.put(TAG_TITLE, s.getTitle());
map.put(TAG_LINK, s.getLink());
// adding HashList to ArrayList
rssFeedList.add(map);
// add sqlite id to array
// used when deleting a website from sqlite
sqliteIds[i] = s.getId().toString();
}
gridview.setAdapter(new SimpleAdapter(RSSReaderActivity.this,rssFeedList, R.layout.site_list_row,new String[] { TAG_ID, TAG_TITLE, TAG_LINK },new int[] { R.id.sqlite_id, R.id.title, R.id.link }));
registerForContextMenu(gridview);
}
});
return null;
}
protected void onPostExecute(String args) {
// dismiss the dialog after getting all products
pDialog.dismiss();
}
}
}
SO how do we use onsavedinstance() over here.. please can anyone guide me.
add this in menifest file
android:configChanges="keyboardHidden|orientation|screenSize"