In this task you will learn how to add buttons to your user interface to allow the user to join and leave sites, also you will add buttons to allow sites to be added to favorites (or removed) and also to cancel any pending requests to moderated sites. When an operation is carried out, a toast indicates the nature of the change.
-
MainActivity needs to be changed to allow the passing of the
siteService object to the
SiteDetailActivity. The siteService object
is Parcelable, so this needs to be taken into account when
unpacking it. Modify your MainActivity as follows:
package com.alfresco.tutorials.sitetest; import java.util.ArrayList; import org.alfresco.mobile.android.api.exceptions.AlfrescoSessionException; import org.alfresco.mobile.android.api.model.Site; import org.alfresco.mobile.android.api.services.SiteService; import org.alfresco.mobile.android.api.session.RepositorySession; import android.app.Activity; import android.content.Intent; import android.os.AsyncTask; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.AdapterView.OnItemClickListener; import android.widget.Toast; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.AdapterView; public class MainActivity extends Activity { private SiteArrayAdapter adapter; private ArrayList<Site> sites; private SiteService siteService; private RepositorySession session; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); LinearLayout ll = (LinearLayout) findViewById(R.id.linearLayout); ListView lv = new ListView(this); sites = new ArrayList<Site>(); adapter = new SiteArrayAdapter(this, sites); lv.setAdapter(adapter); ll.addView(lv); adapter.setNotifyOnChange(true); lv.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Intent intent = new Intent(getApplicationContext(), SiteDetailActivity.class); Site site = sites.get(position); intent.putExtra("targetSite", site); intent.putExtra("siteService", siteService); startActivity(intent); } }); // Modify to suit your SkyVault server installation String url = "http://localhost:8080/alfresco"; String username = "admin"; String password = "admin"; new ConnectToRepo().execute(url, username, password); } class ConnectToRepo extends AsyncTask<String, Integer, String> { private static final String TAG = "ConnectToRepo"; @Override protected String doInBackground(String... params) { Log.d(TAG, "doInBackground"); Log.d(TAG, params[0] + ":" + params[1] + ":" + params[2]); String url = params[0]; String username = params[1]; String password = params[2]; try { // connect to on-premise repo session = RepositorySession.connect(url, username, password); // Get site service siteService = session.getServiceRegistry() .getSiteService(); // Get all sites sites = (ArrayList<Site>) siteService.getAllSites(); } catch (AlfrescoSessionException e) { Log.e(TAG, "Failed to connect: " + e.toString()); System.exit(0); } Log.d(TAG, "doInBackground Complete"); return "doInBackground Complete"; } @Override protected void onPostExecute(String result) { super.onPostExecute(result); Log.d(TAG, "onPostExecute"); Toast.makeText(MainActivity.this, result, Toast.LENGTH_LONG).show(); adapter.addSites((ArrayList<Site>) sites); adapter.notifyDataSetChanged(); } } }
The main change here is to pull out the siteService object as a private variable (so it can be accessed outside of the code where it is initialized), and is then packaged into an intent, which will be sent to SiteDetailActivity.
Note: As always you will need to change the URL, username and password to suit your SkyVault installation. -
The SiteDetailActivity also needs to be changed. Modify your
code as follows:
package com.alfresco.tutorials.sitetest; import java.util.List; import org.alfresco.mobile.android.api.exceptions.AlfrescoServiceException; import org.alfresco.mobile.android.api.model.Site; import org.alfresco.mobile.android.api.services.SiteService; import android.os.AsyncTask; import android.os.Bundle; import android.app.Activity; import android.content.Intent; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TableLayout; import android.widget.TextView; import android.widget.Toast; import android.support.v4.app.NavUtils; public class SiteDetailActivity extends Activity { private static final String TAG = "SiteDetailActivity"; private static final int NOP = 0; private static final int JOIN = 100; private static final int JOIN_REQUEST = 101; private static final int LEAVE = 102; private static final int CANCEL = 103; private static final int ADD_FAVE = 104; private static final int REMOVE_FAVE = 105; private Site site; private SiteService siteService; private int operation = NOP; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_site_detail); // Show the Up button in the action bar. getActionBar().setDisplayHomeAsUpEnabled(true); // Get message from intent Intent intent = getIntent(); site = (Site) intent.getSerializableExtra("targetSite"); siteService = (SiteService) intent.getParcelableExtra("siteService"); // We now need to display site details in a UI TextView tv = (TextView) findViewById(R.id.site_short_name_value); tv.setText((CharSequence) site.getShortName()); tv = (TextView) findViewById(R.id.site_description_value); tv.setText((CharSequence) site.getDescription()); tv = (TextView) findViewById(R.id.site_identifier_value); tv.setText((CharSequence) site.getIdentifier()); tv = (TextView) findViewById(R.id.site_GUID_value); tv.setText((CharSequence) site.getGUID()); tv = (TextView) findViewById(R.id.site_title_value); tv.setText((CharSequence) site.getTitle()); tv = (TextView) findViewById(R.id.site_visibility_value); tv.setText((CharSequence) site.getVisibility().value()); // isFavorite if (site.isFavorite()) { tv = (TextView) findViewById(R.id.site_is_favorite_value); tv.setText("True"); } else { tv = (TextView) findViewById(R.id.site_is_favorite_value); tv.setText("False"); } // isMember if (site.isMember()) { tv = (TextView) findViewById(R.id.site_is_member_value); tv.setText("True"); } else { tv = (TextView) findViewById(R.id.site_is_member_value); tv.setText("False"); } // isPendingMember if (site.isPendingMember()) { tv = (TextView) findViewById(R.id.site_is_pending_member_value); tv.setText("True"); } else { tv = (TextView) findViewById(R.id.site_is_pending_member_value); tv.setText("False"); } drawButtons(); } public void drawButtons() { String visibility = site.getVisibility().value(); boolean isMember = site.isMember(); boolean isPendingMember = site.isPendingMember(); boolean isFavorite = site.isFavorite(); Log.d(TAG, "DRAW_BUTTONS..."); // if public and not member draw Join if (visibility.equalsIgnoreCase("PUBLIC") && !isMember) { Log.d(TAG, "DRAW_BUTTONS: draw Join button"); Button btn = new Button(this); btn.setText("Join"); TableLayout layout = (TableLayout) findViewById(R.id.tableLayout); layout.addView(btn); btn.setId(JOIN); btn.setOnClickListener(buttonListener); } // if member draw Leave if (isMember) { Log.d(TAG, "DRAW_BUTTONS: draw Leave button"); Button btn = new Button(this); btn.setText("Leave"); TableLayout layout = (TableLayout) findViewById(R.id.tableLayout); layout.addView(btn); btn.setId(LEAVE); btn.setOnClickListener(buttonListener); } // if moderated and not member draw Join Request, but not if request pending if (visibility.equalsIgnoreCase("MODERATED") && !isMember && !isPendingMember) { Log.d(TAG, "DRAW_BUTTONS: draw Join Request button"); Button btn = new Button(this); btn.setText("Join Request"); TableLayout layout = (TableLayout) findViewById(R.id.tableLayout); layout.addView(btn); btn.setId(JOIN_REQUEST); btn.setOnClickListener(buttonListener); } // if member and not favorite draw Add to favorites if (isMember && !isFavorite) { Log.d(TAG, "DRAW_BUTTONS: draw Add to favorites button"); Button btn = new Button(this); btn.setText("Add to Favorites"); TableLayout layout = (TableLayout) findViewById(R.id.tableLayout); layout.addView(btn); btn.setId(ADD_FAVE); btn.setOnClickListener(buttonListener); } // if join request pending draw Cancel join request if (isPendingMember) { Log.d(TAG, "DRAW_BUTTONS: draw Cancel join request button"); Button btn = new Button(this); btn.setText("Cancel Join Request"); TableLayout layout = (TableLayout) findViewById(R.id.tableLayout); layout.addView(btn); btn.setId(CANCEL); btn.setOnClickListener(buttonListener); } // if favorite draw remove from favorites if (isFavorite) { Log.d(TAG, "DRAW_BUTTONS: draw Remove from favorites button"); Button btn = new Button(this); btn.setText("Remove from Favorites"); TableLayout layout = (TableLayout) findViewById(R.id.tableLayout); layout.addView(btn); btn.setId(REMOVE_FAVE); btn.setOnClickListener(buttonListener); } } private OnClickListener buttonListener = new OnClickListener() { @Override public void onClick(View v) { operation = v.getId(); // p1 and p2 for future use. Operation is passed but not used. new SubmitSiteOperation().execute(String.valueOf(operation), "p1", "p2"); } }; @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.activity_site_detail, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: // This ID represents the Home or Up button. In the case of this // activity, the Up button is shown. Use NavUtils to allow users // to navigate up one level in the application structure. For // more details, see the Navigation pattern on Android Design: // // http://developer.android.com/design/patterns/navigation.html#up-vs-back // NavUtils.navigateUpFromSameTask(this); return true; } return super.onOptionsItemSelected(item); } class SubmitSiteOperation extends AsyncTask<String, Integer, String> { private static final String TAG = "SubmitSiteOperations"; private String message; @Override protected String doInBackground(String... params) { Log.d(TAG, "doInBackground"); Log.d(TAG, params[0] + ":" + params[1] + ":" + params[2]); try { switch (operation) { case JOIN: site = siteService.joinSite(site); message = "You joined site "+site.getShortName(); break; case LEAVE: site = siteService.leaveSite(site); message = "You left site "+site.getShortName(); break; case JOIN_REQUEST: site = siteService.joinSite(site); message = "Request queued for site "+site.getShortName(); break; case ADD_FAVE: site = siteService.addFavoriteSite(site); message = site.getShortName()+" added to your favorites"; break; case CANCEL: // get pending site requests // and cancel where shortName matches List<Site> requests = siteService .getPendingSites(); for (Site request : requests) { if (request.getShortName().equals( site.getShortName())) { site = siteService.cancelRequestToJoinSite(request); } } message = "Requests cancelled for "+site.getShortName(); break; case REMOVE_FAVE: site = siteService.removeFavoriteSite(site); message = site.getShortName()+" removed from your favorites"; break; case NOP: message = "Nothing useful!"; break; } } catch (AlfrescoServiceException e) { Log.e(TAG, "Error while working with site: " + site.getShortName()); Log.e(TAG, "Exception generated: " + e.toString()); Log.e(TAG, "With Error Code: " + e.getErrorCode()); System.exit(0); } Log.d(TAG, "Operation Complete: " + operation + " "+message); return message; } @Override protected void onPostExecute(String result) { super.onPostExecute(result); Log.d(TAG, "onPostExecute"); Toast.makeText(SiteDetailActivity.this, result, Toast.LENGTH_LONG) .show(); } } }
There are a number of additions here over the previous code. First, constants for the various site operations that can be handled are defined. Also a variable to store the unpacked siteService object is declared. Note that siteService is a parcelable object, so is unpacked with a different method call to serializable objects.
Code to dynamically draw the relevant buttons, depending on the site status, is located in drawButtons(). This method determines what the relevant buttons to draw are, and then dynamically creates them and adds them to the user interface. Once the user clicks the button to perform the operation they want, the button id is recorded and this is used to set the required operation.
As network operations, such as requesting to join a site, cannot be carried out in the main UI thread in Android, these site operations (join, leave, and so on) are moved to an Async task. The switch statement routes the operation request to the correct code.
The onPostExecute() code simply displays a toast providing some feedback to the user that the required operation has been carried out.
-
You are now ready to run your application. You will be presented with a list of
sites. Click on a site will show you relevant buttons depending on your
membership status, as shown in the following screenshot:
- Play with the application thoroughly to make sure it works as you expect. Feel free to create more test sites in Share.