Monday, 26 December 2016

Android: Creating a Custom Navigation Drawer

The navigation drawer is a panel that displays the app’s main navigation options on the left edge of the screen. It is hidden most of the time, but is revealed when the user swipes a finger from the left edge of the screen or, while at the top level of the app, the user touches the app icon in the action bar.
This post describes how to implement a Navigation Drawer using DrawerLayout a few simple steps.

1. Create a Drawer Layout:
    Create a file under res/layout/ folder named as activity_home.xml:

 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/top_parent"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">

    <include
        android:id="@+id/toolbar"
        layout="@layout/layout_toolbar" />

    <android.support.v4.widget.DrawerLayout
        android:id="@+id/drawer_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@+id/toolbar">

        <!-- The main content view -->
        <FrameLayout
            android:id="@+id/content_frame"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

        </FrameLayout>

        <!-- The navigation drawer -->
        <ListView
            android:id="@+id/left_drawer"
            android:layout_width="240dp"
            android:layout_height="match_parent"
            android:layout_gravity="start"
            android:background="@color/colorPrimaryDark"
            android:choiceMode="singleChoice"
            android:divider="@android:color/white"
            android:dividerHeight="0.5dp" />

    </android.support.v4.widget.DrawerLayout>
</RelativeLayout>

2. Create a Toolbar layout for your app's actionbar:
    Create a file under res/layout/ folder named as layout_toolbar.xml to show the home button animation as suggested in Material design:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/toolbar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="?attr/colorPrimaryDark">

    <TextView
        android:id="@+id/toolbar_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Title"
        android:textAlignment="center"
        android:textAppearance="@android:style/TextAppearance.Material.Widget.Toolbar.Title"
        android:textColor="@android:color/white" />
</android.support.v7.widget.Toolbar>

3. Initialize your drawer list:
    Create a class named as HomeActivity.java and use the following code snippet:

public class HomeActivity extends AppCompatActivity {
    private DrawerLayout mDrawerLayout;
    private ListView mDrawerList;
    private ActionBarDrawerToggle mDrawerToggle;
    ArrayList<NavigationDrawerItemPOJO> pojoArrayList;
    Toolbar toolbar;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_home);
     
        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        mDrawerList = (ListView) findViewById(R.id.left_drawer);

        pojoArrayList = new ArrayList<>();
        NavigationDrawerItemPOJO nav = new NavigationDrawerItemPOJO();
        nav.setIcon(R.mipmap.ic_launcher);
        nav.setName("Name 1");
        pojoArrayList.add(nav);
       
        mDrawerList.setAdapter(new NavigationDrawerAdapter(this, R.layout.item_navigation_drawer, pojoArrayList));

        // Set the list's click listener
        mDrawerList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
                Toast.makeText(getApplicationContext(), "Item clicked: " + position, Toast.LENGTH_SHORT).show();
                mDrawerLayout.closeDrawer(mDrawerList);
            }
        });
       .. .. ..
    }
}


4. Setup your drawer layout:

public class HomeActivity extends AppCompatActivity {
    private DrawerLayout mDrawerLayout;
    private ListView mDrawerList;
    private ActionBarDrawerToggle mDrawerToggle;
    ArrayList<NavigationDrawerItemPOJO> pojoArrayList;
    Toolbar toolbar;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_home);
        initToolbar();

.........

        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, toolbar, R.string.drawer_open, R.string.drawer_close) {

            /** Called when a drawer has settled in a completely closed state. */
            public void onDrawerClosed(View view) {
                super.onDrawerClosed(view);
                invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
                syncState();
            }

            /** Called when a drawer has settled in a completely open state. */
            public void onDrawerOpened(View drawerView) {
                super.onDrawerOpened(drawerView);
                invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
                syncState();
            }
        };

        // Set the drawer toggle as the DrawerListener
        mDrawerLayout.addDrawerListener(mDrawerToggle);
        mDrawerToggle.syncState();
    }

    //Set the custom toolbar
    public void initToolbar() {
        toolbar = (Toolbar) findViewById(R.id.toolbar);
        if (toolbar != null) {
            setSupportActionBar(toolbar);
        }
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        getSupportActionBar().setHomeButtonEnabled(true);
        getSupportActionBar().setDisplayShowTitleEnabled(false);
        TextView txtvw = (TextView) findViewById(R.id.toolbar_title);
        txtvw.setText("Nishant");
    }
.....
}

5. Create your drawer adapter and drawer item POJO:

public class NavigationDrawerAdapter extends ArrayAdapter<NavigationDrawerItemPOJO> {
        private final Context context;
        private final int layoutResourceId;
        private ArrayList<NavigationDrawerItemPOJO> arrayList;

        public NavigationDrawerAdapter(Context context, int layoutResourceId,
                                                     ArrayList<NavigationDrawerItemPOJO> arrayList) {
            super(context, layoutResourceId, arrayList);
            this.context = context;
            this.layoutResourceId = layoutResourceId;
            this.arrayList = arrayList;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            LayoutInflater inflater = ((Activity) context).getLayoutInflater();
            View v = inflater.inflate(layoutResourceId, parent, false);
            ImageView imageView = (ImageView) v.findViewById(R.id.navDrawerImageView);
            TextView textView = (TextView) v.findViewById(R.id.navDrawerTextView);
            NavigationDrawerItemPOJO choice = arrayList.get(position);
            imageView.setImageResource(choice.getIcon());
            textView.setText(choice.getName());
            return v;
        }
    }

    public class NavigationDrawerItemPOJO {
        public int getIcon() {
            return icon;
        }

        public void setIcon(int icon) {
            this.icon = icon;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public int icon;
        public String name;

        public NavigationDrawerItemPOJO() {
        }
   }

That's all..!!
After this your home activity will look something like this:

HomeActivity.java
 
public class HomeActivity extends AppCompatActivity {
    private DrawerLayout mDrawerLayout;
    private ListView mDrawerList;
    private ActionBarDrawerToggle mDrawerToggle;
    ArrayList<NavigationDrawerItemPOJO> pojoArrayList;
    Toolbar toolbar;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_home);
        initToolbar();
        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        mDrawerList = (ListView) findViewById(R.id.left_drawer);

        pojoArrayList = new ArrayList<>();
        NavigationDrawerItemPOJO nav = new NavigationDrawerItemPOJO();
        nav.setIcon(R.mipmap.ic_launcher);
        nav.setName("Name 1");
        pojoArrayList.add(nav);
        NavigationDrawerItemPOJO nav1 = new NavigationDrawerItemPOJO();
        nav1.setIcon(R.mipmap.ic_launcher);
        nav1.setName("Name 2");
        pojoArrayList.add(nav1);
        mDrawerList.setAdapter(new NavigationDrawerAdapter(this, R.layout.item_navigation_drawer, pojoArrayList));

        // Set the list's click listener
        mDrawerList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
                Toast.makeText(getApplicationContext(), "Item clicked: " + position, Toast.LENGTH_SHORT).show();
                mDrawerLayout.closeDrawer(mDrawerList);
            }
        });

        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, toolbar, R.string.drawer_open, R.string.drawer_close) {

            /** Called when a drawer has settled in a completely closed state. */
            public void onDrawerClosed(View view) {
                super.onDrawerClosed(view);
                invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
                syncState();
            }

            /** Called when a drawer has settled in a completely open state. */
            public void onDrawerOpened(View drawerView) {
                super.onDrawerOpened(drawerView);
                invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
                syncState();
            }
        };

        // Set the drawer toggle as the DrawerListener
        mDrawerLayout.addDrawerListener(mDrawerToggle);
        mDrawerToggle.syncState();
    }

    //Set the custom toolbar
    public void initToolbar() {
        toolbar = (Toolbar) findViewById(R.id.toolbar);
        if (toolbar != null) {
            setSupportActionBar(toolbar);
        }
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        getSupportActionBar().setHomeButtonEnabled(true);
        getSupportActionBar().setDisplayShowTitleEnabled(false);
        TextView txtvw = (TextView) findViewById(R.id.toolbar_title);
        txtvw.setText("Nishant");
    }

    public class NavigationDrawerAdapter extends ArrayAdapter<NavigationDrawerItemPOJO> {
        private final Context context;
        private final int layoutResourceId;
        private ArrayList<NavigationDrawerItemPOJO> arrayList;

        public NavigationDrawerAdapter(Context context, int layoutResourceId, ArrayList<NavigationDrawerItemPOJO> arrayList) {
            super(context, layoutResourceId, arrayList);
            this.context = context;
            this.layoutResourceId = layoutResourceId;
            this.arrayList = arrayList;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            LayoutInflater inflater = ((Activity) context).getLayoutInflater();
            View v = inflater.inflate(layoutResourceId, parent, false);
            ImageView imageView = (ImageView) v.findViewById(R.id.navDrawerImageView);
            TextView textView = (TextView) v.findViewById(R.id.navDrawerTextView);
            NavigationDrawerItemPOJO choice = arrayList.get(position);
            imageView.setImageResource(choice.getIcon());
            textView.setText(choice.getName());
            return v;
        }
    }

    public class NavigationDrawerItemPOJO {
        public int getIcon() {
            return icon;
        }

        public void setIcon(int icon) {
            this.icon = icon;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public int icon;
        public String name;

        public NavigationDrawerItemPOJO() {
        }
    }
}


Run it and enjoy your app with a drawer that has material design drawer animation.
In this post your drawer will slide below the actionBar, just to show the animation. You can have it over the actionBar as well.

Share, Comment and Reply if any issues.


Friday, 16 December 2016

Android: Implement "Press BACK again to exit"

You might have noticed a pattern in many android applications these days in which on pressing the back button to exit the application it gives you a message which says "Please press BACK again to exit" .
This post is regarding implementing this feature in your android app.
To implement this, you just need to do the following things:

1. In your activity in which you want to implement this feature, add a variable as follows:
                         
                                 private boolean isBackPressedOnce = false;  

2. Now add the following code in the onBackPressed() method of your activity as follows:

    @Override
    public void onBackPressed() {
            if (isBackPressedOnce) {
                super.onBackPressed();
                return; // exit the appliactaion
            }

            this.isBackPressedOnce = true;
            Toast.makeText(this, "Please press BACK again to exit", Toast.LENGTH_SHORT).show();

            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    isBackPressedOnce = false;
                    // Runnable to change the value of variable isBackPressedOnce to true after 2 
                    // seconds if you take more than 2 seconds of time in pressing the back button again.
                }
            }, 2000);

    }

That's all. Now on pressing the back button in your app it will show you the message "Please press BACK again to exit".

Share & comment if any issues.


Sunday, 11 December 2016

Android Animations: Expand & Collapse

In reference to my previous post here, this post is regarding some other styles of animation that you can use in your app to make it look more subtle.
As you know Animations in android can add subtle visual cues that notify users about what's going on in your app and improve their mental model of your app's interface. Animations are especially useful when the screen changes state, such as when content loads or new actions become available. Animations can also add a polished look to your app, which gives your app a higher quality feel.

So lets get started now: This tutorial shows you simple way to add Expand & Collapse style animation in your app in just a few steps.
The Expand animation is somewhat like unfolding a view step by step or you can say opening a view from 0 to 100 slowly.
So to add the expand animation in your app just add the following method in your code:

public static void expandAnimation(final View v) {
        v.measure(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.WRAP_CONTENT);
        final int targetHeight = v.getMeasuredHeight();
        // Older versions of android (pre API 21) cancel animations for views with a height of 0.
        v.getLayoutParams().height = 1;
        v.setVisibility(View.VISIBLE);
        Animation a = new Animation() {
            @Override
            protected void applyTransformation(float interpolatedTime, Transformation t) {
                v.getLayoutParams().height = interpolatedTime == 1
                        ? WindowManager.LayoutParams.WRAP_CONTENT
                        : (int) (targetHeight * interpolatedTime);
                v.requestLayout();
            }
            @Override
            public boolean willChangeBounds() {
                return true;
            }
        };
        // 1dp/ms
        a.setDuration(300);
        v.startAnimation(a);
    }
          

Now to set this animation on any view, just call this method and pass that view which you want to expand, as the parameter to this method as follows:

                    expandAnimation(findViewById(R.id.myview));       

Now after expanding the view you also need to close it or you can say you'll need to collapse it.
Don't worry, closing it is also as simple as expanding it.
Just add the following method in your code to collapse your view.    

public static void collapseAnimation(final View v) {
        final int initialHeight = v.getMeasuredHeight();
        Animation a = new Animation() {
            @Override
            protected void applyTransformation(float interpolatedTime, Transformation t) {
                if (interpolatedTime == 1) {
                    v.setVisibility(View.GONE);
                } else {
                    v.getLayoutParams().height = initialHeight - (int) (initialHeight * interpolatedTime);
                    v.requestLayout();
                }
            }
            @Override
            public boolean willChangeBounds() {
                return true;
            }
        };
        // 1dp/ms
        a.setDuration(300);
        v.startAnimation(a);
    }
        

Now to set this collapse animation on any view, just call this method as you called the method to expand it and pass that view which you want to collapse, as the parameter to this method as follows:

                       collapseAnimation(findViewById(R.id.myview));    

That's all. Use it and have fun.
Comment if any issues and share.



Sunday, 27 November 2016

Fix Error: Configuration with name 'default' not found in android-studio

While importing or cloning a code from any version control system you might sometimes get an error showing you as "Error: Configuration with name 'default' not found". This error generally occurs due to following reasons:
1. When a module doens't have the build.gradle file,
2. You're trying to use a project that doesn't have a "build.gradle" file.

Essentially the build.gradle file for each submodule needs to have the information on how to build itself and any custom gradle command definitions.
So, you need to make sure that each submodule in your project has its own build.gradle file.
The name 'default' happens because your project level build.gradle is trying to build a project that doesn't know how to build itself, thus it is given the name 'default.'

Fix 1:
- If you are cloning a project from a version control system, then make a new clone of your project:

                                       git clone <LINK_TO_YOUR_PROJECT>  

and then issue the git submodule command:

                                       git submodule update --init --recursive  
and after this check whether your external folders are being populated with required folders and files.

Fix 2:
- After importing your project, run the following to commands:
                                       git submodule init  
                                       git submodule update  

Fix 3:
Add you library projects in your app level build.gradle file as follows:

               compile fileTree(dir: 'libs', include: ['*.jar'])              
               compile 'com.android.support:appcompat-v7:21.0.3' 
               compile project(":libs:<Your project name>")      

For more information on gradle visit: http://tools.android.com/tech-docs/new-build-system/user-guide


Thanks and reply if any issues.


Sunday, 20 November 2016

Background Service: IntentService

A Service is a component which runs in the background, without direct interaction with the user. A service has no user interface as a result of which it is not bound to the lifecycle of an activity. Services are used for repetitive and potential long running operations, checking for new data, data processing, indexing content, etc.

The IntentService class provides a straightforward structure for running an operation on a single background thread. IntentService runs outside the application in a background process, so the process will run even if your application is closed.

- A few limitations of an IntentService:

- You cannot affect the user interface from this background service directly,
- Requests are handled on a single worker thread and processes just one request at a time,
- You cannot easily cancel an intent service once you start one.

- A service can take two states −
  
  Started - A service is started when an application component, such as an activity, starts it by calling startService(). Once started, a service can run in the background indefinitely, even if the component that started it is destroyed.

  Bound - A service is bound when an application component binds to it by calling bindService(). A bound service offers a client-server interface that allows components to interact with the service, send requests and get results.

Implementation:
1. Make a simple class that extends Service class to make it your background service class named as MyService.java

public class MyService extends Service {

   @Override
   public int onStartCommand(Intent intent, int flags, int startId) {
      // Let it continue running until it is stopped.
      Toast.makeText(this, "Service Started", Toast.LENGTH_LONG).show();
      return START_STICKY;
   }

   @Override
   public void onDestroy() {
      super.onDestroy();
      Toast.makeText(this, "Service Destroyed", Toast.LENGTH_LONG).show();
   }
}

2. Now in your MainActivity.java class add the following method to start and stop your service as follows:

public class MainActivity extends Activity {
   String msg = "Test Service : ";

   @Override
   public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
      Log.d(msg, "The onCreate() event called..!");
   }

   public void startService(View view) {
      startService(new Intent(getApplicationContext(), MyService.class));
   }

   // Method to stop the service
   public void stopService(View view) {
      stopService(new Intent(getApplicationContext(), MyService.class));
   }
}

3. Add the service tag in your AndroidManifest.xml file as follows:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
   package="com.nishant.backgroundservicesample">

   <application
      android:allowBackup="true"
      android:icon="@mipmap/ic_launcher"
      android:label="@string/app_name"
      android:supportsRtl="true"
      android:theme="@style/AppTheme">

      <activity android:name=".MainActivity">
         <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
         </intent-filter>
      </activity>

      <service android:name=".MyService" />

   </application>
</manifest>

That's all. Now run your project and test it.
You can add a timer in your service to prompt you at a certain interval, for example show a simple toast at every 5 minutes through your service. Try it.
Comment if you have any issues.




Sunday, 13 November 2016

Change your home screen wallpaper/background from your android app

The background the application that you use the most sometimes become your favorite. What if you have an option to set your homescreen's background right from your application with just a click?
Well this post will show you to change your android phone's home background from your android app. It means that you can change your phone's home screen wallpaper from your app.

1. To change the wallpaper of your home screen from your app, first you need to set a permission in your AndroidManifest.xml file as follows:

 <uses-permission android:name="android.permission.SET_WALLPAPER"/>

2. Now to set the image of your choice as the background of your home screen we have the WallpaperManager class which can be used as follows:

         WallpaperManager myWallpaperManager =                                                                                            WallpaperManager.getInstance(getApplicationContext());
            try {
                         myWallpaperManager.setResource(R.drawable.five);
                 } catch (IOException e) {
                         // TODO Auto-generated catch block
                          e.printStackTrace();
             }

3. You can use the above code in your app on the onClick() method of a button to change the background of your home screen as follows:

            Button buttonSetWallpaper = (Button)findViewById(R.id.btn);
            ImageView imagePreview = (ImageView)findViewById(R.id.imgVw);
            imagePreview.setImageResource(R.drawable.sample_img);

            buttonSetWallpaper.setOnClickListener(new Button.OnClickListener(){
            @Override
                  public void onClick(View arg0) {
                            WallpaperManager myWallpaperManager 
                              = WallpaperManager.getInstance(getApplicationContext());
                 try {
                            Bitmap icon = BitmapFactory.decodeResource(getResources(),
                            R.drawable.sample_img);
                      myWallpaperManager.setBitmap(icon);

                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                     e.printStackTrace();
                }

            }});

That's all.


Sunday, 6 November 2016

Pop-up Context Menu in Android

This tutorial is regarding the Pop-up context menu in android. With this tutorial will see how to create a simple pop-up menu.
Android Popup Menu displays the menu below the anchor text if space is available otherwise above the anchor text. It disappears if you click outside the popup menu. Anchor text is the text relative to which your pop-up is visible.
The android.widget.PopupMenu is the direct subclass of java.lang.Object class.

1. Create a file as follows activity_main.xml:
This file will be created automatically when your project is being created.

<RelativeLayout xmlns:androclass="http://schemas.android.com/apk/res/android"  
    xmlns:tools="http://schemas.android.com/tools"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent" 
    tools:context=".MainActivity" >  
  
    <Button  
        android:id="@+id/button1"  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"
        android:layout_margin="16dp"  
        android:text="Show Popup" />  
  
</RelativeLayout> 

2. Create another class named popup_menu.xml:
This file is to be created inside the res/menu directory.

<menu xmlns:androclass="http://schemas.android.com/apk/res/android" >  
  
    <item  
        android:id="@+id/one"  
        android:title="Item_One"/>  
      
    <item  
        android:id="@+id/two"  
        android:title="Item_Two"/>  
        
    <item  
        android:id="@+id/three"  
        android:title="Item_Three"/>  
          
</menu> 

3. Now in your activity class named MainActivity.java do the following:

public class MainActivity extends Activity {  

         Button button1;  
           
         @Override  
         protected void onCreate(Bundle savedInstanceState) {  
          super.onCreate(savedInstanceState);  
          setContentView(R.layout.activity_main);  
            
          button1 = (Button) findViewById(R.id.button1);  
          button1.setOnClickListener(new OnClickListener() {  
           
           @Override  
           public void onClick(View v) {  
            //Creating the instance of PopupMenu  
            PopupMenu popup = new PopupMenu(MainActivity.this, button1);  
            //Inflating the Popup using xml file  
            popup.getMenuInflater().inflate(R.menu.popup_menu, popup.getMenu());  
           
            //registering popup with OnMenuItemClickListener  
            popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {  
             public boolean onMenuItemClick(MenuItem item) {  
              Toast.makeText(MainActivity.this,"You Clicked : " + item.getTitle(),
Toast.LENGTH_SHORT).show();  
              return true;  
             }  
            });  
            popup.show();//showing popup menu  
           }  
          }); 
         }  
    }  

That's all. Your Pop-up menu is created.

Sunday, 23 October 2016

Parse Cloud : Background Jobs

Today's tutorial is regarding Parse. Parse is an Open source backend or Parse can be roughly described as a could for hosting the APIs that your mobile app needs to communicate with in order to function. It also helps you send push notifications to your app users in order to communicate with them or bring them back to your app. If you are building a small application that consists of user login and after logging in you have some small stuff to do that requires a small logic which is user as the main point in the application then Parse can be a good option for that as it provides you a facility for cloud code and jobs that are used to run background long running function without the callbacks from your code. Other alternatives for Parse are Back4App, Firebase, Digital Ocean. This tutorial is regarding Parse server hosting on Back4App.

Getting Started
Cloud Code is built into Parse Server. The default entry point for your Cloud Code is at ./cloud/main.js.

What is Cloud Code?
For complex apps, sometimes you just need a bit of logic that isn’t running on a mobile device. Cloud Code makes this possible.
Cloud Code is easy to use because it’s built on the same JavaScript SDK that powers thousands of apps. The only difference is that this code runs in your Parse Server rather than running on the user’s mobile device. When you update your Cloud Code, it becomes available to all mobile environments instantly. You don’t have to wait for a new release of your application. This lets you change app behavior on the fly and add new features faster.
Even if you’re only familiar with mobile development, Cloud Code is straightforward and easy to use and understand.

Cloud Jobs
Sometimes you want to execute long running functions, and you don’t want to wait for the response. Cloud Jobs are just meant for that.

Define a Job

Parse.Cloud.job("myCloudJob", function(request, status) {
  Parse.Cloud.httpRequest({
      url: 'http://nishantsh.blogspot.in/2016/10/parse-cloud-background-jobs.html'
      success: function(httpResponse) {
        response(httpResponse.text);
      },
      error: function(httpResponse) {
        response('Request failed with response code ' + httpResponse.status)
      }
    });
});
:-Note that calling status.success or status.error won’t prevent any further execution of the job.

Running a Job
Calling jobs is done via the REST API and is protected by the master key.
1.What you need to do is set the following:

url: https://api.parse.com/1/jobs/[name of your test job] (maybe you need to encode the space to a %20 but I would recommend do start without spaces)
2.method: POST

3.request header:

X-Parse-Application-Id: [your app id]
X-Parse-REST-API-Key: [your master key] //(find it here: goto your app => CoreSettings)
Content-Type: application/json

That's all. Run it.
You can pass some data alongside the call if you want to customize the job execution.

Scheduling a Job
You can schedule your jobs according to your requirements that is you can run them manually also or you can schedule them to run on their own at some intervals. You can schedule your jobs as follows:
Goto BackgroundJobs => Schedule a Job => fill in and click save. Then from Browser a Job you can run your job manually.

That's all.



Friday, 30 September 2016

App Engine backend with Firebase Cloud Messaging

Google Cloud Messaging (GCM) is a service that allows you to send push notifications from your server to your users, and also to receive messages from devices on the same connection. The GCM service handles all aspects of queueing of messages and delivery to the target Android application running on the target device. GCM is the same great product from Google but now under a new name: Firebase Cloud Messaging or FCM for short.
This tutorial guides you through how to implement an App engine with FCM.

1. Add Google Cloud Module:
Make a new project to generate a token which will be used for sending and receiving notifications from firebase. You can create a new project from my previous post to get your token or if you are having your own project then just implement the code to your project mentioned in this post to generate the token which will be used further.
To add the backend to your existing or new Android app, open Android Studio and navigate to "File => New Module" or right-click on your project and choose "New => Module".


 In the "New Module" dialog that appears, choose "Google Cloud Module":


Then choose "App Engine Backend with Google Cloud Messaging" from first drop-down list.


Enter the module/package names for your new backend, and choose the "client" module in the project which contains your Android app. You can enter the name of your choice for your new backend. The client module will be set up to call your newly generated backend. The module name which you've entered above (marked with red 1) will be used in your Android Studio project. The package name (marked with red 2) will be used for all classes imported from this template and (reversed) for Endpoints API namespaces. In turn, Endpoints API namespaces will be used to derive the name of the autogenerated Android client libraries. This ensures that the names of generated client libraries will match your package name.


2. Debug the backend locally:
As soon as the backend module is added to your project and Gradle sync finishes, a new run configuration with your backend's module name should be created. Rebuild your project (via "Build => Rebuild Project") and launch this run configuration. It will invoke appengineRun task in Gradle plug-in for App Engine, which in turn will start the local App Engine Java development server. Navigate to http://localhost:8080. You should see the following page:


3. Connect your app with your backend:
To test the application, you need a Google Cloud Messaging API key. Follow the instructions to create a google-services.json configuration file and API key. Open the <backend>/src/main/webapp/WEB-INF/appengine-web.xml file (it should have been opened by default when you generated the backend), and copy the generated API key into appengine-web.xml file, replacing

<property name="gcm.api.key" value="YOUR_KEY_HERE"/>

with

<property name="gcm.api.key" value="AIza..."/>

4. Register your device:
Before any messages can be sent from your backend to the devices, these devices need to be registered with your backend. When you added this backend module to your project, the required permissions, needed by Firebase Cloud Messaging have been added into the Android manifest of your app, and the required build dependencies have been added to your app's build.gradle file.
Furthermore, a RegistrationEndpoint Cloud Endpoints API has been automatically generated for you, so that you could start calling this endpoint from your Android app to register devices with your new backend. Set up your Google Cloud Messaging Client to obtain a registration token, register your android device with your new backend, and set up the listener services to show push notifications from the GCM backend.
To send your newly obtained GCM registration token to the server, use the following code snippet which you should invoke from the RegistrationIntentService you created while setting up the client:

 private void sendRegistrationToServer(String token) throws IOException {
        Registration.Builder builder = new Registration.Builder(AndroidHttp.newCompatibleTransport(),
                new AndroidJsonFactory(), null)
                // Need setRootUrl and setGoogleClientRequestInitializer only for local testing,
                // otherwise they can be skipped
                .setRootUrl("http://<YOUR_LOCAL_IP>:8080/_ah/api/")
                .setGoogleClientRequestInitializer(new GoogleClientRequestInitializer() {
                    @Override
                    public void initialize(AbstractGoogleClientRequest<?> abstractGoogleClientRequest)
                            throws IOException {
                        abstractGoogleClientRequest.setDisableGZipContent(true);
                    }
                });
        Registration regService = builder.build();
        regService.register(token).execute();
    }

5. Test it:
If you have added a RegistrationIntentService invocation to one of your Android app activities and set up the google-services.json configuration file containing your Google Developers Console project number, you are ready to test the device registration with your backend locally. Now launch your backend locally as described in point-2. and ensure that you can access it via http://localhost:8080. If you can access the backend locally, change the run configuration back to your Android app and run the Android emulator.
Testing on a physical device with a local development server requires minor changes to your configuration. You must make your development server accessible to the network by setting it to listen to external connections. You can do this by editing the build.gradle for the backend project and setting the httpAddress.

appengine {
  ....
  httpAddress = "0.0.0.0"
  ....
}

You must also change the endpoint root url to point to your computer's ip address when creating the endpoint(In your RegistrationIntentService).

Registration.Builder builder = new Registration.Builder(AndroidHttp.newCompatibleTransport(),
        new AndroidJsonFactory(), null)
        .setRootUrl("http://<YOUR_COMPUTER_ADDRESS>:8080/_ah/api/")
        ....

Now to see notification in your physical device make sure your backend is running locally as shown in point-2. and your app running in your physical device. Then from your backend enter a message and click Send Message>>, then you will be able to see a notification in your device as follows:
6. Deploy your backend:
If your backend is working fine locally, you can now deploy it to Google App Engine.
 - Stop the backend, if it is running locally, by selecting Run => Stop.
 - Run Build => Deploy Module to App Engine.
 - In the Deploy to App Engine dialog, select your module. From the Deploy To: dropdown list, choose your Google Console Project which you have create to get your api_key or if you have not created your one then choose "Click here to create a new Google Developers Console project." This will open Google Developers Console. If you are running this task for the first time, you will be prompted to sign-in with your Google Account. Choose an account and sign in.
 - Create a new project and switch back to the Deploy to App Engine dialog in Android Studio.
Now update your src/main/webapp/WEB-INF/appengine-web.xml file's <application> property and replace myApplicationId with the ID of the project that you just created. This will be important if you try to deploy from the command line.
 - Click the Refresh button in the bottom right corner of the Deploy To: dropdown list and then select the project you just created.
 - Click Deploy. You can monitor the status of your deployment in the Android Studio console.

7. Testing against your deployed backend:
Once you have deployed your backend to App Engine, you can connect your Android app to it by modifying the RegistrationIntentService class explained in point-4. above. and replace particular lines:

Registration.Builder builder = new Registration.Builder(AndroidHttp.newCompatibleTransport(),
        new AndroidJsonFactory(), null)
        // Need setRootUrl and setGoogleClientRequestInitializer only for local testing,
        // otherwise they can be skipped
        .setRootUrl("http://10.0.2.2:8080/_ah/api/")
        .setGoogleClientRequestInitializer(new GoogleClientRequestInitializer() {
            @Override
            public void initialize(AbstractGoogleClientRequest<?> abstractGoogleClientRequest)
                    throws IOException {
                abstractGoogleClientRequest.setDisableGZipContent(true);
            }
        });

with these lines

Registration.Builder builder = new Registration.Builder(AndroidHttp.newCompatibleTransport(),
        new AndroidJsonFactory(), null)
        .setRootUrl("https://android-app-backend.appspot.com/_ah/api/");

where android-app-backend corresponds to your own Project ID created above in 6.

8. At this point you should be all set to run your Android app in an emulator or on the physical device and send messages from your backend which you have created and deployed just now.
You can access your backend at https://android-app-backend.appspot.com , where android-app-backend corresponds to your own Project ID created above in 6 and successfully communicate with your new App Engine backend!!

That's all. Comment if any queries.

Thursday, 22 September 2016

Android transitions: Animations

Animations in android are a good way to make your application more user friendly and interactive. Animations are used to give the UI a rich look and feel. Animations in android apps can be performed through XML or android code. Animation is the process of creating motion and shape change. In this post we will take a look at different types of simple animations in android.
Create following XML files for animation in /anim folder under your res/ directory:

1. anim_fade_in.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:fillAfter="true" >

    <alpha
        android:duration="1000"
        android:fromAlpha="0.0"
        android:interpolator="@android:anim/accelerate_interpolator"
        android:toAlpha="1.0" />
</set>

2. anim_fade_out.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:fillAfter="true" >

    <alpha
        android:duration="1000"
        android:fromAlpha="1.0"
        android:interpolator="@android:anim/accelerate_interpolator"
        android:toAlpha="0.0" />
</set>

3. anim_slide_down.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:anim/overshoot_interpolator">

    <translate
        android:duration="1000"
        android:fromYDelta="-800%"
        android:toYDelta="0%" />
</set>

4. anim_slide_up.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">

    <translate
        android:duration="1000"
        android:fromYDelta="800%"
        android:toYDelta="0" />
</set>

5. anim_slide_out_to_right.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:shareInterpolator="false">
    <translate
        android:duration="400"
        android:fromXDelta="0%"
        android:fromYDelta="0%"
        android:toXDelta="100%"
        android:toYDelta="0%" />
</set>

6. anim_slide_out_to_left.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:shareInterpolator="false">
    <translate
        android:duration="300"
        android:fromXDelta="0%"
        android:toXDelta="-100%" />
</set>

7. anim_slide_in_from_right.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:shareInterpolator="false">
    <translate
        android:duration="400"
        android:fromXDelta="100%"
        android:fromYDelta="0%"
        android:toXDelta="0%"
        android:toYDelta="0%" />
</set>

8. anim_slide_in_from_left.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:shareInterpolator="false">
    <translate
        android:duration="300"
        android:fromXDelta="100%"
        android:toXDelta="0%" />
</set>

9. anim_blink.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <alpha android:fromAlpha="0.0"
        android:toAlpha="1.0"
        android:interpolator="@android:anim/accelerate_interpolator"
        android:duration="600"
        android:repeatMode="reverse"
        android:repeatCount="infinite"/>
</set>

10. anim_zoom_in.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:fillAfter="true" >

    <scale
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="1000"
        android:fromXScale="1"
        android:fromYScale="1"
        android:pivotX="50%"
        android:pivotY="50%"
        android:toXScale="3"
        android:toYScale="3" >
    </scale>
</set>

11. anim_zoom_out.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:fillAfter="true" >
    <scale
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="1000"
        android:fromXScale="1.0"
        android:fromYScale="1.0"
        android:pivotX="50%"
        android:pivotY="50%"
        android:toXScale="0.5"
        android:toYScale="0.5" >
    </scale>
</set>

12. anim_rotate.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <rotate android:fromDegrees="0"
        android:toDegrees="360"
        android:pivotX="50%"
        android:pivotY="50%"
        android:duration="600"
        android:repeatMode="restart"
        android:repeatCount="infinite"
        android:interpolator="@android:anim/cycle_interpolator"/>
</set>

Now to implement these animation in your app, just in your activity do the following:

      ImageView image = (ImageView)findViewById(R.id.imageView);
      Animation anim = AnimationUtils.loadAnimation(getApplicationContext(),                                         R.anim.your_anim_file);
      image.startAnimation(anim);

That's all. You can change the animation type you want and apply it to the view as shown above.