Wednesday, December 23, 2015

Android Volley Out of memory exception fixed using clear app cache dynamically


Hi, I used Volley in one of my project and at a time our API data changed from smaller to larger one.
and our Application started crashing and giving out of memory error. And when we clear App data and start Application again it worked fine.

After looking at certain links like
volley out of memory error
volley out of memory error 2

these links did'nt helped me but after noticing that when I clear App data app works fine. So here is solution which is working perfect for me and my App do not crash.

JSONObject mainObject = null;
INetworkOperationListner getJSONListener;

INetworkOperationListner will send data to Activity which called below doInBackGround method.
please note this is not AsyncTask doInBackground, this is my custom doInBackground. Volley donot need AsyncTask.

When request is completed and onResponse method is called I am callling deleteCache(context) method. which will clear cache after every call and no Out of memory error will occur.

public JSONObject doInBackground(HashMap<String,String> params, final String url) {
        RequestQueue mRequestQueue;
           JsonObjectRequest req = new JsonObjectRequest(url, new JSONObject(params),
                new com.android.volley.Response.Listener<JSONObject>() {
                    @Override                    public void onResponse(JSONObject response) {
                        mainObject = response;
                        try {
                            deleteCache(context);
                            getJSONListener.onRemoteCallComplete(response.toString());

                        } catch (JSONException e) {
                            e.printStackTrace();
                        }
                    }
                }, new com.android.volley.Response.ErrorListener() {
            @Override            public void onErrorResponse(VolleyError error) {
            }
        }
        )
        {
       @Override            public Map<String, String> getHeaders() throws AuthFailureError {
                HashMap<String, String> headers = new HashMap<String, String>();
                headers.put("Username", Constants.Username);
                headers.put("Password", Constants.Password);
                return headers;
            }
        };
        int socketTimeout = 15000;
        RetryPolicy policy = new DefaultRetryPolicy(socketTimeout, DefaultRetryPolicy.DEFAULT_TIMEOUT_MS, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT);
        req.setRetryPolicy(policy);
        //mRequestQueue.add(req);        Volley.newRequestQueue(context).add(req);

        return mainObject;
    }


How to delete Android Application cache programatically deleteCache(Context) will be called from onResponse.

public static void deleteCache(Context context) {
    try {
        File dir = context.getCacheDir();
        deleteDir(dir);
    } catch (Exception e) {}
}

public static boolean deleteDir(File dir) {
    if (dir != null && dir.isDirectory()) {
        String[] children = dir.list();
        for (int i = 0; i < children.length; i++) {
            boolean success = deleteDir(new File(dir, children[i]));
            if (!success) {
                return false;
            }
        }
        return dir.delete();
    }
    else if(dir!= null && dir.isFile())
        return dir.delete();
    else {
        return false;
    }
}

Acknowledgment: I got above delete app cache from stack overflow.
Use above code and enjoy your app will never crash due to volley out of memory error. :)




Saturday, October 3, 2015

Android listen for Incoming and Outgoing calls and block calls automatically in android using java reflection


First of all create a new aidl directory, and add ITelephony.aidl.
ITelephony.aidl file should be like this. Its package name must be same as below.


package com.android.internal.telephony; 
interface ITelephony {

 
   boolean endCall();
    void answerRingingCall();
     void silenceRinger();
 }


Create a new class named PhoneCallReceiver add Add these lines in Manifest.xml

<receiver android:name=".PhoneCallReceiver">
<intent-filter><action android:name="android.intent.action.PHONE_STATE"/></intent-filter>
</receiver>
If you want to enable/disable this broadcast receiver. You can add following code inActivity from where you want to start/stop this call blocking functionality.
extends PhoneCallReceiver class from BroadCastReceiver and implement onReceive method,onReceive method will be called whenever Phone_STATE will be changed which we added as action in intent-filter in manifest file
public void onReceive(Context context, Intent intent) {
    Log.v(TAG, "Receving....");    telephony = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
If statement will be true if there is Incoming Call, if you want to block Outgoing calls
add this code in else body which is below. 
if(intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(TelephonyManager.EXTRA_STATE_RINGING)) {
You can get Caller number using below line of code.
      caller_number = intent.getStringExtra("incoming_number");
       
 try {
           Class c = Class.forName(telephony.getClass().getName()); 
           Method m = c.getDeclaredMethod("getITelephony");
           m.setAccessible(true);
           telephonyService = (ITelephony) m.invoke(telephony);
           telephonyService.endCall();
           Log.d("CallBlocked", "CallBlocked");
           
        }
 catch (Exception e) {
            e.printStackTrace();      
  }

    } else {

        If you want to block Outgoing calls add the above code here...
    }
}

Write in Air Using Mobile Phone, Windows phone 8.1 Application source code

Using below code you can make drawing by moving Mobile phone in the Air. This application was done for Windows Phone 8.1 during a project, however its not a complete code, you can add more methods and can apply different techniques to smooth accelerometer values.

MainPage.XAML

This is not complete code of xaml file, this code is just to give you an idea, xaml file which is layout
file contains Canvas like below, application will draw hand movements on canvas. You can also add a pencil in canvas and move it / change its position within canvas as accelerometer values changes.

        <!--TODO: Content should be placed within the following grid-->
        <Grid Grid.Row="1" x:Name="root_layout" Tapped="root_layout_Tapped"
           Margin="19,9.5,19,0">
        <StackPanel Orientation="Vertical" VerticalAlignment="Center">
        <Canvas Background="White" Name="MyCanvas" Height="500"  Width="500">
        </Canvas>
        </StackPanel>
        </Grid>

---------------------------------------------------------------------------------------------------------------

MainPage.XAML.CS

This file contains actual logic,
Below is accelerometer reading change event, this will be called when you want app to start detecting hand movments, you can initialize accelerometer object.

public async void _accelerometer_ReadingChanged(Accelerometer sender, AccelerometerReadingChangedEventArgs args)
        {

            await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
            {

_num variable is used for, how many previous values you want to consider for calculating hand movment.
                if (_index >= _num)
                {
                    _index = 0;
                }

 As line is 2-D object, so we need only 2 values for x and y, but accelerometer gives us three     values  for X,Y,Z axis. so you can transform three values into 2. but I am using X and Z axis just to give you an Idea,

 X and Z axis values of accelerometer will be saved in an array so that application can calculate      average of values for noise removal and smoothing values of accelerometer.
 As you may have an idea that accelerometer gives us almost 180 values in a second for all the three    axis and application cannot process all values, so it needs to remove noise and smooth values.

                _x[_index] = (_accelerometer.GetCurrentReading().AccelerationX);
                _y[_index] = (_accelerometer.GetCurrentReading().AccelerationZ);

                _index++;
                for (int i = 0; i < _num; i++)
                {
                    _sumx += _x[i];
                    _sumy += _y[i];

                }

      y and x variable below contains smoothed values after averaging, which we will use for drawing.
                double y = _sumx / _num;

                double x = _sumy / _num;


                _currentposition.X = (x * 200);
                _currentposition.Y = (y * 200);


                // boundry detect

If you need to make sure that line which you are drawing donot cross Canvas boundary, you can //add a check like below.

if (_currentposition.X > MyCanvas.ActualWidth - 30 || _currentposition.Y > MyCanvas.ActualHeight - 30)
                {
                }

Here we will make a line object like below by giving it current and previous values of acceleromter
and then we will add this line object in Canvas.
           
                _drawLine = new Line()
                {
                    X1 = _previousposition.X,
                    Y1 = _previousposition.Y,
                    X2 = _currentposition.X,
                    Y2 = _currentposition.Y,
                    StrokeThickness = _strokrthick,
                    Stroke = new SolidColorBrush(Colors.Blue)

                };

                _previousposition.X = _currentposition.X;
                _previousposition.Y = _currentposition.Y;


If you need to detect pause, in accelerometer values, or hand movement, you can use below code.
it will calculate distance between values, if distance is below a certain threshold, you can make sure that user is not moving mobile phone or not drawing. You can find distance function below.
                //if (gloabal_length > 0)
                //{
                //    gloabal_array[cc] = _previousposition.X;
                //    gloabal_array[++cc] = _previousposition.Y;

                //    cc++;
                //    gloabal_length = gloabal_length - 2;
                //}

                //else if (gloabal_length == 0)
                //{
                //    gloabal_length = 6;
                //    cc = 0;

                //    int i = 0;
                //    g1 = gloabal_array[i];
                //    g2 = gloabal_array[i + 1];
                //    g3 = gloabal_array[i + 2];
                //    g4 = gloabal_array[i + 3];
                //    g5 = gloabal_array[i + 4];
                //    g6 = gloabal_array[i + 5];

                //}

                MyCanvas.Children.Add(_drawLine);
                double dist = Distance(g1, g2, g3, g4, g5, g6);

         
                if (flag == 0)
                {
                    MyCanvas.Children.Remove(_drawLine);
                    flag = 1;
                }

            });
     
     
        }

function for calculating distance between accelerometer values.

   /*CALCULATING DISTANCE*/
        private double Distance(double x1, double y1, double x2, double y2, double x3, double y3)
        {
            double d = 0;
       
            double[] dist_values = new double[200];

            d = Math.Sqrt(Math.Pow((x2 - x1), 2) + Math.Pow((y2 - y1), 2) + Math.Pow((x3 - x2), 2) +    Math.Pow((y3 - y2), 2));

            return d;
        }/*DISTANCE FUNCTION ENDS HERE */


If you want to convert this drawing into an image and want to store it on your device or want to send it, you can convert canvas into an image using below code.


     RenderTargetBitmap renderTargetBitmap = new RenderTargetBitmap();
                await renderTargetBitmap.RenderAsync(MyCanvas, (int)MyCanvas.Width, (int)MyCanvas.Height);
                IBuffer pixelBuffer = await renderTargetBitmap.GetPixelsAsync();
                byte[] pixels = null;
                pixels = pixelBuffer.ToArray();

                // 2. Write the pixels to a InMemoryRandomAccessStream
                var stream = new InMemoryRandomAccessStream();
                var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.BmpEncoderId, stream);

                encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Straight, (uint)renderTargetBitmap.PixelWidth,
                    (uint)renderTargetBitmap.PixelHeight, 96, 96, pixels);

                await encoder.FlushAsync();
                WB = new WriteableBitmap(renderTargetBitmap.PixelWidth, renderTargetBitmap.PixelHeight);
                WB.SetSource(stream);
                if (WB == null)
                    return;

                string filename = "Image-" + DateTime.Now.ToFileTime() + ".jpeg";
                await SaveWriteableBitmapAsJpeg(WB, filename);

                StorageFile userPhoto = await KnownFolders.CameraRoll.GetFileAsync(filename);

                BitmapImage image = new BitmapImage();

                byte[] fileBytes = null;
                using (IRandomAccessStreamWithContentType _stream = await userPhoto.OpenReadAsync())
                {

                    fileBytes = new byte[_stream.Size];
                    using (DataReader reader = new DataReader(_stream))
                    {
                        await reader.LoadAsync((uint)_stream.Size);
                        reader.ReadBytes(fileBytes);
                    }
                }


// If you want to convert it into string for serializing/streaming. than use below code
string encodedImage = Convert.ToBase64String(fileBytes);







Wednesday, September 30, 2015

asmack Android XMPP Login and Multi User Chat


ConnectionConfiguration config = new ConnectionConfiguration(SERVER_IPADDRESS, SERVER_PORT);
config.setDebuggerEnabled(true);
XMPPConnection connection = new XMPPConnection(config);
SmackConfiguration.setPacketReplyTimeout(100000);
connection.connect();

Now you are connected to server.

ChatManager chatManager = connection.getChatManager();

If you want to create group you have to login to the server using XMPP connection object like below.
connection.login("userName", "Password");

You can also login anonymously like this if your server allows you.
connection.LoginAnonymously();

Log.v("LoggedIn : ", "hammad");


// connection.getRoster().createGroup("hammamd");

If you donot specify correct Domain Name which your server recognize you will get Exception.
like Remote Server Not found or Not Authorised or Service not available.


MultiUserChat multiUserChat = new MultiUserChat(connection,"admin" + "@" + DOMAIN_NAME);

Log.v("Group join : ", "hammad");

This statment will join group with nick name hammad. if no group exist it will create a new group.
multiUserChat.join("hammad");


Than you can add message listner for reading/parsing incoming messages. like below. here you should extract message from packet object by converting it into message type class. 
PacketFilter filter = new MessageTypeFilter(org.jivesoftware.smack.packet.Message.Type.groupchat);connection.addPacketListener(new PacketListener() {
    @Override    public void processPacket(Packet packet) {
        org.jivesoftware.smack.packet.Message message = (org.jivesoftware.smack.packet.Message) packet;        if (message.getBody() != null) {
            String from = message.getFrom();            String Body = message.getBody();            // Add incoming message to the list view or similar        }
    }
}, filter);

with this line a message will be sent to group..

multiUserChat.sendMessage("hi group, I am Hammad");

If you want to get all registered users from server use below code.
You will need this code when you want to sync phone contacts with server, after getting all registered users from server in a list, read your android phone contacts and compare for contacts syncing.
If you want to search for a specific user from server replace * in the code with user name which you want to search.
do not forget to send configurations. use this this link for refrence, how to add configurations.
get Registered users from openfire server.


UserSearchManager search = new UserSearchManager(connection);try {
    Form searchForm = search.getSearchForm("search." + connection.getServiceName());    Form answerForm = searchForm.createAnswerForm();    answerForm.setAnswer("Username", true);    answerForm.setAnswer("search", "*");    System.out.println("search form");    ReportedData data = search.getSearchResults(answerForm, "search." + connection.getHost();    if (data.getRows() != null) {
        Iterator<ReportedData.Row> it = data.getRows();        while (it.hasNext()) {
            
            ReportedData.Row row = it.next();            Iterator iterator = row.getValues("jid");            if (iterator.hasNext()) {
                String value = iterator.next().toString();                user_list.add(value);
                // use variable user_list. List<String> user_list. initialize this variable.

             }
        }
    } else {
             // No contacts Found
    }
} catch (XMPPException e1) {
    // TODO Auto-generated catch block    e1.printStackTrace();}




There is another method of creating and joinning multi user group chat which is available at
below link.

http://stackoverflow.com/questions/32822357/create-persistent-group-in-xmpp-clientusingasmacklibrary-in-android





Thursday, September 10, 2015

Android NFC and Android Beam Tutorial


ABOUT ANDROID NFC:

Below are the few important things you need to know before starting development for P2P communication using Android based NFC devices.

 NFC allows sharing of files/data between devices using wireless technology. Required distance is cm  or less to initiate connection. Maximum distance can be 10 cm.

 Data transmission rate 424 kbits/s.

 Peer to peer communication mode of NFC is known as Android Beam.

Android Beam only works when the application sending the data is running in the foreground and the device receiving the data is unlocked.

Android Beam has two API’s.

NDEF Transfer API (for small data like URL or contact)
File Transfer API (for large data like videos)

User can exchange URL’s, contacts, images, videos.

Both devices can recognize each other and can transmit data simultaneously.

NFC P2P mode communication is available since API level 14 (since 4.0, Ice Cream Sandwich).

Device identifications must be implemented in application protocols, when needed.

In Android Beam, it has two options NFCIP-1 and LLCP.

In NFCIP mode, before starting communication devices can be defined, meaning which device will start communication (initiate) and which device will respond (reply). However in LLCP mode after initial handshake, decision is made by application.

The Android Beam animation is normally is shown when two NFC-capable devices come into range.

If application has to send large data it can hand over connection to Wi-Fi/Bluetooth. This results in faster transfer speeds between devices.
For beaming of specific content, an app is allowed to control the content being sent when adding Android Beam support. If the app does not specify data, beaming the app will open it on the receiving device. If the receiving device does not have the app, it will open the application page in the Play Store.

References:
http://stackoverflow.com/questions/tagged/nfc-p2p
http://open-nfc.org/wp/home/features/
http://code.tutsplus.com/tutorials/sharing-files-with-nfc-on-android--cms-22501
http://www.nfc.cc/2011/12/28/development-android-beam-and-nfc-peer-2-peer/


Kotlin Android MVP Dagger 2 Retrofit Tutorial

http://developine.com/building-android-mvp-app-in-kotlin-using-dagger-retrofit/