Sunday, October 30, 2016

Android App To Understand Sticky Broadcasts

This blog post is about an application that can be used to understand what is the difference between sticky broadcasts and ordinary broadcasts of Android system. App name is StickyBCast. App has below package name.
com.blogspot.nipunswritings.stickybcast.

UI of the app is shown below.
Above UI shows what sticky broadcast and ordinary broadcast sent. This app send broadcast at two events. One is when onStop() is called and other one is when user touch on send button. Content that is sent with sticky broadcast is displayed below "Sticky Broadcast Content" and Content that is sent with ordinary broadcast is displayed below "Ordinary Broadcast Content". The content that is sent with broadcast are shown in TextViews. 

To show content that is sent with sticky broadcast TextView with Id "sticky_content_tv" is used. TextView with id ordinary_content_tv is used to show the content that is sent with normal broadcast.

Class (MainActivity) below is used to show difference between two types of broadcasts. 

public class MainActivity extends AppCompatActivity {

    private TextView oContentTv;
    private TextView sContentTv;

    private String oContent;
    private String sContent;

    private IntentFilter oContentFilter;
    private IntentFilter sContentFilter;

    private BroadcastReceiver oReceiver = new BroadcastReceiver() {
        @Override        public void onReceive(Context context, Intent intent) {
            oContent = intent.getStringExtra(Constants.ORDINARY_EXTRA);
            setTextViews();
        }
    };

    private BroadcastReceiver sReceiver = new BroadcastReceiver() {
        @Override        public void onReceive(Context context, Intent intent) {
            sContent = intent.getStringExtra(Constants.STICKY_EXTRA);
            setTextViews();
        }
    };


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

        oContentTv = (TextView) findViewById(R.id.ordinary_content_tv);
        sContentTv = (TextView) findViewById(R.id.sticky_content_tv);

        oContentFilter = new IntentFilter(Constants.ORDINARY_ACTION);
        sContentFilter = new IntentFilter(Constants.STICKY_ACTION);
    }

    @Override    protected void onStart() {
        super.onStart();

        oContent = "";
        sContent = "";

        Intent oIntent = registerReceiver(oReceiver, oContentFilter);
        Intent sIntent = registerReceiver(sReceiver, sContentFilter);

        if (oIntent != null) {
            oContent = oIntent.getStringExtra(Constants.ORDINARY_EXTRA);
        }

        if (sIntent != null) {
            sContent = sIntent.getStringExtra(Constants.STICKY_EXTRA);
        }

        setTextViews();
    }


    @Override    protected void onStop() {
        super.onStop();
        sendBroadcasts("Ordinay Value 2", "Sticky Value 2");
    }

    private void setTextViews() {
        oContentTv.setText(this.oContent);
        sContentTv.setText(this.sContent);
    }

    public void sendBroadcasts(String oExtrVal, String sExtrVal) {
        Intent oIntent = new Intent(Constants.ORDINARY_ACTION);
        Intent sIntent = new Intent(Constants.STICKY_ACTION);

        oIntent.putExtra(Constants.ORDINARY_EXTRA, oExtrVal);
        sIntent.putExtra(Constants.STICKY_EXTRA, sExtrVal);


        sendBroadcast(oIntent);
        sendStickyBroadcast(sIntent);
    }

    public void sendBCastWithClick(View view) {
        sendBroadcasts("Ordinay Value 1", "Sticky Value 1");
    }
}

Some of the constants that are needed for this application has been defined in a class called Constants. This is the definition of that class.

public class Constants {
    public static String STICKY_ACTION = "com.blogspot.nipunswritings.s_action";
    public static String ORDINARY_ACTION = "com.blogspot.nipunswritings.o_action";

    public static String STICKY_EXTRA = "com.blogspot.nipunswritings.s_extra";
    public static String ORDINARY_EXTRA = "com.blogspot.nipunswritings.o_extra";
}

In MainActivitypublic void sendBroadcasts(String oExtrVal, String sExtrVal) method is called at two event. One event is in the onStop() method of the activity and other one is in the button click listener of send button with the method public void sendBCastWithClick(View view). The arguments that are passed to method sendBroadcasts(String, String) are different in two events. 

Code segment that is useful to understand difference between sticky broadcasts and normal broadcasts is this.

        Intent oIntent = registerReceiver(oReceiver, oContentFilter);
        Intent sIntent = registerReceiver(sReceiver, sContentFilter);

here when registration is done if sticky broadcast has been sent earlier that is returned by the function registerReceiver(Intent) for sticky broadcasts. But for normal broadcasts it returns null. If you run the app and click send button both text boxes will display text values that have been sent by broadcasts. In that case there is no difference between those two types of broadcast.  

Then do something that cause to call onStop() and come back to app. The TextView for sticky broadcast text has been set with the "Sticky Value 2" but other one is empty. Because system doesn't provide normal broadcast intents that was sent before registration. So for below code oIntent  is null.
        if (oIntent != null) {
            oContent = oIntent.getStringExtra(Constants.ORDINARY_EXTRA);
        }

        if (sIntent != null) {
            sContent = sIntent.getStringExtra(Constants.STICKY_EXTRA);
        }

To send broadcasts below function is used. Method sendStickyBroadcast(sIntent) is deprecated even though that is used for this example. 

    public void sendBroadcasts(String oExtrVal, String sExtrVal) {
        Intent oIntent = new Intent(Constants.ORDINARY_ACTION);
        Intent sIntent = new Intent(Constants.STICKY_ACTION);

        oIntent.putExtra(Constants.ORDINARY_EXTRA, oExtrVal);
        sIntent.putExtra(Constants.STICKY_EXTRA, sExtrVal);


        sendBroadcast(oIntent);
        sendStickyBroadcast(sIntent);
    }

Reference:
  • https://developer.android.com/reference/android/content/Context.html#sendStickyBroadcast(android.content.Intent)





Sunday, August 14, 2016

sendBroadcast Android Example

This is an example of using method sendBroadcast() to send broadcasts in Android. App has one BroadcastReceiver. It display broadcast action if there is one else display nothing. It also display the addition of two numbers that were sent to it. 

BroadcastReceiver has been implemented with the class NumberReceiver. So it must be registered by using the manifest file.

<receiver
    android:name=".NumberReceiver"
    android:enabled="true"
    android:exported="true">
    <intent-filter>
       <action android:name="com.blogspot.nipunswritings.demosendbcast.add" />
    </intent-filter>
</receiver>

It can receive intents with the below action

com.blogspot.nipunswritings.demosendbcast.add

Project has class Constants that has been defined key for intent actions and extras.

public class Constants { 
    public static String ACTION_ADD = "com.blogspot.nipunswritings.demosendbcast.add"; 
    public static String EXTRA_X = "com.blogspot.nipunswritings.demosendbcast.x"; 
    public static String EXTRA_Y = "com.blogspot.nipunswritings.demosendbcast.y";
}

In the activity that invoke sendBroadcast() has Two EditTexts and a Button. When user click the button numbers in two EditTexts are send to BroadcastReceiver after converting them to integers. This is the button onClick method.

public void sendToAddition (View view) {

    boolean withAction = false;

    int x = Integer.parseInt(xEt.getText().toString());
    int y = Integer.parseInt(yEt.getText().toString());

    Intent intent;

    if (withAction) {
        intent = new Intent(Constants.ACTION_ADD);
    } else {
        intent = new Intent(MainActivity.this, NumberReceiver.class);
    }
    intent.putExtra(Constants.EXTRA_X, x);
    intent.putExtra(Constants.EXTRA_Y, y);

    sendBroadcast(intent);
}

Important code snippet of above method is this.

    Intent intent;

    if (withAction) {
        intent = new Intent(Constants.ACTION_ADD);
    } else {
        intent = new Intent(MainActivity.this, NumberReceiver.class);
    }
    intent.putExtra(Constants.EXTRA_X, x);
    intent.putExtra(Constants.EXTRA_Y, y);
 
    sendBroadcast(intent); 

If Boolean variable withAction is true Intent instance is created with the ACTION_ADD in constants file. If it is not true since both Receiver and Activity in the same class Intent instance is created with the class. Then integer values which are got by casting String that are provided by EditTexts are put into Intent instance. Finally sendBroadcast() is called.

Method onReceive(Context, Intent) of NumberReceiver. has been written below.
 
@Overridepublic void onReceive(Context context, Intent intent) {
    int x = intent.getIntExtra(Constants.EXTRA_X, 0);
    int y = intent.getIntExtra(Constants.EXTRA_Y, 0);

    String action = intent.getAction();
    if (action != null) {
        Toast.makeText(context, "Action = "+action, Toast.LENGTH_LONG).
                show();
    } else {
        Toast.makeText(context, "Action isn't available", Toast.LENGTH_LONG).
                show();
    }


    Toast.makeText(context, "x + y = "+Calculator.performAddition(x,y), Toast.LENGTH_LONG).
            show();
}

It get extras and actions then display them with a Toast.

Calculations is done by using the Calculator class. Calculator class implementation is this.

public class Calculator {
    public static int performAddition (int x, int y) {
        return x+y;
    }
}


Sunday, July 17, 2016

Android LocalBroadcastManager Example

Using broadcasts in Android applications sometimes introduce problems as broadcasts can be received by the other applications too. To prevent these problems Android system has LocalBroadcastManager that can be used to implement secure communication mechanism within app components.

This example shows how to use LocalBroadcastManager to send and receive broadcasts. Though this application has only one activity it can LocalBroadcastManager is capable doing more than that. For example It can be used to send broadcasts from service to another activity, from One BroadcastReceiver to activity like use cases.

The app which is developed for demonstration has one EditText and Button. When user type something on EditText and click the Button typed content send to BroadcastReceiver that has been registered by using LocalBroadcastManager. After it received that Text it shows as a Toast.


Above image shows what this application does. Implementation of this application is on MainActivity class which is shown below.

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    private final String TEXT_SENT_ACTION =  
       "com.blogspot.nipunswritings.bcsender.action.TEXT_SENT";
    private final String TEXT_EXTRA 
       "com.blogspot.nipunswritings.bcsender.extra.TEXT";

    private BroadcastReceiver textSentReceier = new BroadcastReceiver() {
        @Override        public void onReceive(Context context, Intent intent) {
            String textExtra = intent.getStringExtra(TEXT_EXTRA);
            Toast.makeText(context, textExtra, Toast.LENGTH_LONG).show();
        }
    };

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

    @Override    protected void onResume() {
        super.onResume();

        IntentFilter textSentIntentFilter = new IntentFilter(TEXT_SENT_ACTION);
        LocalBroadcastManager
                .getInstance(MainActivity.this)
                .registerReceiver(textSentReceier, textSentIntentFilter);
    }

    @Override    protected void onPause() {
        LocalBroadcastManager.getInstance(MainActivity.this)
            .unregisterReceiver(textSentReceier);

        super.onPause();

    }

    public void sendLocalTestBc(View view) {
        EditText sendingTextEt = (EditText) findViewById(R.id.activity_main_sent_text_et);
        String sendingText = sendingTextEt.getText().toString();

        Intent textSentIntent = new Intent(TEXT_SENT_ACTION);
        textSentIntent.putExtra(TEXT_EXTRA, sendingText);
        LocalBroadcastManager.getInstance(MainActivity.this).sendBroadcast(textSentIntent);
    }
}


As Broadcasts and associated data are needed to be identified at the beginning of above class unique identifiers for above class has been defined like this.

    private final String TEXT_SENT_ACTION =  
       "com.blogspot.nipunswritings.bcsender.action.TEXT_SENT";
    private final String TEXT_EXTRA 
       "com.blogspot.nipunswritings.bcsender.extra.TEXT";

Receive Local Broadcasts 
To receive broadcasts this activity must have a BroadcastReceiver implementation, that is shown below.

    private BroadcastReceiver textSentReceier = new BroadcastReceiver() {
        @Override        public void onReceive(Context context, Intent intent) {
            String textExtra = intent.getStringExtra(TEXT_EXTRA);
            Toast.makeText(context, textExtra, Toast.LENGTH_LONG).show();
        }
    };

Register Receiver with LocalBroadcastManager
In the onResume() IntentFilter is created to register receiver for designated action. IntentFilter constructor take that action as the parameter so it can receive broadcasts with this action.  
Next line is about registering receiver for the IntentFilter by using LocalBroadcastManager and registerReceiver(). After that receiver has ability to get broadcasts with TEXT_SENT_ACTION.
    @Override    protected void onResume() {
        super.onResume();

        IntentFilter textSentIntentFilter = new IntentFilter(TEXT_SENT_ACTION);
        LocalBroadcastManager
                .getInstance(MainActivity.this)
                .registerReceiver(textSentReceier, textSentIntentFilter);
    }

Unregister Receiver with LocalBroadcastManager
    @Override    protected void onPause() {
        LocalBroadcastManager.getInstance(MainActivity.this)
            .unregisterReceiver(textSentReceier);

        super.onPause();

    }

All registered BroadcastReceivers must be unregistered so it has done in onPause() by using unregisterReceiver() and LocalBroadcastManager.

Sending LocalBroadCasts

    public void sendLocalTestBc(View view) {
        EditText sendingTextEt = (EditText) findViewById(R.id.activity_main_sent_text_et);
        String sendingText = sendingTextEt.getText().toString();

        Intent textSentIntent = new Intent(TEXT_SENT_ACTION);
        textSentIntent.putExtra(TEXT_EXTRA, sendingText);
        LocalBroadcastManager.getInstance(MainActivity.this).sendBroadcast(textSentIntent);
    }

Above method is onClick method of the button. When user touch that button a Intent is crated with previously defined action and data key. After that it is sent with sendBroadcast() and LocalBroadcastManager.

References:
  • https://developer.android.com/reference/android/support/v4/content/LocalBroadcastManager.html

Sunday, June 26, 2016

registerReceiver (BroadcastReceiver, IntentFilter) Android Example

This example is about using registerReceiver and unregisterReceiver methods to use BroadcastReceiver programmatically. When BroadcastReceiver is registered in this way it's not declared in the AndroidManifest.xml file.

This application project has one Activity file and it register BroadcastReceiver to obtain battery level change information. Broadcast action ACTION_BATTERY_CHANGED is used by Android system to broadcast battery level changing information. Therefore that is used in this project.

Below source code is about implementation of the class BatteryChangedReceiver that extends from BroadcastReceiver. It receive battery change information and extra data on that intent are got by using the class BatteryManager. BatteryManager class has definitions of extra data that are sent with aforementioned broadcast action. Once onReceive(Context, Intent) method receives that data they are shown as Toast.

BatteryChangedReceiver Implementation

import android.content.BroadcastReceiver; 
import android.content.Context; 
import android.content.Intent; 
import android.os.BatteryManager; 
import android.widget.Toast; 
 
public class BatteryChangedReceiver extends BroadcastReceiver { 
   public BatteryChangedReceiver() {
   } 
 
   @Override
   public void onReceive(Context context, Intent intent) { 
      if (intent.getAction().equals(Intent.ACTION_BATTERY_CHANGED)) { 
         int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1); 
         int scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
         Toast.makeText(context, "Level = "+level+", 
                        Scale = "+scale, Toast.LENGTH_LONG).show();
      }
   }
}

Above BroadcastReceiver is registered in the class MainActivity. That source code is this.

MainActivity Implementation

public class MainActivity extends AppCompatActivity { 
 
   private BatteryChangedReceiver batteryChangedReceiver; 
   private IntentFilter intentFilter; 
 
   @Override
   protected void onCreate(Bundle savedInstanceState) { 
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main); 
 
      batteryChangedReceiver = new BatteryChangedReceiver(); 
      intentFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
   } 
 
   @Override
   protected void onResume() { 
      super.onResume();
      registerReceiver(batteryChangedReceiver, intentFilter);
   } 
 
   @Override
   protected void onPause() {
      unregisterReceiver(batteryChangedReceiver);
      super.onPause();
   }
}

An instance of the BatteryChangedReceiver is created to be used as first argument to registerReceiver() method. This method needs IntentFilter object for second argument to register BroadcastReceiver provided with first argument for a specific Intent. So both objects for first and second arguments are created in onCreate() method.
 
   batteryChangedReceiver = new BatteryChangedReceiver(); 
   intentFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);

The method registerReceiver() is called in onResume() to register BroadcastReceiver. 
 
protected void onResume() { 
   super.onResume();
   registerReceiver(batteryChangedReceiver, intentFilter);
} 

As the BroadcastReceiver is registered in the onResume() it must be unregistered onPause(). Otherwise error will be occurred for leaking BroadcastReceiver. A BroadcastReceiver must be unregistered as many as it is registered.
 
@Override 
protected void onPause() {
   unregisterReceiver(batteryChangedReceiver); 
   super.onPause();
}

If onStop() is used to register BroadcastReceiver it must be unregistered in onStop().

Reference
  • https://developer.android.com/reference/android/content/Context.html#registerReceiver(android.content.BroadcastReceiver,%20android.content.IntentFilter)
  • https://developer.android.com/reference/android/content/Context.html#unregisterReceiver(android.content.BroadcastReceiver)
  • https://developer.android.com/reference/android/content/Intent.html#ACTION_BATTERY_CHANGED
  • https://developer.android.com/reference/android/os/BatteryManager.html

Sunday, June 19, 2016

Android BroadcastReceiver

Android applications need some mechanism to know when some event is occurred. For example some applications need to perform tasks when Android OS booting is completed. Android SDK provide BroadcastReceiver class for that purpose. This blog post content is about using BroadcastReceiver to get notification about connecting and disconnecting Android OS running device from external power source.
Name of this application is ConDisConInfo. So it has the main package with name com.blogspot.nipunswritings.ConDisConInfo. To create a BroadcastReceiver follow these steps.
  • Right Click on Main package
  • New
  • Other
  • Broadcast Receiver
  • Give name and click Finish
Once Finish is clicked a new java file can be seen in main package with the name PowerConnInfoReceiver.java. It has a PowerConnInfoReceiver class which extends from super class BroadcastReceiver. PowerConnInfoReceiver has below method which receive power connection/disconnection information which is sent by system.

@Overridepublic void onReceive(Context context, Intent intent) {
    
}

After  PowerConnInfoReceiver is created AndroidManifest.xml file has been updated with receiver element. That is registering a Broadcast Receiver. The receiver element in AndroidManifest.xml file is this.

<receiver 
     android:name=".PowerConnInfoReceiver" 
     android:enabled="true"
     android:exported="true">
</receiver>

Though that element is in the AndroidManifest.xml file PowerConnInfoReceiver will not receive any broadcast. A BroadcastReceiver to receive broadcasts it must be specified what broadcasts it must be received through the intent-filter element. Therefore receiver element is updated like below to receive broadcasts as mentioned above.

<receiver 
    android:name=".PowerConnInfoReceiver" 
    android:enabled="true"
    android:exported="true">
    <intent-filter>
        <action android:name="android.intent.action.ACTION_POWER_CONNECTED" />
        <action android:name="android.intent.action.ACTION_POWER_DISCONNECTED" />
    </intent-filter>
</receiver>

Notice the actions inside intent-filter. Without those actions this application doesn't work as expected. 

Method onReceive(Context, Intent) is updated to filter received information via Intent object and to display information to user as a Toast. So updated onReceive(Context, Intent) method is this.

@Overridepublic void onReceive(Context context, Intent intent) {
    if (intent.getAction().equals(Intent.ACTION_POWER_CONNECTED)){
        Toast.makeText(context, "Power Connected", Toast.LENGTH_LONG).show();
    } else if (intent.getAction().equals(Intent.ACTION_POWER_DISCONNECTED)) {
        Toast.makeText(context, "Power Disconnected", Toast.LENGTH_LONG).show();
    }
}

Run this app on a emulator. This application can be tested with battery section in extended controls of emulator. When charger connection is toggled between AC Charger and None corresponding Toast is displayed.



Reference:
  • https://developer.android.com/reference/android/content/BroadcastReceiver.html
  • https://developer.android.com/reference/android/content/Intent.html#ACTION_POWER_CONNECTED
  • https://developer.android.com/reference/android/content/Intent.html#ACTION_POWER_DISCONNECTED

Sunday, June 12, 2016

HelloCharts for Android Example

This example is using HelloCharts for Android to plot line chart for function |sin(x)|. The value range for x axis is from 0 to 360 degrees. The x values are given like 0, 15, 30, 45 ... 360. So there is difference of 15 degrees between  two points. But X axis is drawn with 30 degree scale. Therefore it goes like 0, 30, 60, 90, ..., 180, ...360. Y axis is drawn with scale of 0.25 from 0 to 1.0 to make Y axis range 0, 0.25, 0.5, 1.

At the end of this example developed application creates the below chart.

Add hello-charts library to app by adding below line to dependencies block of build.gradle file of app module. Then sync the project by using Android Studio.

compile 'com.github.lecho:hellocharts-library:1.5.8@aar'


Project has one Activity file with the name MainActivity.java. It's layout resource file is activity_main.xml.

This is the content of activity_main.xml. It has RelativeLayout as root element and RelativeLayout contain TextView and chart definition.

<TextView 
 android:id="@+id/chartLbl" 
 android:gravity="center" 
 android:layout_width="match_parent" 
 android:layout_height="wrap_content" 
 android:text="|sin(x)|" 
 android:layout_alignParentTop="true"     
 android:layout_alignParentStart="true"     
 android:layout_alignParentLeft="true"     
 android:layout_margin="5dp" 
 android:textStyle="bold" />

<lecho.lib.hellocharts.view.LineChartView 
 android:id="@+id/chart"     
 android:layout_width="match_parent" 
 android:layout_height="match_parent" 
 android:padding="10dp" 
 android:layout_below="@+id/chartLbl"/>

The element lecho.lib.hellocharts.view.LineChartView is xml definition of the line chart.

Now reference to this LineChartView can be made with findViewById(int) method. To hold reference to that view, field of type LineChartView has been defined in the MainActivity.java like this.
 
private LineChartView lineChartView;

Line chart has been created with below method. That is called in onCreate(Bundle) method.
 
public void drawSinAbsChart()

Method definition of  drawSinAbsChart()

public void drawSinAbsChart() {
    String decimalPattern = "#.##";
    DecimalFormat decimalFormat = new DecimalFormat(decimalPattern);

    lineChartView = (LineChartView) findViewById(R.id.chart);

    List<PointValue> values = new ArrayList<PointValue>();

    PointValue tempPointValue;
    for (float i = 0; i <= 360.0; i+= 15.0f) {
        tempPointValue = new PointValue(i, Math.abs((float)Math.sin(Math.toRadians(i))));
        tempPointValue.setLabel(decimalFormat
                   .format(Math.abs((float)Math.sin(Math.toRadians(i)))));
        values.add(tempPointValue);
    }

    Line line = new Line(values)
                   .setColor(Color.BLUE)
                   .setCubic(false)
                   .setHasPoints(true).setHasLabels(true);
    List<Line> lines = new ArrayList<Line>();
    lines.add(line);

    LineChartData data = new LineChartData();
    data.setLines(lines);

    List<AxisValue> axisValuesForX = new ArrayList<>();
    List<AxisValue> axisValuesForY = new ArrayList<>();
    AxisValue tempAxisValue;
    for (float i = 0; i <= 360.0f; i += 30.0f){
        tempAxisValue = new AxisValue(i);
        tempAxisValue.setLabel(i+"\u00b0");
        axisValuesForX.add(tempAxisValue);
    }

    for (float i = 0.0f; i <= 1.00f; i += 0.25f){
        tempAxisValue = new AxisValue(i);
        tempAxisValue.setLabel(""+i);
        axisValuesForY.add(tempAxisValue);
    }

    Axis xAxis = new Axis(axisValuesForX);
    Axis yAxis = new Axis(axisValuesForY);
    data.setAxisXBottom(xAxis);
    data.setAxisYLeft(yAxis);


    lineChartView.setLineChartData(data);


}

Code Explanation

    String decimalPattern = "#.##";
    DecimalFormat decimalFormat = new DecimalFormat(decimalPattern);

Values that are obtained must be shown only up to two decimal places in chart point labels. Object decimalFormat is created for that purpose.

    lineChartView = (LineChartView) findViewById(R.id.chart);

Above jave statement is to obtain the LineChartView object that is declared in the layout xml resource.

    List<PointValue> values = new ArrayList<PointValue>();

    PointValue tempPointValue;
    for (float i = 0; i <= 360.0; i+= 15.0f) {
        tempPointValue = new PointValue(i, Math.abs((float)Math.sin(Math.toRadians(i))));
        tempPointValue.setLabel(decimalFormat
                   .format(Math.abs((float)Math.sin(Math.toRadians(i)))));
        values.add(tempPointValue);
    }

Tha values that must be displayed in the line chart must be in the List of type List<PointValue>. That is doing here. That list contains points which are drawn in the chart. Point is represented with PointValue Class. for loop create those points and set it label that are shown at the points.

    Line line = new Line(values)
                   .setColor(Color.BLUE)
                   .setCubic(false)
                   .setHasPoints(true).setHasLabels(true);
    List<Line> lines = new ArrayList<Line>();
    lines.add(line);

    LineChartData data = new LineChartData();
    data.setLines(lines);

Line chart can  contain many lines, Above code shows how to create new line with the values which was generated function |sin(x)|. Method setColor() is used to define color of the line. This chart has straight line as setCubic() has been provided false value. If setHasPoints() called with argument false value points wouldn't be displayed.When setHasLabels() is provided with argument true value labels that was set during PointValue object are created is shown. The lines variable of type List<Line> holds all the lines that is drawn in the chart. This example chart has only one line so it has been added. Finally that lines object is added to LineChartData object with setLines().

    List<AxisValue> axisValuesForX = new ArrayList<>();
    List<AxisValue> axisValuesForY = new ArrayList<>();
    AxisValue tempAxisValue;
    for (float i = 0; i <= 360.0f; i += 30.0f){
        tempAxisValue = new AxisValue(i);
        tempAxisValue.setLabel(i+"\u00b0");
        axisValuesForX.add(tempAxisValue);
    }

    for (float i = 0.0f; i <= 1.00f; i += 0.25f){
        tempAxisValue = new AxisValue(i);
        tempAxisValue.setLabel(""+i);
        axisValuesForY.add(tempAxisValue);
    }

    Axis xAxis = new Axis(axisValuesForX);
    Axis yAxis = new Axis(axisValuesForY);
    data.setAxisXBottom(xAxis);
    data.setAxisYLeft(yAxis);

Java statements that are shown creating X and Y axis of the chart. First loop creates X axis which is started from 0 and goes upto 360 with increment 15.0 from previous x value. Values of axis is represented with object of type List<AxisValue> and AxisValue objects are used represent a location in the axis. AxisValue has setLabel() to display developer preferred label in the chart. In same way Y axis also has been created. After thata x & y axis is created as Axis objects. X axis is set to bottom with setAxisXBottom() and Y Axis is set to left with setAxisYLeft().

Chart data is provided to LineChartView with below statement.

    lineChartView.setLineChartData(data);

If axis values is cut off this link might be helpful. I had similar problem but I could resolve it without that link by adding 5dp padding around LineChartView.

Reference:
  • https://github.com/lecho/hellocharts-android

Saturday, June 4, 2016

Renaming Android Studio Project and Main Package

Content of this blog post has been tested with Android Studio 2.0.

Changing Project Name
  • Open Project Window (View → Tool Windows → Project or Alt + 1)
  • By default Project window shows the Android view change it to Project view with the drop down menu at top left. 


  •  Right click on project root → Show in Explorer.
  • Close Android Studio.
  • Go into project folder.
  • Change .iml file to new name that you want to have for the project.
  •  Change the project folder name to new name which is same name of .iml file.
  • Start Android Studio
  • Click on “Open an existing Android Studio project”
  • Find & select the renamed project, then “Ok”
Changing Package name
  • Right Click on package name (I tried this on main package)
  • Refactor
  • Rename
  • Rename Package
  • Type new name & click Refactor
  • Click on Do Refactor 
After doing this I have observed changing the main package name successfully renamed other two packages (androidTest & Test) during refactoring process. Although Generated files like AndroidManifest.xml also had correct values strings.xml file had old project name for the string element with attribute “app_name”.
Above experiment was done on a very small project.


Sunday, February 14, 2016

iOS Auto Layout Notes - 1

This post has written about 
  • Adding auto layout constraints to UI object by using interface builder
  • Changing auto layout constraints by using swift language
Auto layout constraints can be defined to work with different Size classes. Size classes that is applied to different devices and orientations can be change with the below Pop over in the interface builder.

Since UI components of this application is needed to be fit to all the UIs height and width size class of Any is selected here.

There is a UIImageView object on the UIViewController of this class. To center it horizontally on the screen select the UIImageView click on the align button to display Add New Alignment Constraints pop up.

On the pop up menu Select Horizontally in Container and then click on the button Add 1 Constraint.

UIImageView needs to be 10 point below from the top layout guide. And it need to have width and height of 200 points. To do that click on the pin button to show pop up that can be used to add constraints for above requirements.

Once the constraints were set by using pin pop up like above click on Add 3 Constraints to add them to UIImageView.

To see changes on the storyboard. Click on the Resolve Auto Layout Issues button that shows a   menu like below .Then click on Update Frames.

That will remove orange color lines if there are them and adjust UI dimensions to reflect constraints.

Change Auto layout Constraints with Swift Code

Create IBOutlet to UIImageView width and height constraints.

@IBOutlet weak var imageHeight: NSLayoutConstraint!
@IBOutlet weak var imageWidth: NSLayoutConstraint!


Write a method like below to change Auto layout constraints which is referred through outlets by using swift code.

func resizeImage(size: Int){
    imageHeight.constant = CGFloat(size)
    imageWidth.constant = CGFloat(size)
}


Value of instance of  NSLayoutConstraint can be changed by assigning new CGFloat value to that instance's constant property.

Sunday, February 7, 2016

How To Install Boost C++ Library On Ubuntu 14.04 LTS

This is how boost C++ library can be installed into a location that is needed to be put. Here I have installed into a folder in my home home folder. All the below command executed from a folder that contain boost_1_59_0.tar.bz2 file. Boost has been installed without ICU.

$ lsb_release -a

No LSB modules are available.
Distributor ID:    Ubuntu
Description:    Ubuntu 14.04.2 LTS
Release:    14.04
Codename:    trusty

$ python -V

Python 2.7.6

$ sudo apt-get install g++

$ sudo apt-get install python2.7-dev

$ sudo apt-get install libicu-dev

$ sudo apt-get install libbz2-dev

$ sudo apt-get install build-essential

$ sudo apt-get install autotools-dev

$ tar --bzip2 -xf boost_1_59_0.tar.bz2

$ cd boost_1_59_0/

$ ./bootstrap.sh --prefix=/home/nipun/BoostLibs --without-icu

$ ./b2 install --prefix=/home/nipun/BoostLibs