Documentation : Permissions - Android

This example shows how to protect your shared data.

Application consists of only one model, which has two fields. First field - title - has default set of permissions, which means that it can be read, created and updated by any user. However, second field - director - can be read, created and updated only by user, who owns this record. In this example we will see that first field is visible for both users, where second is visible only for creator. Main screen of application contains list of model entities and two buttons. User can add new entity and synchronize with mobeelizer cloud. There are two users in the system and there's a possibility to switch user on application life time.

Design Your App

First of all, create new application in Mobeelizer App Designer called Permissions.

Secondly, create new model called PermissionsEntity.

We will need two fields. Firstly, create text field, name it title and use default credentials. Secondly, create text field called director and set credentials to own for each option.

For now leave conflict resolving property on overwrite. By default, there is one group - users, device category - mobile and role - users-mobile define. Deploy application to test environment. On test environment create two users with passwords: 

  • a - usera
  • b - userb

Last thing to do in App Designer is download configured template for android. Select installed Andoird SDK in target SDK field.

Use the Mobeelizer SDK

Extract downloaded zip file then open eclipse and import project.

Add resource files

Before we start  implementing our example we will add some resource files into the project:

Prepare main screen

We will start with creating main screen controls, as you read before on main screen there is list of model entities, two buttons to synchronize and add new entity and enother one to switch between users.

main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <TextView
            android:layout_marginTop="20dip"
            android:layout_marginLeft="50dip"
            android:textSize="25dip"
            android:id="@+id/currentUser"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentTop="true"
            android:bufferType="spannable"
            android:text="Permissions" />
                 
        <ImageButton
            android:layout_height="50dip"
            android:layout_width="50dip"
            android:layout_marginLeft="260dip"
            android:layout_marginTop="10dip"
            android:id="@+id/userSwitch"
            android:layout_alignParentLeft="true"/>
    </RelativeLayout>
        <View
        android:id="@+id/titleBarSeparator"
        android:layout_width="fill_parent"
        android:layout_height="2dip"
        android:layout_alignParentLeft="true"
        android:background="#FFB4B4B4" />
    <ListView
        android:id="@android:id/list"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" >
    </ListView>
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="10dip">
        <Button
            android:enabled="false"
            android:layout_height="wrap_content"
            android:layout_width="100dip"
            android:layout_marginLeft="10dip"
            android:layout_marginTop="10dip"
            android:id="@+id/footerAdd"
            android:layout_alignParentLeft="true"
            android:text="Add" />
        <Button
            android:enabled="false"
            android:layout_height="wrap_content"
            android:layout_width="100dip"
            android:layout_marginLeft="10dip"
            android:layout_marginTop="10dip"
            android:id="@+id/footerSync"
            android:layout_toRightOf="@+id/footerAdd"
            android:text="Sync" />
    </RelativeLayout>
</LinearLayout>

To keep clean in our code we will create an interface to define operations supported by our main screen. First of all we have to have possibility to refresh entities list, there shoud be also posibility to disable and enable all buttons, and to get or set currenty logged in user.

MainScreen.java
public interface MainScreen {
	
	    void disableButtons();
	     
	    void enableButtons();
	     
	    void refreshList();
	     
	    String getCurrentUser();
	     
	    void setCurrentUser(String user);
}

When interface is ready let's implement it on PermissionsActivity. In constructor we will get all created controls in layout definition and store it in class private fields. 

PermissionsActivity.java
public class PermissionsActivity extends Activity implements MainScreen {
    /** Called when the activity is first created. */
	
	private ListView mList;
    
	   private TextView mCurrentUser;
	    
	   private Button mAddButton, mSyncButton;
	   
	   private ImageButton mSwitchUserButton;
	    
	   private String currenUser;
	   
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        mAddButton = (Button) findViewById(R.id.footerAdd);
        mSyncButton = (Button) findViewById(R.id.footerSync);
        mSwitchUserButton = (ImageButton) findViewById(R.id.userSwitch);
        mCurrentUser = (TextView) findViewById(R.id.currentUser);
        mList = (ListView) findViewById(android.R.id.list);
        
        // TODO: Add on click listeners
    }
	public void disableButtons() {
		mAddButton.setEnabled(false);
        mSyncButton.setEnabled(false);
        mSwitchUserButton.setEnabled(false);
	}
	public void enableButtons() {
		mAddButton.setEnabled(true);
        mSyncButton.setEnabled(true);
        mSwitchUserButton.setEnabled(true);
		
	}
	public void refreshList() {
		// TODO Refres entities list
		
	}
	public String getCurrentUser() {
        return currenUser;
	}
	public void setCurrentUser(String user) {
        currenUser = user;
        if(user != null){
        	if(currenUser.equals("a")){
        		mSwitchUserButton.setImageResource(R.drawable.bt_user_a_big);
        	}
        	else if(currenUser.equals("b")){
        		mSwitchUserButton.setImageResource(R.drawable.bt_user_b_big);
        	}
        }
	}
}

Switch beetwen users

Before we implement refreshing entities list we have to create switching user things. We will create separated class for that called "SwichUserOperations", this class will implement OnClickListener interface, so object of this class can be set as onClickListener in 'Switch' button. This class will also implement MobeelizerOperationCallback interface and we will use it as a login method callback. 

SwitchUserOperations.java
public class SwitchUserOperations implements OnClickListener , MobeelizerOperationCallback{
    
   private static final String USER_A_LOGIN = "a";
    
   private static final String USER_B_LOGIN = "b";
    
   private static final String USER_A_PASS = "usera";
    
   private static final String USER_B_PASS = "userb";
   private String userToLoggIn;
   private String password;
    
   private MainScreen page;
    
   public SwitchUserOperations(MainScreen page){
       this.page= page;
   }
    
   public void onClick(View v) {
       page.disableButtons();
       if(page.getCurrentUser() == USER_A_LOGIN){
           userToLoggIn = USER_B_LOGIN;
           password = USER_B_PASS;
       }
       else {
           userToLoggIn = USER_A_LOGIN;
           password = USER_A_PASS; 
       }
       Mobeelizer.login(userToLoggIn, password, this);
   }
   public void onFailure(MobeelizerOperationError arg0) {
       page.setCurrentUser(null);
       page.refreshList();
       page.enableButtons();
   }
   public void onSuccess() {
       page.setCurrentUser(userToLoggIn);
       page.refreshList();
       page.enableButtons();
   }
}

It is easy, right? When user click on switch button, we will check which user was logged in recently and then we will login other one. We have to also disable all buttons before login. When login will finish with success we will set current user value in FilePage and then enable all buttons. 

Last thing to do in switching users is setting object of just created class to button as a onclick listener.

PermissionsActivity.java
	@Override
    public void onCreate(Bundle savedInstanceState) {
        ...
        SwitchUserOperations switchOperations = new SwitchUserOperations(this);
        mSwitchUserButton.setOnClickListener(switchOperations);
        switchOperations.onClick(null);
		...
    }

Get current user entities

Ok we can switch between users now and it is time to create refreshing entity list code. To show our entities on list we have to create addapter for that, and list item layout template.

Add  list_item.xml file to layout folder, add implement it like this:

list_item.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="50dp"
    android:minHeight="50dp"
    android:orientation="vertical" >
    <TextView
        android:id="@+id/listItemTitle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="5dip"/>
    <TextView
        android:id="@+id/listItemDirector"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="25dip"
        android:layout_marginLeft="20dip"/>
    <ImageView
        android:id="@+id/listItemUser"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_centerVertical="true"
        android:layout_marginRight="10dp"/>
</RelativeLayout>

When template is ready it is time to create adapter. Create new class ListAdapter which extends ArrayAdapter<FileSyncEntity> and override getView method. 

ListAdapter.java
public class ListAdapter extends ArrayAdapter<PermissionsEntity> {
	private int resourceId = 0;
	
    private LayoutInflater inflater;
    
    public ListAdapter(Context context, int resource,
            List<PermissionsEntity> objects) {
        super(context, 0, objects);
        this.resourceId = resource;
        this.inflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }
    
    public static class ViewHolder {
        public ImageView author;
        public TextView title;
        public TextView director;
    }
    
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View view = convertView;
        ViewHolder holder;
        if (view == null) {
            view = inflater.inflate(resourceId, parent, false);
            holder = new ViewHolder();
            holder.author = (ImageView) view.findViewById(R.id.listItemUser);
            holder.title = (TextView) view.findViewById(R.id.listItemTitle);
            holder.director = (TextView) view.findViewById(R.id.listItemDirector);
            view.setTag(holder);
        } else {
            holder = (ViewHolder) view.getTag();
        }
        PermissionsEntity item = (PermissionsEntity) getItem(position);
        // Add owner name to author label
        if(item.getOwner().equals("a")){
            holder.author.setImageResource(R.drawable.bt_user_a_small);	
        }
        else if(item.getOwner().equals("b")){
        	holder.author.setImageResource(R.drawable.bt_user_b_small);
        }
        // Add created bitmap to ImageView
        holder.title.setText(item.getTitle());
        holder.director.setText((item.getDirector() == null)? "***********" : item.getDirector());
        return view;
    }    
}

This code is pretty simple. In constructor we are getting resource of item template definition and list of items. In overridden method we have to convert our PermissionsEntity class object to View object. We are getting TextViews and ImageView controls for title, director and owner fields from template and then fill them content with specified values. On the end of this method we are returning View object. 

When adapter is ready it is time to come back to refreshList method in PermissiosActivity class.

PermissionsActivity.java
...
	public void refreshList() {
		List<PermissionsEntity> entities = Mobeelizer.getDatabase().list(PermissionsEntity.class);
        ListAdapter adapter = new ListAdapter(this, R.layout.list_item, entities);
        mList.setAdapter(adapter);
	}
...

We are getting list of all entities from database, creating new adapter and then setting created object into list control.

Add entity into database

It is time now to implement adding new entities to database. As in switch user code we will also creates seperated class for that which will implement OnClickListener. We will get movie titiles from predefined xml file. We already added it into project resources at the beging of this example. Create new class AddOperations.

AddOperation.java
public class AddOperation implements OnClickListener {
	
	private MainScreen mView;
	
	String[] mTitles;
	String[] mDirectors;
	
    private static Random mRand;
    
    static {
        mRand = new Random(System.nanoTime());
    }
    public AddOperation(MainScreen view, Resources res){
        this.mView = view;
        mTitles = res.getStringArray(R.array.movieTitles);
        mDirectors = res.getStringArray(R.array.movieDirectors);
    }
    
	public void onClick(View arg0) {
		PermissionsEntity entity = new PermissionsEntity();
		int index = mRand.nextInt(mTitles.length);
		entity.setTitle(mTitles[index]);
		entity.setDirector(mDirectors[index]);
		Mobeelizer.getDatabase().save(entity);
		this.mView.refreshList();
	}
}

In constructor we are loading lista of movie titles and directories from resources and creating object to generate random numbers. When user click on button we will create new object set it values and save into database, on the end we will refresh entities list displayed on main screen.

Remember to set object of this class as add button onclick listener. 

PermissionsActivity.java
    @Override
    public void onCreate(Bundle savedInstanceState) {
		...
        mAddButton.setOnClickListener(new AddOperation(this, this.getResources()));
    }

Synchronize with mobeelizer

Greate, our example is almost ready, last thing to do is synchronization, but not be afraid it will be as easy as other operations. We will create new class for that again, and we will implements OnClickListener and MobeelizerOperationCallback interfaces in it.

SyncOperations.java
public class SyncOperations implements OnClickListener , MobeelizerOperationCallback {
     
    private FilePage view;
    public SyncOperations(FilePage view){
        this.view = view;
    }
    public void onFailure(MobeelizerOperationError arg0) {
        view.refreshList();
        view.enableButtons();
    }
    public void onSuccess() {
        view.refreshList();
        view.enableButtons();
    }
    public void onClick(View arg0) {
        view.disableButtons();
        if(Mobeelizer.isLoggedIn()){
            Mobeelizer.sync(this);
        }
    }
}

It is actually just calling Mobeelizer sync method. When synchronization finished without any errors given entities list is refreshed, and that is all.

And remember to add created operation classes as buttons onClick listeners.

PermissionsActivity.java
    @Override
    public void onCreate(Bundle savedInstanceState) {
        ...
        mSyncButton.setOnClickListener(new SyncOperations(this));
    }

Congratulations our example is completed. You can test it now on as many devices as you can find.

Conclusion

To conclude, this example presents permissions settings. We can observe that with Mobeelizer permissions settings, we can easily control visibility and data access. 

Attachments: