Hot questions for Chart Data in MPAndroidChart

Data received from Android Bluetooth socket is getting plotted in the line chart only after socket's termination

Question: I have recently started working on Android, Kotlin and MPAndroidChart. I am developing an Android application that receives data from a bluetooth server and the data obtained should be plotted in real time using MPAndroidChart.

Here is the Kotlin code:

class ConnectionActivity:AppCompatActivity() {

    companion object{
        val TAG = "FlowSensor"
        val APP_NAME = "FlowSensor"
        var myUUID: UUID = UUID.fromString("8ce255c0-200a-11e0-ac64-0800200c9a66")
        var mBluetoothSocket: BluetoothSocket? = null
        lateinit var mProgress: ProgressDialog
        lateinit var mBluetoothAdapter: BluetoothAdapter
        var mIsConnected: Boolean = false
        lateinit var mAddress: String
        lateinit var editText:EditText
        lateinit var mChart:LineChart
        var xVal:Int = 0
        var yVal:Int = 0
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT

        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_connection)

        mChart = findViewById<LineChart>(R.id.line_chart)

       receive_button.setOnClickListener{
            ReceiveData()
        }
    }

    //1 parameters missing
    private fun mAddEntry() {
        Log.d(TAG, "yVal : $yVal")
        var mData = mChart.data

        if(mData != null){
            var mDataSet = mData.getDataSetByIndex(0)

            if(mDataSet == null){
                mDataSet = createDataSet()
                mData.addDataSet(mDataSet)
            }

            var mEntry:Entry = Entry( xVal.toFloat(), yVal.toFloat())
            xVal++

            mData.addEntry(mEntry, 0)

            //Notify chart data has changed
            mChart.notifyDataSetChanged()

            //Limit no of visible entries
           // mChart.setVisibleXRange(1f, 6f)
            mChart.setVisibleXRangeMaximum(6f)

            //Scroll to the last entry
            mChart.moveViewToX(xVal.toFloat())
        }
    }

    //1 parameter missing
    private fun createDataSet(): LineDataSet? {
        var mDataSet = LineDataSet(null, "Data vals")

        //mDataSet.setDrawCubic
        mDataSet.cubicIntensity = 0.2f
        mDataSet.axisDependency = YAxis.AxisDependency.LEFT
        mDataSet.setColor(ColorTemplate.getHoloBlue())
        mDataSet.setCircleColor(ColorTemplate.getHoloBlue())
        mDataSet.lineWidth = 2f
        mDataSet.circleSize = 4f
        mDataSet.fillAlpha = 65
        mDataSet.fillColor = ColorTemplate.getHoloBlue()
        mDataSet.highLightColor = Color.rgb(244, 117, 177)
        mDataSet.valueTextColor = Color.WHITE
        mDataSet.valueTextSize = 10f

        return mDataSet
    }

    private fun ReceiveData() {
        val buffer = ByteArray(1024) // buffer store for the stream
        var bytes: Int // bytes returned from read()
        // Keep listening to the InputStream until an exception occurs
        Log.d(TAG, "Inside ReceiveData()")
        while (true) { // Read from the InputStream
            if(mBluetoothSocket != null)
            {
                try {
                    bytes = mBluetoothSocket!!.inputStream.read(buffer)
                    val incomingMessage = String(buffer, 0, bytes)
                    Log.d(TAG, "InputStream: $incomingMessage")
                    yVal = incomingMessage.toInt()
                    mAddEntry()
                } catch (e: IOException) {
                    Log.e(TAG, "write: Error reading Input Stream. " + e.message)
                    break
                }
            }
        }
    }

}

App starts in the Main Activity(code not attached here), looks for paired devices then using code

intent = Intent(this, ConnectionActivity::class.java)
            intent.putExtra(EXTRA_ADDRESS, address)
            startActivity(intent)

control reaches Connection Activity (code attached above).

App is successfully receiving data from server; verified by observing logcat. In ReceiveData(), I am trying to pass the received data to mAddEntry() which is responsible for drawing the graph. But the problem is, data is plotted only after I terminate the socket, so after Line no 112 in the attached logcat log, all the data is plotted at once (no data loss). I want to plot data in real time, and this is the problem I am facing.

graph plotting has been independently verified by passing dummy data in real-time inside onCreate() in ConnectionActivity class using the timer.scheduleAtFixedRate. This is working as expected.

Answer: by calling the reciveData() inside the receive_button onClickListner you are executing while loop that will run until Bluetooth socket is connected and it is runing on the MainThread (UIThread) and it will block the UI thread and doesn't let any other ui updateto happen you should execute the reciveData() function on the background and when you want the plot the data in chart you should pass the data in ui thread or call the mAddEntry() function in ui thread


Reading data from json array to plot in graph

Question: So I am using the MPandroid chart dependency to plot the graph on an android app. For this I am adding data to an ArrayList of class Entry of the graph. I am adding the data manually for now but I want to parse a the data from a json file and add it to graph. can anyone tell me how can I read individual data elements of Json array to add to graph.

This is the code I am using to read the json file.I have the file in my asset folder.

  try {
        InputStream is=getAssets().open("gaitdata.json");
        int size=is.available();
        byte[] buffer=new byte[size];
        is.read(buffer);
        is.close();
        json=new String(buffer,"UTF-8");
        JSONArray jsonArray=new JSONArray(json);

            for(int i=0;i<jsonArray.length();i++){
                JSONObject obj=jsonArray.getJSONObject(i);
                if(obj.getString("name").equals("kinematics")){
                    hipvalue.add(obj.getString("hip_min"));


              }
            }

Also this is the json file I want to read.

{
 "name":"kinematics",
 "hip_min":[1.2,5.67,2.34,6.8]
}

Also I want the float value but since it is not working so I have used obj.getString() to get the "hip_min" value for json.

And Lastly this is how I add data manually to Array list.

ArrayList<Entry> entries=new ArrayList<>();
        entries.add(new Entry(0,19.85f));

Answer: For converting the Json Arry to floating Array you can try the following code .

   String value = "{'name':'kinematics','hip_min':[1.2,5.67,2.34,6.8]}";
        JSONObject obj = new JSONObject(value);
        List hip_min = new ArrayList<Float>();
        JSONArray jsonArray;

        jsonArray = obj.getJSONArray("hip_min");

        for (Object item : jsonArray
        ) {
            hip_min.add(item);
        }
        System.out.println("Size : " + hip_min.size());

And for Chart

 int i=0;
        for (Object item:hip_min
             ) {
            entries.add(new Entry(i,item))
                    i=i+2;


        }

the value of i is for horizontal shift. i hope that will help.


MPAndroidChart: multiple LineDataSet from LiveData in a LineChart

Question: Looking at other examples, I see that the chart needs all the data sets at once and you cannot add them iteratively once they are ready. Am I wrong?

ArrayList<ILineDataSet> dataSets = new ArrayList<ILineDataSet>();
...
dataSets.add(d1);
dataSets.add(d2);
...
LineData data = new LineData(dataSets);
mChart.setData(data);

My problem is that I hold the necessary data for the multiple LineDataSet in a database and access them through LiveData. To draw a single LineDataSet would be simple because I would write the logic of this inside stuff.observe{}.

stuff.observe(this, goodStuff -> {
    Data data = generateData(goodStuff);
    mChart.setData(data);
});

But now I have to observe multiple stuff and then set the data of multiple stuff to the chart. How to achieve this?

Answer: Yes, you can add data Dynamically/Real time, just keep in mind that you also need to notify your chart about data in your observer,

stuff.observe(this, goodStuff -> {
    Data data = generateData(goodStuff);
    mChart.setData(data);
    mChart.notifyDataSetChanged(); // let the chart know it's data changed
    mChart.invalidate(); // refresh chart
});

BarChart is not showing correct dynamic data

Question: I have implemented bar chart where data will come dynamically. In my code data is coming from server but the graph is not show correct data it shows only -1, 0 and 1 position. I am using MPAndroidChart library for bar chart.

elow is my fragment class

public class MonthsFragment extends Fragment {

public String user_id;
// Session Manager Class
UserSessionManager session;

BarChart chartUniqueVisitors;
ArrayList<BarEntry> BARENTRY ;
ArrayList<String> BarEntryLabels ;
BarDataSet Bardataset ;
BarData BARDATA ;

public float jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec;

public MonthsFragment(){}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View view= inflater.inflate(R.layout.fragment_unique_visitors, container, false);

    session = new UserSessionManager(getContext());
    session.checkLogin();
    // get user data from session
    HashMap<String, String> user = session.getUserDetails();
    user_id = user.get(UserSessionManager.KEY_USER_ID);
    return view;
}

    private void getDataForBusinessAddress() {
        String URL ="XYZ.php?username="+user_id;
        StringRequest stringRequest = new StringRequest(Request.Method.POST,URL, new Response.Listener<String>() {
            @Override
            public void onResponse(String response) {
                Log.e("Response montghly____",response);

                JSONArray jsonarray = null;
                try {
                    jsonarray = new JSONArray(response);
                    for (int i = 0; i < jsonarray.length(); i++) {
                        JSONObject jsonobject = jsonarray.getJSONObject(i);
                        jan = Float.parseFloat(jsonobject.getString("Jan"));
                        feb = Float.parseFloat(jsonobject.getString("Feb"));
                        mar = Float.parseFloat(jsonobject.getString("Mar"));
                        apr = Float.parseFloat(jsonobject.getString("Apr"));
                        may = Float.parseFloat(jsonobject.getString("May"));
                        jun = Float.parseFloat(jsonobject.getString("Jun"));
                        jul = Float.parseFloat(jsonobject.getString("Jul"));
                        aug = Float.parseFloat(jsonobject.getString("Aug"));
                        sep = Float.parseFloat(jsonobject.getString("Sep"));
                        oct = Float.parseFloat(jsonobject.getString("Oct"));
                        nov = Float.parseFloat(jsonobject.getString("Nov"));
                        dec = Float.parseFloat(jsonobject.getString("Dece"));
                        AddValuesToBARENTRY(jan,feb,mar,apr,may,jun,jul,aug,sep,oct,nov,dec);
                    }
                } catch (JSONException e) {
                    e.printStackTrace();
                }

            }
        },
                new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                        Toast.makeText(getContext(),error.getMessage().toString(),Toast.LENGTH_LONG).show();
                    }
                });

        RequestQueue requestQueue = Volley.newRequestQueue(getContext());
        requestQueue.getCache().clear();
        requestQueue.add(stringRequest);
    }

public void onViewCreated(View v, Bundle savedInstanceState) {
    super.onViewCreated(v, savedInstanceState);
    chartUniqueVisitors = (BarChart) v.findViewById(R.id.chartUniqueVisitors);

    getDataForBusinessAddress();

    BARENTRY = new ArrayList<>();
    BarEntryLabels = new ArrayList<String>();
    AddValuesToBarEntryLabels();
    Bardataset = new BarDataSet(BARENTRY, "Projects");
    BARDATA = new BarData(BarEntryLabels, Bardataset);
    Bardataset.setColors(ColorTemplate.COLORFUL_COLORS);
}

AddValuesToBARENTRY function to add response data to BARENTRY ArrayList

 public void AddValuesToBARENTRY(float jan, float feb, float mar, float apr, float may, float jun, float jul, float aug, float sep, float oct, float nov, float dec){
    BARENTRY.add(new BarEntry(jan, 0));
    BARENTRY.add(new BarEntry(feb, 1));
    BARENTRY.add(new BarEntry(mar, 2));
    BARENTRY.add(new BarEntry(apr, 3));
    BARENTRY.add(new BarEntry(may, 4 ));
    BARENTRY.add(new BarEntry(jun, 5 ));
    BARENTRY.add(new BarEntry(jul, 6));
    BARENTRY.add(new BarEntry(aug, 7));
    BARENTRY.add(new BarEntry(sep, 8));
    BARENTRY.add(new BarEntry(oct, 9));
    BARENTRY.add(new BarEntry(nov, 10));
    BARENTRY.add(new BarEntry(dec, 11));
    chartUniqueVisitors.setData(BARDATA);
}

AddValuesToBarEntryLabels function to add the values on Barchat

public void AddValuesToBarEntryLabels(){
    BarEntryLabels.add("Jan");
    BarEntryLabels.add("Feb");
    BarEntryLabels.add("Mar");
    BarEntryLabels.add("Apr");
    BarEntryLabels.add("May");
    BarEntryLabels.add("Jun");
    BarEntryLabels.add("Jul");
    BarEntryLabels.add("Aug");
    BarEntryLabels.add("Sep");
    BarEntryLabels.add("Oct");
    BarEntryLabels.add("Nov");
    BarEntryLabels.add("Dec");
  }
 }

Output is like below, which is not correct format.

Answer: The problem is in filling BarEntry

BARENTRY.add(new BarEntry(jan, 0));
BARENTRY.add(new BarEntry(feb, 1));

It should be :

BARENTRY.add(new BarEntry(0, jan));
BARENTRY.add(new BarEntry(1, feb));

First value index (x Value) second is actual value - height of BAR (that comes fom server).

Also call setData once on onCreate method, now you call it in loop, and it is called multiple time.

chartUniqueVisitors.setData(BARDATA);

Here what I got with your data


MPAndroidChart - Multiple lines for chart.setNoDataText

Question: I'm using the MPAndroidChart library which has a string written on the chart if no data is available yet.

If the string is too long, it seems to just overflow to both sides of the screen so I'm wondering if it's possible to make that text use multiple lines, because neither \n, <p>, nor <br> work.

The method to set that text is chart.setNoDataText(String) where chart is a LineChart view.

Answer: It is impossible, if you take a look at source of the library, here how it draws text

    @Override
    protected void onDraw(Canvas canvas) {
        if (mData == null) {    
            boolean hasText = !TextUtils.isEmpty(mNoDataText);    
            if (hasText) {
                MPPointF c = getCenter();
                canvas.drawText(mNoDataText, c.x, c.y, mInfoPaint);
            }    
            return;
        }

        if (!mOffsetsCalculated) {

            calculateOffsets();
            mOffsetsCalculated = true;
        }
    }

Here main line is

canvas.drawText(mNoDataText, c.x, c.y, mInfoPaint);

Library draws text mNoDataText as single line, starting from c.x, c.y. canvas.drawText() doesn't know how to handle newlines.


Populate MPAndroidChart Bar chart with SQLite database

Question: I have a MPAndroidChart that I want to use to display the results of a SQL Query giving the sum of my income column and grouping it by income_category. Another user on here got me closer to getting it to work, but I am receiving a null object reference error when I do the BarChart.setData. Debug shows the query works, so I can't figure out why it is null. Below is the code in the BudgetDbHelper:

public ArrayList<BarEntry> getBarEntries() {
    String income_sum_column = "income_sum";
    SQLiteDatabase db = this.getReadableDatabase();
    String[] columns = new String[]{"SUM(income) AS " + income_sum_column,"income_category"};
    Cursor csr = db.query("transactions",columns,null,null,"income_category",null,null);
    ArrayList<BarEntry> rv = new ArrayList<>();
    while(csr.moveToNext()) {
        rv.add(new BarEntry(
                csr.getInt(csr.getColumnIndex("income_category")),
                csr.getFloat(csr.getColumnIndex(income_sum_column))
        ));
    }
    csr.close();
    return rv; 

And here is the code for the CYIncomeChartActivity:

public class CYIncomeChartActivity extends AppCompatActivity {

    SQLiteDatabase sqLiteDatabase;

    // Database helper object //
    private BudgetDbHelper mDbHelper;

    BarChart barChart;

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

        mDbHelper = new BudgetDbHelper(this);
        sqLiteDatabase = mDbHelper.getWritableDatabase();

        ArrayList<BarEntry> barEntries = mDbHelper.getBarEntries();

        BarDataSet barDataSet = new BarDataSet(barEntries,"Income By Income Category");
        barDataSet.setColors(ColorTemplate.COLORFUL_COLORS);

        BarData barData = new BarData(barDataSet);
        barData.setBarWidth(0.9f);

        barChart.setData(barData);
    }
}

Answer: Your issue is that barChart is null, because you never set it to anything. You need something like

barChart = findViewById(R.id.my_chart);

in there before you can call

barChart.setData(barData);

Passing dataset between activity in MPAndroidChart

Question: I want to display barchart in full screen after clicking on a button but I got an error when passing BarEntry class between activities.

android.os.ParcelFormatException: Cannot parcel an Entry with non-parcelable data

my code :

ArrayList<BarEntry> barEntries = new ArrayList<>();
        barEntries.clear();
        barEntries.add(new BarEntry(0, new float[]{8f, 9f, 10f}, "Jan"));
        barEntries.add(new BarEntry(1, new float[]{11f, 9f, 5f}, "Feb"));
        barEntries.add(new BarEntry(2, new float[]{8f, 3f, 4f}, "Mar"));
        barEntries.add(new BarEntry(3, new float[]{5f, 14f, 2f}, "Apr"));
        barEntries.add(new BarEntry(4, new float[]{5f, 2f, 3f}, "May"));
        barEntries.add(new BarEntry(5, new float[]{2f, 15f, 6f}, "Jun"));
        barEntries.add(new BarEntry(6, new float[]{15f, 2f, 8f}, "Jul"));
        barEntries.add(new BarEntry(7, new float[]{4f, 19f, 4f}, "Aug"));
        barEntries.add(new BarEntry(8, new float[]{5f, 5f, 5f}, "Sept"));
        barEntries.add(new BarEntry(9, new float[]{6f, 6f, 6f}, "Oct"));
        barEntries.add(new BarEntry(10, new float[]{8f, 9f, 10f}, "Nov"));
        barEntries.add(new BarEntry(11, new float[]{2f, 7f, 7f}, "Dec"));
        barEntries.add(new BarEntry(12, new float[]{6f, 2f, 8f}, "Jan"));

Intent bar = new Intent(ChartRevenueActivity.this, FullscreenActivity.class);
                Bundle bundle = new Bundle();
                bundle.putSerializable("barEntries", barEntries);
                bar.putExtra("type", "barChart");
                bar.putExtras(bundle);
                startActivity(bar);

Answer: Add this lib to build.gradle,

compile 'com.google.code.gson:gson:2.8.1'

convert your Arraylist to json using Gson and pass the json string to new activity.

Intent bar = new Intent(ChartRevenueActivity.this, FullscreenActivity.class);
    bar.putExtra("type", "barChart");
    bar.putExtra("barentry",new Gson().toJson(barEntries));
    startActivity(bar);

retrieve the Arraylist in new activity like this,

ArrayList<BarEntry> barEntries = 
            new Gson().fromJson(getIntent().getStringExtra("barentry"), new TypeToken<ArrayList<BarEntry>>(){}.getType());

mpandroidchart LineData cannot be applied to (java.util.ArrayLIst<java.lang.String>

Question:

public class MainActivity extends AppCompatActivity {
private LineChart lineChart;

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


    lineChart = (LineChart)findViewById(R.id.chart);

    ArrayList<Entry> val  = new ArrayList<Entry>();

    val.add(new Entry(100.0f,0));
    val.add(new Entry(100.0f,1));
    val.add(new Entry(100.0f,2));
    val.add(new Entry(100.0f,3));

    LineDataSet setComp1 = new LineDataSet(val,"Company 1");
    setComp1.setAxisDependency(YAxis.AxisDependency.LEFT);

    ArrayList<LineDataSet> dataSets = new ArrayList<LineDataSet>();
    dataSets.add(setComp1);

    ArrayList<String> xVals = new ArrayList<String>();
    xVals.add("1.Q");
    xVals.add("2.Q");
    xVals.add("3.Q");
    xVals.add("4.Q");

    **LineData data = new LineData(xVals,dataSets);**


    lineChart.setData(data);
    lineChart.invalidate();
}
}

I've tried other Mpandroid LineCharts but always comes up with the same errors like this one.

LineData(com.github.mikephill.charting.interfaces.datasets.ILineDataSet...) in LineData cannot be applied to (java.util.ArrayLIst, java.util.ArrayList)

Error:(53, 25) error: constructor LineData in class LineData cannot be 
applied to given types;
required: ILineDataSet[]
found: ArrayList<String>,ArrayList<LineDataSet>
reason: varargs mismatch; ArrayList<String> cannot be converted to 
ILineDataSet

Specifically, [LineData data = new LineData(xVals,dataSets); ] this line is the problem.

Already set build.gradle and also imported jar file. How can I fix this?

Answer: To give multiple line datasets use following example and also use version 3.0.3 of mpcharts

ArrayList<Entry> lineEntries = new ArrayList<Entry>();
    lineEntries.add(new Entry(0, 6));
    lineEntries.add(new Entry(1, 9));
    lineEntries.add(new Entry(2, 4));
    lineEntries.add(new Entry(3, 8));
    lineEntries.add(new Entry(4, 12));
    lineEntries.add(new Entry(5, 10));

    LineDataSet lineDataSet1 = new LineDataSet(lineEntries, "Line1");
    lineDataSet1.setAxisDependency(YAxis.AxisDependency.LEFT);
    lineDataSet1.setColors(getColor("defaultGreen"));
    lineDataSet1.setLineWidth(3);
    lineDataSet1.setHighlightEnabled(true);
    lineDataSet1.setCircleColor(getColor("defaultOrange"));
    lineDataSet1.setCircleRadius(6);
    lineDataSet1.setCircleHoleRadius(3);
    lineDataSet1.setDrawHighlightIndicators(true);
    lineDataSet1.setHighLightColor(Color.RED);
    lineDataSet1.setValueTextSize(defaultValueTextSize);
    lineDataSet1.setValueTextColor(getColor("primaryDark"));
    lineDataSet1.setMode(LineDataSet.Mode.CUBIC_BEZIER);

    ArrayList<Entry> lineEntries2 = new ArrayList<Entry>();
    lineEntries2.add(new Entry(0, 8));
    lineEntries2.add(new Entry(1, 11));
    lineEntries2.add(new Entry(2, 6));
    lineEntries2.add(new Entry(3, 10));
    lineEntries2.add(new Entry(4, 14));
    lineEntries2.add(new Entry(5, 12));

    LineDataSet lineDataSet2 = new LineDataSet(lineEntries2, "Line2");
    lineDataSet2.setAxisDependency(YAxis.AxisDependency.LEFT);
    lineDataSet2.setColors(getColor("defaultOrange"));
    lineDataSet2.setLineWidth(3);
    lineDataSet2.setHighlightEnabled(true);
    lineDataSet2.setCircleColor(getColor("defaultGreen"));
    lineDataSet2.setCircleRadius(6);
    lineDataSet2.setCircleHoleRadius(3);
    lineDataSet2.setDrawHighlightIndicators(true);
    lineDataSet2.setHighLightColor(Color.RED);
    lineDataSet2.setValueTextSize(defaultValueTextSize);
    lineDataSet2.setValueTextColor(getColor("primaryDark"));
    lineDataSet2.enableDashedLine(8,16,4);
    lineDataSet2.setMode(LineDataSet.Mode.CUBIC_BEZIER);

    ArrayList<ILineDataSet> dataSets = new ArrayList<ILineDataSet>();
    dataSets.add(lineDataSet1);
    dataSets.add(lineDataSet2);

    LineData data = new LineData(dataSets);

    lineChart.setData(data);
    lineChart.animateY(1000);
    lineChart.getDescription().setText("Line Comparison Chart");

    Legend legend = lineChart.getLegend();
    legend.setStackSpace(5);
    legend.setTextColor(Color.BLACK);

    // xAxis customization
    XAxis xAxis = lineChart.getXAxis();
    xAxis.setGranularity(1f);
    xAxis.setGranularityEnabled(true);
    xAxis.setCenterAxisLabels(false);
    xAxis.setDrawGridLines(true);
    xAxis.setTextColor(Color.BLACK);
    xAxis.setPosition(XAxis.XAxisPosition.BOTH_SIDED);

    YAxis leftAxis = lineChart.getAxisLeft();
    leftAxis.setTextColor(Color.BLACK);
    YAxis rightAxis = lineChart.getAxisRight();
    rightAxis.setTextColor(Color.BLACK);

To give one line dataset use following example:

lineEntries = new ArrayList<Entry>();
    lineEntries.add(new Entry(0, 10));
    lineEntries.add(new Entry(1, 11));
    lineEntries.add(new Entry(2, 12));
    lineEntries.add(new Entry(3, 14));
    lineEntries.add(new Entry(4, 18));
    lineEntries.add(new Entry(5, 31));

    lineDataSet = new LineDataSet(lineEntries, "Line");
    lineDataSet.setAxisDependency(YAxis.AxisDependency.LEFT);
    lineDataSet.setHighlightEnabled(true);
    lineDataSet.setLineWidth(3);
    lineDataSet.setColor(getColor("defaultBlue"));
    lineDataSet.setCircleColor(getColor("defaultOrange"));
    lineDataSet.setCircleRadius(6);
    lineDataSet.setCircleHoleRadius(3);
    lineDataSet.setDrawHighlightIndicators(true);
    lineDataSet.setHighLightColor(Color.RED);
    lineDataSet.setValueTextSize(defaultValueTextSize);
    lineDataSet.setValueTextColor(getColor("primaryDark"));

    LineData lineData = new LineData(lineDataSet);
    lineChart.getXAxis().setPosition(XAxis.XAxisPosition.BOTH_SIDED);
    lineChart.animateY(1000);
    lineChart.setData(lineData);

For Custom xAxis values please refer following;

barChart.getXAxis().setValueFormatter(new IndexAxisValueFormatter(getXAxisValues()));

 private ArrayList<String> getXAxisValues()
{
    ArrayList<String> labels = new ArrayList<String> ();

    labels.add( "JAN");
    labels.add( "FEB");
    labels.add( "MAR");
    labels.add( "APR");
    labels.add( "MAY");
    labels.add( "JUN");
    return labels;
}