RSS

Category Archives: Android

Obfuscating Android Code with Proguard

By:

First enable minifyEnabled in your build.gradle file, like

minifyEnabled true

After this, add below lines in progurad-rules.txt file

-keep class yourpackage.** { *; }
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-verbose

For checking that its working fine go to:

http://www.javadecompilers.com/apktool website so that you can verify after decompilation.

It will work and your classes will be hidden completely.

Copyfrom: https://stackoverflow.com/questions/17290023/obfuscation-in-android-studio

http://medium/@rakawestu/obfuscating-android-code-with-proguard-d43234df9785

Advertisements
 
Leave a comment

Posted by on April 5, 2018 in Android, Mobile Development

 

Horizontal RecyclerView in Vertical RecyclerView like Google Play Store

By: 

Step: 1
======
Create two Model Classes like below.

SingleItemModel.java

1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
package com.pratap.gplaystore.models;

/**
 * Created by pratap.kesaboyina on 01-12-2015.
 */
public class SingleItemModel {


    private String name;
    private String url;
    private String description;


    public SingleItemModel() {
    }

    public SingleItemModel(String name, String url) {
        this.name = name;
        this.url = url;
    }


    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getName() {
        return name;
    }

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

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }


}

SectionDataModel.java

1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
package com.pratap.gplaystore.models;

import java.util.ArrayList;

/**
 * Created by pratap.kesaboyina on 30-11-2015.
 */
public class SectionDataModel {



    private String headerTitle;
    private ArrayList<SingleItemModel> allItemsInSection;


    public SectionDataModel() {

    }
    public SectionDataModel(String headerTitle, ArrayList<SingleItemModel> allItemsInSection) {
        this.headerTitle = headerTitle;
        this.allItemsInSection = allItemsInSection;
    }



    public String getHeaderTitle() {
        return headerTitle;
    }

    public void setHeaderTitle(String headerTitle) {
        this.headerTitle = headerTitle;
    }

    public ArrayList<SingleItemModel> getAllItemsInSection() {
        return allItemsInSection;
    }

    public void setAllItemsInSection(ArrayList<SingleItemModel> allItemsInSection) {
        this.allItemsInSection = allItemsInSection;
    }


}

Step: 2
======
Create an Activity with RecyclerView to show the list in vertical order.

MainActivity.java

 

1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
package com.pratap.gplaystore;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;

import com.pratap.gplaystore.adapters.RecyclerViewDataAdapter;
import com.pratap.gplaystore.models.SectionDataModel;
import com.pratap.gplaystore.models.SingleItemModel;

import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {

    private Toolbar toolbar;


    ArrayList<SectionDataModel> allSampleData;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        toolbar = (Toolbar) findViewById(R.id.toolbar);

        allSampleData = new ArrayList<SectionDataModel>();

        if (toolbar != null) {
            setSupportActionBar(toolbar);
            toolbar.setTitle("G PlayStore");

        }


        createDummyData();


        RecyclerView my_recycler_view = (RecyclerView) findViewById(R.id.my_recycler_view);

        my_recycler_view.setHasFixedSize(true);

        RecyclerViewDataAdapter adapter = new RecyclerViewDataAdapter(this, allSampleData);

        my_recycler_view.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));

        my_recycler_view.setAdapter(adapter);


    }

    public void createDummyData() {
        for (int i = 1; i <= 5; i++) {

            SectionDataModel dm = new SectionDataModel();

            dm.setHeaderTitle("Section " + i);

            ArrayList<SingleItemModel> singleItem = new ArrayList<SingleItemModel>();
            for (int j = 0; j <= 5; j++) {
                singleItem.add(new SingleItemModel("Item " + j, "URL " + j));
            }

            dm.setAllItemsInSection(singleItem);

            allSampleData.add(dm);

        }
    }
}

Create an XML Layout for the above activity class

activity_main.xml

1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        android:elevation="8dp"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
        app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />


    <android.support.v7.widget.RecyclerView
        android:id="@+id/my_recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scrollbars="none" />


</LinearLayout>

Step: 3
======
Now Create an Adapter Class for the recyclerView in the MainActivity.


RecyclerViewDataAdapter.java

 

1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
package com.pratap.gplaystore.adapters;

/**
 * Created by pratap.kesaboyina on 24-12-2014.
 */
import android.content.Context;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import com.pratap.gplaystore.R;
import com.pratap.gplaystore.models.SectionDataModel;

import java.util.ArrayList;

public class RecyclerViewDataAdapter extends RecyclerView.Adapter<RecyclerViewDataAdapter.ItemRowHolder> {

    private ArrayList<SectionDataModel> dataList;
    private Context mContext;

    public RecyclerViewDataAdapter(Context context, ArrayList<SectionDataModel> dataList) {
        this.dataList = dataList;
        this.mContext = context;
    }

    @Override
    public ItemRowHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
        View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.list_item, null);
        ItemRowHolder mh = new ItemRowHolder(v);
        return mh;
    }

    @Override
    public void onBindViewHolder(ItemRowHolder itemRowHolder, int i) {

        final String sectionName = dataList.get(i).getHeaderTitle();

        ArrayList singleSectionItems = dataList.get(i).getAllItemsInSection();

        itemRowHolder.itemTitle.setText(sectionName);

        SectionListDataAdapter itemListDataAdapter = new SectionListDataAdapter(mContext, singleSectionItems);

        itemRowHolder.recycler_view_list.setHasFixedSize(true);
        itemRowHolder.recycler_view_list.setLayoutManager(new LinearLayoutManager(mContext, LinearLayoutManager.HORIZONTAL, false));
        itemRowHolder.recycler_view_list.setAdapter(itemListDataAdapter);


        itemRowHolder.btnMore.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {


                Toast.makeText(v.getContext(), "click event on more, "+sectionName , Toast.LENGTH_SHORT).show();



            }
        });


       /* Glide.with(mContext)
                .load(feedItem.getImageURL())
                .diskCacheStrategy(DiskCacheStrategy.ALL)
                .centerCrop()
                .error(R.drawable.bg)
                .into(feedListRowHolder.thumbView);*/
    }

    @Override
    public int getItemCount() {
        return (null != dataList ? dataList.size() : 0);
    }

    public class ItemRowHolder extends RecyclerView.ViewHolder {

        protected TextView itemTitle;

        protected RecyclerView recycler_view_list;

        protected Button btnMore;



        public ItemRowHolder(View view) {
            super(view);

            this.itemTitle = (TextView) view.findViewById(R.id.itemTitle);
            this.recycler_view_list = (RecyclerView) view.findViewById(R.id.recycler_view_list);
            this.btnMore= (Button) view.findViewById(R.id.btnMore);


        }

    }

}

Now create an xml Layout file for the above adapter class.

list_item.xml

1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"

    android:background="?android:selectableItemBackground"
    android:orientation="vertical"
    android:padding="5dp">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="2dp">


        <TextView
            android:id="@+id/itemTitle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_alignParentStart="true"
            android:layout_centerVertical="true"
            android:layout_gravity="center_vertical"
            android:layout_toLeftOf="@+id/btnMore"
            android:text="Sample title"
            android:textColor="@android:color/black"
            android:textSize="18sp" />

        <Button
            android:id="@+id/btnMore"
            android:layout_width="wrap_content"
            android:layout_height="42dp"
            android:layout_alignParentEnd="true"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:theme="@style/MyButton"
            android:text="more"
            android:textColor="#FFF" />


    </RelativeLayout>

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recycler_view_list"
        android:layout_width="match_parent"
        android:layout_height="160dp"
        android:layout_gravity="center_vertical"
        android:orientation="horizontal" />


</LinearLayout>

Step: 4
======

Now , In order to make a horizontal RecyclerView , we need create a layout and Adapter class for each row.

list_single_card.xml

1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    app:cardCornerRadius="5dp"
    app:cardUseCompatPadding="true"
    >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="0dp"
        android:background="?android:selectableItemBackground"
        android:orientation="vertical">

        <ImageView
            android:id="@+id/itemImage"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:layout_gravity="center_horizontal"
            android:scaleType="fitCenter"
            android:src="@drawable/android" />


        <TextView
            android:id="@+id/tvTitle"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@id/itemImage"
            android:gravity="center"
            android:padding="5dp"
            android:text="Sample title"
            android:textColor="@android:color/black"
            android:textSize="18sp" />


    </LinearLayout>

</android.support.v7.widget.CardView>

 


The Adapter Class for Horizontal RecyclerView


SectionListDataAdapter.java

 

1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
package com.pratap.gplaystore.adapters;

/**
 * Created by pratap.kesaboyina on 24-12-2014.
 */

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import com.pratap.gplaystore.R;
import com.pratap.gplaystore.models.SingleItemModel;

import java.util.ArrayList;

public class SectionListDataAdapter extends RecyclerView.Adapter<SectionListDataAdapter.SingleItemRowHolder> {

    private ArrayList<SingleItemModel> itemsList;
    private Context mContext;

    public SectionListDataAdapter(Context context, ArrayList<SingleItemModel> itemsList) {
        this.itemsList = itemsList;
        this.mContext = context;
    }

    @Override
    public SingleItemRowHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
        View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.list_single_card, null);
        SingleItemRowHolder mh = new SingleItemRowHolder(v);
        return mh;
    }

    @Override
    public void onBindViewHolder(SingleItemRowHolder holder, int i) {

        SingleItemModel singleItem = itemsList.get(i);

        holder.tvTitle.setText(singleItem.getName());


       /* Glide.with(mContext)
                .load(feedItem.getImageURL())
                .diskCacheStrategy(DiskCacheStrategy.ALL)
                .centerCrop()
                .error(R.drawable.bg)
                .into(feedListRowHolder.thumbView);*/
    }

    @Override
    public int getItemCount() {
        return (null != itemsList ? itemsList.size() : 0);
    }

    public class SingleItemRowHolder extends RecyclerView.ViewHolder {

        protected TextView tvTitle;

        protected ImageView itemImage;


        public SingleItemRowHolder(View view) {
            super(view);

            this.tvTitle = (TextView) view.findViewById(R.id.tvTitle);
            this.itemImage = (ImageView) view.findViewById(R.id.itemImage);


            view.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {


                    Toast.makeText(v.getContext(), tvTitle.getText(), Toast.LENGTH_SHORT).show();

                }
            });


        }

    }

}

ScreenShots
=========

Source code
========
DropBox Link

Demo
========

Copy from: http://android-pratap.blogspot.com/2015/12/horizontal-recyclerview-in-vertical.html

 
Leave a comment

Posted by on February 8, 2018 in Android, Mobile Development

 

Android Push Notifications when app is closed

By: Charuක

 

Yes, it is possible ‘to receive notifications from google cloud message when the application is fully closed’.

Infact, A broadcast receiver is the mechanism GCM uses to deliver messages. You need to have implement a BroadcastReceiver and declare it in the AndroidManifest.xml.

Please refer to the following code snippet.

AndroidManifest.xml

<receiver
    android:name=".GcmBroadcastReceiver"
    android:permission="com.google.android.c2dm.permission.SEND" >
    <intent-filter>
        <!-- Receives the actual messages. -->
        <action android:name="com.google.android.c2dm.intent.RECEIVE" />
        <category android:name="com.google.android.gcm.demo.app" />
    </intent-filter>
</receiver>
<service android:name=".GcmIntentService" />

Java code

public class GcmBroadcastReceiver extends WakefulBroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        // Explicitly specify that GcmIntentService will handle the intent.
        ComponentName comp = new ComponentName(context.getPackageName(),
                GcmIntentService.class.getName());
        // Start the service, keeping the device awake while it is launching.
        startWakefulService(context, (intent.setComponent(comp)));
        setResultCode(Activity.RESULT_OK);
    }
}

When GCM delivers a message to your device, BroadcastReceiver will receive the message and call the onReceive() function, wherein you may start a service to actually perform the intended task for you.

The above Code example uses a specialized BroadcastReceiver called WakefulBroadcastReceiver, which makes sure that the device doesn’t go to sleep, while the service is doing its work.

Refer to the Official Android Page for the same: https://developer.android.com/google/gcm/client.html

 

 

 

Copy from: https://stackoverflow.com/questions/24313539/push-notifications-when-app-is-closed

 
Leave a comment

Posted by on September 15, 2017 in Android, Mobile Development

 

Adding Badge count on menu items like cart , notification etc

By: mobikul.com

In every application, we decorate our MenuItem placed on ActionBar. Displaying of badge count not only decorate the ActionBar beautifully but also displays useful information like showing the number of items currently available in your cart or update you with unread notification.

We can create badge count using either a custom view or by adding a distinct drawable to display the each state of MenuItem.

Both the options have its pros and cons.

There is another approach using LayerDrawable which is more flexible and efficient than the former approaches.

Here’s what we’re going to do:

  1. Create a LayerDrawable to display MenuItem with a badge.
  2. Create a custom drawable let us called BadgeDrawable.
  3. Set badge on the menu item from our Activity.

LayerDrawable

A Drawable that manages an array of other Drawables. These are drawn in array order, so the element with the largest index will be drawn on top.It can be defined in an XML file with the

It can be defined in an XML file with the <layer-list> element. Each Drawable in the layer is defined in a nested<item>

i. Creating a layer drawable to display menu item on layer one and badge on top of it.

ic_menu_cart.xml

ii. Creating menu for our activity to display the count on the menu items.

main.xml

iii. Creating a flexible and efficient custom BagdeDrawable class to draw a view that looks like a count

BagdeDrawable.java

 

Setting up altogether

We can get the icon of the menu using getIcon() method.

Here is our method setBadgeCount(). We can pass LayerDrawable which we get from meniItem and setBadge from anywhere from the application.

Sample source code

 

Copy from: https://mobikul.com/adding-badge-count-on-menu-items-like-cart-notification-etc/

 

 

 
Leave a comment

Posted by on June 7, 2017 in Android, Mobile Development

 

Get started with RabbitMQ on Android (Android Studio)

By: LOVISA JOHANSSON (cloudamqp)

This guide explains how to create a simple chat application in Android using Android Studio and RabbitMQ. Everyone that has the application will be able to send and receive messages from all other users that are using the same application.

If you are using Eclipse, check out this blog post instead.

In the code given, messages will first be added to an internal queue and the publisher will send messages from the internal queue to RabbitMQ when there is a connection established. The message will be added back to the queue if the connection is broken.

RabbitMQ Android

This guide assumes that you have downloaded, installed and set up everything correct for Android Studio.

Start by creating a new Android project, open Android Studio and go to File -> New -> New Project..

1. Configure your new project

  1. Enter project information as specified below.create new android project
  2. Select the form factor your app will run onandroid studio
  3. Select if you like to add an activity to your app or not. In this example we choose Blank Activity to get autogenerated files for the project.add android activity
  4. Customize the Activitycustomize android activity

2. Add Java AMQP library to project

RabbitMQ has developed an excellent Java AMQP library. The full API documentation for the library can be found here.

We need to include the RabbitMQ Java Client Library and reference the jar files into the project. In Android Studio you can create a libs folder in the same level as the app. Copy and past the jars in to this libs folder. Mark all the jar files and press “Add As Library…” as seen in the image below.

add rabbitmq library

You can confirm that the libs has been added as library by opening build.gradle and check under dependencies, all files should seen be there.

dependencies {
  ...
  compile files('libs/rabbitmq-client.jar')
  ...
}

NOTE: Only if you are using Android Gradle plugin 0.7.0 and do get the error “Duplicate files copied in APK” when you later run your application, you need to add packagingOptions to your build.gradle file as specified in here.

android {
  packagingOptions {
    exclude 'META-INF/LICENSE.txt'
    exclude 'META-INF/NOTICE.txt'
  }
}

3. Android Manifest, internet permission

We need to tell the Android system that this app is allowed to access internet. Open the AndroidManifest.xml file, located in the root of the project. Add the user permission android.permission.INTERNET just before the closing /manifest tag.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.cloudamqp.rabbitmq"
     android:versionCode="1"
     android:versionName="1.0">
     ......
     <uses-permission android:name="android.permission.INTERNET"></uses-permission>
</manifest>

4. Start coding

Layout

Create the view for the application. The .xml layout file can be found under res->layout. What we have here is a root ScrollView containing a

EditText a Button and a TextView The EditText will be used as an input field for the text that will be sent. The text will be published when the button is pressed and all messages received by the subscriber will be printed to the TextView.

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
  ...
  <EditText
  android:id="@+id/text"
  android:layout_width="fill_parent"
  android:background="#ffffff"
  android:hint="Enter a message" />

  <Button
  android:id="@+id/publish"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:layout_below="@+id/text"
  android:text="Publish message" />

  <TextView
  android:id="@+id/textView"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:layout_below="@+id/publish"
  android:textColor="#000000" />
  ...
</ScrollView>

Publish

Create an internal message queue. In this case is a BlockingDeque used. Blockingqueues implementations are designed to be used primarily for producer-consumer queues.

private BlockingDeque<String> queue = new LinkedBlockingDeque>String>();
void publishMessage(String message) {
  try {
    Log.d("","[q] " + message);
    queue.putLast(message);
  } catch (InterruptedException e) {
    e.printStackTrace();
  }
}

Create a setup function for the ConnectionFactory The connection factory encapsulates a set of connection configuration parameters, in this case the CLOUDAMQP_URL. The URL can be found in the control panel for your instance.

ConnectionFactory factory = new ConnectionFactory();
private void setupConnectionFactory() {
  String uri = "IP";
  try {
    factory.setAutomaticRecoveryEnabled(false);
    //factory.setUri(uri);
    factory.setHost(uri);

  } catch (KeyManagementException | NoSuchAlgorithmException | URISyntaxException e1) {
    e1.printStackTrace();
}

Create a publisher that publish messages from the internal queue. Messages are added back to the queue if an exception is catched. The publisher will try to reconnect every 5 seconds if the connection is broken.

A thread (“background” or “worker” threads or use of the AsyncTask class) is needed when we have operations to perform that are not instantaneous, such as network access when connecting to rabbitMQ.

We will use a fanout exchange. A fanout exchange routes messages to all of the queues that are bound to it and the routing key is ignored. If N queues are bound to a fanout exchange, will a new message that is published to that exchange, be copied and delivered to all N queues. Fanout exchanges are ideal for the broadcast routing of messages.

public void publishToAMQP()
{
  publishThread = new Thread(new Runnable() {
    @Override
    public void run() {
      while(true) {
        try {
          Connection connection = factory.newConnection();
          Channel ch = connection.createChannel();
          ch.confirmSelect();

          while (true) {
            String message = queue.takeFirst();
            try{
              ch.basicPublish("amq.fanout", "chat", null, message.getBytes());
              Log.d("", "[s] " + message);
              ch.waitForConfirmsOrDie();
            } catch (Exception e){
              Log.d("","[f] " + message);
              queue.putFirst(message);
              throw e;
           }
         }
       } catch (InterruptedException e) {
         break;
       } catch (Exception e) {
         Log.d("", "Connection broken: " + e.getClass().getName());
         try {
           Thread.sleep(5000); //sleep and then try again
         } catch (InterruptedException e1) {
           break;
         }
       }
     }
   }
  });
  publishThread.start();
}

Subscriber

We have now created the publisher, and it is time to create the subscriber. The subscriber will take a handler as parameter. The handler will print the messages to the screen when the messages arrives. The subscribe thread will try to reconnect every 5 seconds when the connection gets broken.

void subscribe(final Handler handler)
{
  subscribeThread = new Thread(new Runnable() {
    @Override
    public void run() {
      while(true) {
        try {
          Connection connection = factory.newConnection();
          Channel channel = connection.createChannel();
          channel.basicQos(1);
          DeclareOk q = channel.queueDeclare();
          channel.queueBind(q.getQueue(), "amq.fanout", "chat");
          QueueingConsumer consumer = new QueueingConsumer(channel);
          channel.basicConsume(q.getQueue(), true, consumer);

          while (true) {
            QueueingConsumer.Delivery delivery = consumer.nextDelivery();
            String message = new String(delivery.getBody());
            Log.d("","[r] " + message);
            Message msg = handler.obtainMessage();
            Bundle bundle = new Bundle();
            bundle.putString("msg", message);
            msg.setData(bundle);
            handler.sendMessage(msg);
          }
        } catch (InterruptedException e) {
          break;
        } catch (Exception e1) {
          Log.d("", "Connection broken: " + e1.getClass().getName());
          try {
            Thread.sleep(5000); //sleep and then try again
          } catch (InterruptedException e) {
            break;
          }
        }
      }
    }
  });
  subscribeThread.start();
}

Call all functions listed above from function onCreate The handler used by the subscribe functions is also created in onCreate. A handler has to be used because it is only possible to write to the GUI from the main tread.

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

  setupConnectionFactory();
  publishToAMQP();
  setupPubButton();

  final Handler incomingMessageHandler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
      String message = msg.getData().getString("msg");
      TextView tv = (TextView) findViewById(R.id.textView);
      Date now = new Date();
      SimpleDateFormat ft = new SimpleDateFormat ("hh:mm:ss");
      tv.append(ft.format(now) + ' ' + message + '\n');
    }
  };
  subscribe(incomingMessageHandler);
}

void setupPubButton() {
  Button button = (Button) findViewById(R.id.publish);
  button.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View arg0) {
      EditText et = (EditText) findViewById(R.id.text);
      publishMessage(et.getText().toString());
      et.setText("");
   }
  });
}

The subscribe and the publish tread can both be interrupted when the application is destroyed by adding following code in onDestroy

Thread subscribeThread;
Thread publishThread;
@Override
protected void onDestroy() {
  super.onDestroy();
  publishThread.interrupt();
  subscribeThread.interrupt();
}

 

Copy from: https://www.cloudamqp.com/blog/2015-07-29-rabbitmq-on-android.html

 

Android support multidex library implementation

By: Nicolas Tyler

There are a few things you have to do,

1- In your gradle you need to specify multidex and add the support library:

android {
    defaultConfig {
        ...
        multiDexEnabled true
        ...
    }
}

dependencies {
  ...
  compile 'com.android.support:multidex:1.0.0'
  ...
}

2- In your manifest you have to set your application to a multidex application:

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

3.1- In your application class you have to either extend MultiDexApplication:

public class my_application extends MultiDexApplication
{
    ...
}

3.2- Or Overide the attachBaseContext() method:

public class my_application extends Application
{
    protected void attachBaseContext(Context base)
    {
        super.attachBaseContext(base);
        MultiDex.install(this);
    }
}

Copy from: http://stackoverflow.com/questions/26925264/android-support-multidex-library-implementation

 
Leave a comment

Posted by on August 25, 2015 in Android, Mobile Development

 

Integrated aSmack (Openfire) with Android

By: http://developer.samsung.com/

Introduction

Instant messaging (IM) communication is done through the use Extensible Messaging and Presence Protocol (XMPP) (also known as Jabber), an open standard XML based messaging communication protocol.

Most IM Clients use the XMPP protocol for communication. Google is one of the clients that use XMPP for its Google Talk Product.

There are various third party libraries available for developing Instant Messaging client applications. One of the most popular XMPP client libraries is Smack API, which is a pure Java Library which allows developers to create IM Clients. Following is a walkthrough of building a simple chat application using the Smack API.

Before starting to develop and explore some of the features of Smack API, developers are requested to go through the technical documentation and API documentation of Smack API (3.2.2 latest version at this time of development of this article)

SmackAPI

The Smack API is a pure Java Library. The asmack third party library has heavily patched the Smack API to work with Android. For more information, visit the Smack API community thread.

Libraries are available under the following section:

Download the asmack library jar file with naming convention asmack-<date>.jar, where <date> is the date of release. Add it to your project lib folder.

The sample chat application does the following:

  • Connects to a GTalk Server
  • Logs into GTalk Server
  • Sets user Presence
  • Gets Rosters
  • Sends Messages
  • Receives Messages

 

Connecting to a Server

In this document, Google Talk Server is used for the development of sample chat app.

Connecting to XMPP server requires knowing of configuration parameters set by XMPP Server.

Following are the required configuration parameters for connecting to GTalk Server:

public static final String HOST = "talk.google.com";
public static final int PORT = 5222;
public static final String SERVICE = "gmail.com";

[Code 1]

For more information on configuration parameters, visit GTalk Developers site.

Following code snippet shows how to use the Smack API for connecting to XMPP Server

ConnectionConfiguration connConfig = new ConnectionConfiguration(HOST, PORT, SERVICE);
XMPPConnection connection = new XMPPConnection(connConfig);

try {
  //Connect to the server
  connection.connect();
} catch (XMPPException ex) {
  connection = null;
  //Unable to connect to server
}

[Code 2]

The XMPPConnection class is used to create the connection to the XMPP server specified by the ConnectionConfiguration class, which uses configuration parameters for establishing connection with the server.

To disconnect, use the disconnect() method.

Login to a Server

Once a connection is established, the user should log in with username and password using the login() method of the Connection class. Following code snippet shows how to login:

//Most servers require you to login before performing other tasks.
connection.login(USERNAME, PASSWORD);
//for example: connection.login(“abc@gmail.com”, “password”);

[Code 3]

Once logged in, user can start using chat features; Chat or GroupChats, Set Presence, Get Rosters etc.

Setting user Presence

After logging in, the user might set his or her presence (availability) status visible to other recipients (Rosters) present in the chat list.

The following code shows how to set the presence. The Presence object is created with a status set to type “unavailable”. This presence status is later send as packet using the Connection class’s sendPacket() method.

// Create a new presence. Pass in false to indicate we're unavailable.
Presence presence = new Presence(Presence.Type.unavailable);
presence.setStatus("I’m unavailable");
connection.sendPacket(presence);

[Code 4]

Getting Roster

The Roster class does the following

  • Keeps track of the availability (presence) of other users
  • Allows users to be organized into groups such as “Friends” and “Co-workers”
  • Finds all roster entries and groups they belong to
  • Retrieves the presence status of each user.

Retrieving the roster is done using the Connection.getRoster() method.

Roster roster = connection.getRoster();
//Get all rosters
Collection<RosterEntry> entries = roster.getEntries();
//loop through
for (RosterEntry entry : entries) {
//example: get presence, type, mode, status
Presence entryPresence = roster.getPresence(entry.getUser());
  Presence.Type userType = entryPresence.getType();
  Presence.Mode mode = entryPresence.getMode();
  String status = entryPresence.getStatus();
}

[Code 5]

The previous code provides the status of users at a given point in time, but to obtain users’ Presence in real time, RosterListener (interface) is used. The Callback methods are called whenever there is change in roster or change in the presence of users in the roster.

roster.addRosterListener(new RosterListener() {
 @Override
 public void presenceChanged(Presence presence) {
   //Called when the presence of a roster entry is changed
 }
 @Override
 public void entriesUpdated(Collection<String> arg0) {
   // Called when a roster entries are updated.
 }
 @Override
 public void entriesDeleted(Collection<String> arg0) {
   // Called when a roster entries are removed.
 }
@Override
 public void entriesAdded(Collection<String> arg0) {
   // Called when a roster entries are added.
 }
});

[Code 6]

Sending Messages

Messages can be sent in one of two ways:

  • In the form of packets using XMPPConnection sendPacket(Message msg) method.
  • As a string of Chat Messages using the Chat class. The Chat is a series of messages exchange between two or more users.

Following code snippet shows how to send Message using sendPacket() method of XMPPConnection

// Send chat msg to with msg type as (chat, normal, groupchat, headline, error)
Message msg = new Message(String to, Message.Type type);
msg.setBody(“How are you?”);
connection.sendPacket(msg);

[Code 7]

The chat class is a convenient way to send messages. The following code snippet shows how to send message using Chat class.

ChatManager chatmanager = connection.getChatManager();
Chat newChat = chatmanager.createChat("abc@gmail.com", new MessageListener() {
  // Receiving Messages
  public void processMessage(Chat chat, Message message) {
    Message outMsg = new Message(message.getBody());
    try {
      //Send Message object
      newChat.sendMessage(outMsg);
    } catch (XMPPException e) {
      //Error
    }
  }
});
try {
  //Send String as Message
  newChat.sendMessage("How are you?");
} catch (XMPPException e) {
  //Error
}

[Code 8]

The ChatManager instance is obtained from XMPPConnection using the getChatManager() method. ChatManager keeps track on all current chats. Chat is created which will now be series of messages exchanged between two users.

The sendMessage(String msg) or sendMessage(Message msg) method is used for sending text messages or message object in the context of a given chat session.

Moreover, MessageListener can be used to get callbacks of notification of Message from other users on chat.

Receiving Messages

Receiving messages from other user is done using:

  • Poll mechanism provided through the use of the PacketCollector class.
  • Asynchronous mechanism through the use of the PacketListener (Recommended)

The following code snippet shows an asynchronous way of listening to incoming messages using PacketListener.

// Add a packet listener to get messages sent to us
PacketFilter filter = new MessageTypeFilter(Message.Type.chat);
connection.addPacketListener(new PacketListener() {
  public void processPacket(Packet packet) {
    Message message = (Message) packet;
    String body = message.getBody();
    String from = message.getFrom();
  }
}, filter);

[Code 9]

Sample Example

Here an example consists of ListView to display the chat conversation between two users. It has by default set values of Google talk XMPP parameters.

Remember to add the jar file into your project lib folder and Internet permission in manifest file. The example is using the asmack library: patched version made for Android.

res\layout\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" >

  <LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal" >

    <TextView
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:minWidth="70dp"
      android:text="Chat With"
      android:textStyle="bold" />

    <EditText
      android:id="@+id/toET"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:hint="Add Recipient"
      android:minWidth="250dp"
      android:scrollHorizontally="true"
      android:singleLine="true"
      android:textSize="16sp" />
  </LinearLayout>

  <ListView
    android:id="@+id/listMessages"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_weight="1"
    android:scrollbars="horizontal" />

  <LinearLayout
    android:id="@+id/linearLayout2"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:gravity="bottom"
    android:orientation="horizontal" >

    <EditText
      android:id="@+id/chatET"
      android:layout_width="0dip"
      android:layout_height="wrap_content"
      android:layout_weight="1"
      android:gravity="top"
      android:hint="Type to compose"
      android:scrollHorizontally="true" >
    </EditText>

    <Button
      android:id="@+id/sendBtn"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_marginLeft="5dp"
      android:layout_marginRight="5dp"
      android:layout_marginTop="5dp"
      android:text="Send"
      android:textStyle="bold" />
  </LinearLayout>
</LinearLayout>

[Code 10]

res\layout\listitem.xml
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
  android:id="@+id/text1"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:singleLine="false"
  android:textStyle="bold" />

[Code 11]

AndroidManifest.xml
"<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
  package="com.demo.xmppchat"
  android:versionCode="1"
  android:versionName="1.0" >

  <uses-sdk android:minSdkVersion="8" />

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

  <application
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name" >
    <activity
      android:name=".XMPPChatDemoActivity"
      android:label="@string/app_name" >
      <intent-filter>
        <action android:name="android.intent.action.MAIN" />

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

</manifest>

[Code 12]

XMPPChatDemoActivity.java
package com.demo.xmppchat;

import java.util.ArrayList;
import java.util.Collection;

import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.PacketListener;
import org.jivesoftware.smack.Roster;
import org.jivesoftware.smack.RosterEntry;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.filter.MessageTypeFilter;
import org.jivesoftware.smack.filter.PacketFilter;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smack.util.StringUtils;

import android.app.Activity;
import android.app.ProgressDialog;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;

public class XMPPChatDemoActivity extends Activity {

  public static final String HOST = "talk.google.com";
  public static final int PORT = 5222;
  public static final String SERVICE = "gmail.com";
  public static final String USERNAME = "userid@gmail.com";
  public static final String PASSWORD = "password";

  private XMPPConnection connection;
  private ArrayList<String> messages = new ArrayList<String>();
  private Handler mHandler = new Handler();

  private EditText recipient;
  private EditText textMessage;
  private ListView listview;

  /** Called when the activity is first created. */
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    recipient = (EditText) this.findViewById(R.id.toET);
    textMessage = (EditText) this.findViewById(R.id.chatET);
    listview = (ListView) this.findViewById(R.id.listMessages);
    setListAdapter();

    // Set a listener to send a chat text message
    Button send = (Button) this.findViewById(R.id.sendBtn);
    send.setOnClickListener(new View.OnClickListener() {
      public void onClick(View view) {
        String to = recipient.getText().toString();
        String text = textMessage.getText().toString();          
        Log.i("XMPPChatDemoActivity ", "Sending text " + text + " to " + to);
        Message msg = new Message(to, Message.Type.chat);  
        msg.setBody(text);
        if (connection != null) {
          connection.sendPacket(msg);
          messages.add(connection.getUser() + ":");
          messages.add(text);
          setListAdapter();
        }
      }
    });
    connect();
  }

  /**
   * Called by Settings dialog when a connection is establised with 
   * the XMPP server
   */
  public void setConnection(XMPPConnection connection) {
    this.connection = connection;
    if (connection != null) {
      // Add a packet listener to get messages sent to us
      PacketFilter filter = new MessageTypeFilter(Message.Type.chat);
      connection.addPacketListener(new PacketListener() {
        @Override
        public void processPacket(Packet packet) {
          Message message = (Message) packet;
          if (message.getBody() != null) {
            String fromName = StringUtils.parseBareAddress(message.getFrom());
            Log.i("XMPPChatDemoActivity ", " Text Recieved " + message.getBody() + " from " +  fromName);
            messages.add(fromName + ":");
            messages.add(message.getBody());
            // Add the incoming message to the list view
            mHandler.post(new Runnable() {
              public void run() {
                setListAdapter();
              }
            });
          }
        }
      }, filter);
    }
  }

  private void setListAdapter() {
    ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.listitem, messages);
    listviewr.setAdapter(adapter);
  }

  @Override
  protected void onDestroy() {
    super.onDestroy();
    try {
      connection.disconnect();
    } catch (Exception e) {

    }
  }

  public void connect() {

    final ProgressDialog dialog = ProgressDialog.show(this, "Connecting...", "Please wait...", false);
    Thread t = new Thread(new Runnable() {
      @Override
      public void run() {
        // Create a connection
       ConnectionConfiguration connConfig = new ConnectionConfiguration(HOST, PORT, SERVICE);
       XMPPConnection connection = new XMPPConnection(connConfig);
         try {
           connection.connect();
           Log.i("XMPPChatDemoActivity",  "[SettingsDialog] Connected to "+connection.getHost());
         } catch (XMPPException ex) {
             Log.e("XMPPChatDemoActivity",  "[SettingsDialog] Failed to connect to "+ connection.getHost());
             Log.e("XMPPChatDemoActivity", ex.toString());
             setConnection(null);
         }
          try {
            connection.login(USERNAME, PASSWORD);
            Log.i("XMPPChatDemoActivity",  "Logged in as" + connection.getUser());

            // Set the status to available
            Presence presence = new Presence(Presence.Type.available);
            connection.sendPacket(presence);
            setConnection(connection);

            Roster roster = connection.getRoster();
            Collection<RosterEntry> entries = roster.getEntries();
            for (RosterEntry entry : entries) {

              Log.d("XMPPChatDemoActivity",  "--------------------------------------");
              Log.d("XMPPChatDemoActivity", "RosterEntry " + entry);
              Log.d("XMPPChatDemoActivity", "User: " + entry.getUser());
              Log.d("XMPPChatDemoActivity", "Name: " + entry.getName());
              Log.d("XMPPChatDemoActivity", "Status: " + entry.getStatus());
              Log.d("XMPPChatDemoActivity", "Type: " + entry.getType());
              Presence entryPresence = roster.getPresence(entry.getUser());

              Log.d("XMPPChatDemoActivity", "Presence Status: "+ entryPresence.getStatus());
              Log.d("XMPPChatDemoActivity", "Presence Type: " + entryPresence.getType());

              Presence.Type type = entryPresence.getType();
              if (type == Presence.Type.available)
                Log.d("XMPPChatDemoActivity", "Presence AVIALABLE");
                Log.d("XMPPChatDemoActivity", "Presence : " + entryPresence);
              }
              } catch (XMPPException ex) {
                Log.e("XMPPChatDemoActivity", "Failed to log in as "+  USERNAME);
                Log.e("XMPPChatDemoActivity", ex.toString());
                setConnection(null);
              }
              dialog.dismiss();
           }
      });
    t.start();
    dialog.show();
  }
}

Copy from: http://developer.samsung.com/technical-doc/view.do;jsessionid=pgvxVGNDSLFfXznD9vvnMm0h0JQKhpJhpJvsVlgMK6vdx1R0NxWQ!-1892717541?v=T000000119

 
2 Comments

Posted by on August 7, 2015 in Android, Mobile Development, XMPP