Author Archives: Laxman

Facebook like video player with fullscreen in recyclerView android Tutorial

In this tutorial we will create a video player inside recyclerView posts similar to facebook with fullscreen which will be played from web URL. We will use a library for this case. This video player looks more similar to MX Player -> a popular video player app for android.

Look at the above screenshots of what we are going to achieve in this tutorial.

Setting up Libraries:
Add following dependency to your build.gradle file and sync project.

    compile 'cn.jzvd:jiaozivideoplayer:6.0.2'

    compile 'com.danikula:videocache:2.7.0'
    compile 'com.github.bumptech.glide:glide:4.2.0'
    annotationProcessor 'com.github.bumptech.glide:compiler:4.2.0'

Android provides its own videoView and media player apis for loading video in a view. But they have some disadvantages. We will use the above library for showing video in a simple view.
Same can be done in viewHolders of a reyclerView.

Add following in the layout file of your acitivty, fragment or viewholder for recyclerview:

              <cn.jzvd.JZVideoPlayerStandard
                    android:id="@+id/videoplayer"
                    android:layout_width="match_parent"
                    android:layout_height="200dp" />

Now in java file of your activity, fragment or ViewHolder add following code to display a video from url:

     JZVideoPlayerStandard jzVideoPlayerStandard = (JZVideoPlayerStandard) view.findViewById(R.id.videoplayer);

            HttpProxyCacheServer proxy = getProxy(this);
            jzVideoPlayerStandard.setUp(proxy.getProxyUrl(VIDEO_URL)
                    , JZVideoPlayerStandard.SCREEN_LAYOUT_LIST, TITLE_FOR_VIDEO);

            Glide.with(mContext).load(THUMBNAIL_URL).apply(new RequestOptions().override(50,50)).into(jzVideoPlayerStandard.thumbImageView);

Here VIDEO_URL is url for video, TITLE_FOR_VIDEO is a string for video title, THUMBNAIL_URL is url for showing thumbnail for video.

You also need to override backpress and pause of your Acitivity displaying video:

    @Override
    public void onBackPressed() {
        if (JZVideoPlayer.backPress()) {
           return;
        }
        JZVideoPlayer.releaseAllVideos();
      super.onBackPressed();
    }
    @Override
    protected void onPause() {
        super.onPause();
        JZVideoPlayer.releaseAllVideos();
    }

Now for the video cache to work, add the following code to your projects Application class:

public class MyApplication extends Application {
 
    private HttpProxyCacheServer proxy;

    public static HttpProxyCacheServer getProxy(Context context) {
        MyApplication app = (MyApplication) context.getApplicationContext();
        return app.proxy == null ? (app.proxy = app.newProxy()) : app.proxy;
    }

    private HttpProxyCacheServer newProxy() {
        return new HttpProxyCacheServer(this);
    }
}

Thats it! Now your video should work as the screenshots shown above.

440 total views, 10 views today

Whatsapp like full screen imageview Android with zoom, blur bg in popup window Example Tutorial

In this tutorial we will learn to show an image in fullscreen mode with one click in android popupwindow from any activity or fragment.

In this example we will see a contact profile where when we click on user’s profile it should show in fullscreen mode with zoom enabled. We will directly implement the code for OnClick() of small thumbnail imageview to be shown in fullscreen.

Sample Usage demo:

              new PhotoFullPopupWindow(context, R.layout.popup_photo_full, yourImageView, URL, null);
              

Where parameters in the above method are as follows:
1) context -> context of your activity, fragment, application etc..
2) R.layout.popup_photo_full -> this will be created below in this tutorial.
3) yourImageView-> simply pass your thumbnail imageview
4) URL-> Url of full resolution image.
5) null -> Its the bitmap to be shown in fullscreen, its optional. If you provide the bitmap, then URL will be ignored! and bitmap will be loaded in fullscreen.

Call the above code in onClick Listener of your imageView to be Shown in full screen as shown below:

  yourImageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // Code to show image in full screen:
                new PhotoFullPopupWindow(context, R.layout.popup_photo_full, view, URL, null);
                
            }
        });

Steps to achieve this:
1) We will create a popup windows with custom layout for showing image in full screen.
2) An android library for loading images from local Uri or web URL into imageview called Glide.
3) Android Image Zooming library called PhotoView for zoom effect on gesture like pinch to zoom, swipe , double tap etc.
4) Android Palette Library for picking colour from image.

Setting Up Libraries
Add the following dependencies to your app level build.gradle file:


dependencies {
    compile 'com.github.chrisbanes:PhotoView:2.1.3'

    compile 'com.github.bumptech.glide:glide:4.2.0'
    annotationProcessor 'com.github.bumptech.glide:compiler:4.2.0'

    compile 'com.android.support:palette-v7:26.1.0'
 } 

Now sync your project.
In order to use Glide Library in single line we need to create a standard java class required by Glide. Simply create a new java class in root package of your project. For example: if your app package name is com.store.yourapp then create the following class inside the package com.store.yourapp with name MyAppGlideModule.java


import com.bumptech.glide.annotation.GlideModule;
import com.bumptech.glide.module.AppGlideModule;
@GlideModule
public final class MyAppGlideModule extends AppGlideModule {
}

Now rebuild your project in Android Studio from Build->Rebuild Project.
After building your project only you will be able to access GlideApp.

We have finished setting up libraries.

Start Coding..

Create the layout file for popupWindow called popup_photo_full.xml in your res/layout directory with following code:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/rl_custom_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_margin="20dp"
    android:background="@android:color/black">


    <com.github.chrisbanes.photoview.PhotoView
        android:id="@+id/image"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <ImageButton
        android:id="@+id/ib_close"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:background="@null"
        android:elevation="5dp"
        android:padding="3dp"
        android:src="@android:drawable/ic_menu_close_clear_cancel"
        app:srcCompat="@android:drawable/ic_menu_close_clear_cancel" />

    <ProgressBar
        android:id="@+id/loading"
        style="?android:attr/progressBarStyle"
        android:layout_width="wrap_content"
        android:elevation="10dp"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true" />


</RelativeLayout>

We have created views for
1) ImageButton for close button of popupWindow,
2) PhotoView for showing fullscreen image
3) ProgressBar for showing loading progress while image is loaded.
4) We will use the root layout i.e RelativeLayout of this layout for showing blurred background as shown in whatsapp profile picture after cropping.

Now create a java class for popupWindow with name PhotoFullPopupWindow.java as below:

public class PhotoFullPopupWindow extends PopupWindow {

    View view;
    Context mContext;
    PhotoView photoView;
    ProgressBar loading;
    ViewGroup parent;
    private static PhotoFullPopupWindow instance = null;



    public PhotoFullPopupWindow(Context ctx, int layout, View v, String imageUrl, Bitmap bitmap) {
        super(((LayoutInflater) ctx.getSystemService(LAYOUT_INFLATER_SERVICE)).inflate( R.layout.popup_photo_full, null), ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT);

        if (Build.VERSION.SDK_INT >= 21) {
            setElevation(5.0f);
        }
        this.mContext = ctx;
        this.view = getContentView();
        ImageButton closeButton = (ImageButton) this.view.findViewById(R.id.ib_close);
        setOutsideTouchable(true);

        setFocusable(true);
        // Set a click listener for the popup window close button
        closeButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // Dismiss the popup window
                dismiss();
            }
        });
        //---------Begin customising this popup--------------------

        photoView = (PhotoView) view.findViewById(R.id.image);
        loading = (ProgressBar) view.findViewById(R.id.loading);
        photoView.setMaximumScale(6);
        parent = (ViewGroup) photoView.getParent();
        // ImageUtils.setZoomable(imageView);
        //----------------------------
        if (bitmap != null) {
            loading.setVisibility(View.GONE);
            if (Build.VERSION.SDK_INT >= 16) {
                parent.setBackground(new BitmapDrawable(mContext.getResources(), Constants.fastblur(Bitmap.createScaledBitmap(bitmap, 50, 50, true))));// ));
            } else {
                onPalette(Palette.from(bitmap).generate());

            }
            photoView.setImageBitmap(bitmap);
        } else {
            loading.setIndeterminate(true);
            loading.setVisibility(View.VISIBLE);
            GlideApp.with(ctx) .asBitmap()
                    .load(imageUrl)

                    .error(R.drawable.no_image)
                    .listener(new RequestListener<Bitmap>() {
                                  @Override
                                  public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Bitmap> target, boolean isFirstResource) {
                                      loading.setIndeterminate(false);
                                      loading.setBackgroundColor(Color.LTGRAY);
                                      return false;
                                  }

                                  @Override
                                  public boolean onResourceReady(Bitmap resource, Object model, Target<Bitmap> target, DataSource dataSource, boolean isFirstResource) {
                                      if (Build.VERSION.SDK_INT >= 16) {
                                          parent.setBackground(new BitmapDrawable(mContext.getResources(), Constants.fastblur(Bitmap.createScaledBitmap(resource, 50, 50, true))));// ));
                                      } else {
                                          onPalette(Palette.from(resource).generate());

                                      }
                                      photoView.setImageBitmap(resource);

                                      loading.setVisibility(View.GONE);
                                      return false;
                                  }
                              })



                    .diskCacheStrategy(DiskCacheStrategy.ALL)
                    .into(photoView);

            showAtLocation(v, Gravity.CENTER, 0, 0);
        }
        //------------------------------

    }

    public void onPalette(Palette palette) {
        if (null != palette) {
            ViewGroup parent = (ViewGroup) photoView.getParent().getParent();
            parent.setBackgroundColor(palette.getDarkVibrantColor(Color.GRAY));
        }
    }

}

In this above java file we have used a static method fastblur() from Constants.java, Lets create this file below.
Constants.java:


public class Constants {

    private static final float BITMAP_SCALE = 0.4f;
    private static final int BLUR_RADIUS = 8;

    public static Bitmap fastblur(Bitmap sentBitmap) {
        float scale = BITMAP_SCALE;
        int radius = BLUR_RADIUS;
        int width = Math.round(sentBitmap.getWidth() * scale);
        int height = Math.round(sentBitmap.getHeight() * scale);
        sentBitmap = Bitmap.createScaledBitmap(sentBitmap, width, height, false);

        Bitmap bitmap = sentBitmap.copy(sentBitmap.getConfig(), true);

        if (radius < 1) {
            return (null);
        }

        int w = bitmap.getWidth();
        int h = bitmap.getHeight();

        int[] pix = new int[w * h];
        Log.e("pix", w + " " + h + " " + pix.length);
        bitmap.getPixels(pix, 0, w, 0, 0, w, h);

        int wm = w - 1;
        int hm = h - 1;
        int wh = w * h;
        int div = radius + radius + 1;

        int r[] = new int[wh];
        int g[] = new int[wh];
        int b[] = new int[wh];
        int rsum, gsum, bsum, x, y, i, p, yp, yi, yw;
        int vmin[] = new int[Math.max(w, h)];

        int divsum = (div + 1) >> 1;
        divsum *= divsum;
        int dv[] = new int[256 * divsum];
        for (i = 0; i < 256 * divsum; i++) {
            dv[i] = (i / divsum);
        }

        yw = yi = 0;

        int[][] stack = new int[div][3];
        int stackpointer;
        int stackstart;
        int[] sir;
        int rbs;
        int r1 = radius + 1;
        int routsum, goutsum, boutsum;
        int rinsum, ginsum, binsum;

        for (y = 0; y < h; y++) {
            rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
            for (i = -radius; i <= radius; i++) {
                p = pix[yi + Math.min(wm, Math.max(i, 0))];
                sir = stack[i + radius];
                sir[0] = (p & 0xff0000) >> 16;
                sir[1] = (p & 0x00ff00) >> 8;
                sir[2] = (p & 0x0000ff);
                rbs = r1 - Math.abs(i);
                rsum += sir[0] * rbs;
                gsum += sir[1] * rbs;
                bsum += sir[2] * rbs;
                if (i > 0) {
                    rinsum += sir[0];
                    ginsum += sir[1];
                    binsum += sir[2];
                } else {
                    routsum += sir[0];
                    goutsum += sir[1];
                    boutsum += sir[2];
                }
            }
            stackpointer = radius;

            for (x = 0; x < w; x++) {

                r[yi] = dv[rsum];
                g[yi] = dv[gsum];
                b[yi] = dv[bsum];

                rsum -= routsum;
                gsum -= goutsum;
                bsum -= boutsum;

                stackstart = stackpointer - radius + div;
                sir = stack[stackstart % div];

                routsum -= sir[0];
                goutsum -= sir[1];
                boutsum -= sir[2];

                if (y == 0) {
                    vmin[x] = Math.min(x + radius + 1, wm);
                }
                p = pix[yw + vmin[x]];

                sir[0] = (p & 0xff0000) >> 16;
                sir[1] = (p & 0x00ff00) >> 8;
                sir[2] = (p & 0x0000ff);

                rinsum += sir[0];
                ginsum += sir[1];
                binsum += sir[2];

                rsum += rinsum;
                gsum += ginsum;
                bsum += binsum;

                stackpointer = (stackpointer + 1) % div;
                sir = stack[(stackpointer) % div];

                routsum += sir[0];
                goutsum += sir[1];
                boutsum += sir[2];

                rinsum -= sir[0];
                ginsum -= sir[1];
                binsum -= sir[2];

                yi++;
            }
            yw += w;
        }
        for (x = 0; x < w; x++) {
            rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
            yp = -radius * w;
            for (i = -radius; i <= radius; i++) {
                yi = Math.max(0, yp) + x;

                sir = stack[i + radius];

                sir[0] = r[yi];
                sir[1] = g[yi];
                sir[2] = b[yi];

                rbs = r1 - Math.abs(i);

                rsum += r[yi] * rbs;
                gsum += g[yi] * rbs;
                bsum += b[yi] * rbs;

                if (i > 0) {
                    rinsum += sir[0];
                    ginsum += sir[1];
                    binsum += sir[2];
                } else {
                    routsum += sir[0];
                    goutsum += sir[1];
                    boutsum += sir[2];
                }

                if (i < hm) {
                    yp += w;
                }
            }
            yi = x;
            stackpointer = radius;
            for (y = 0; y < h; y++) {
                // Preserve alpha channel: ( 0xff000000 & pix[yi] )
                pix[yi] = (0xff000000 & pix[yi]) | (dv[rsum] << 16) | (dv[gsum] << 8) | dv[bsum];

                rsum -= routsum;
                gsum -= goutsum;
                bsum -= boutsum;

                stackstart = stackpointer - radius + div;
                sir = stack[stackstart % div];

                routsum -= sir[0];
                goutsum -= sir[1];
                boutsum -= sir[2];

                if (x == 0) {
                    vmin[y] = Math.min(y + r1, hm) * w;
                }
                p = x + vmin[y];

                sir[0] = r[p];
                sir[1] = g[p];
                sir[2] = b[p];

                rinsum += sir[0];
                ginsum += sir[1];
                binsum += sir[2];

                rsum += rinsum;
                gsum += ginsum;
                bsum += binsum;

                stackpointer = (stackpointer + 1) % div;
                sir = stack[stackpointer];

                routsum += sir[0];
                goutsum += sir[1];
                boutsum += sir[2];

                rinsum -= sir[0];
                ginsum -= sir[1];
                binsum -= sir[2];

                yi += w;
            }
        }

        Log.e("pix", w + " " + h + " " + pix.length);
        bitmap.setPixels(pix, 0, w, 0, 0, w, h);

        return (bitmap);

    }
}

We have successfully completed the coding part now!. Just check the Usage demo at the beginning of this tutorial now!

734 total views, 24 views today

Quick Android Form/EditText Validation Library Sample Example Tutorial

In this tutorial we will use a library for quick validation of OTP, Email, Phone, Name, Empty String, Regex etc. entered in an EditText of Android layout file. When the validation fails, a small error message will be shown near the Invalid EditText itself like a tooltip bubble along with a red error exclamation mark inside the EditText. Look at the following screenshots showing the implementations of some of the form validations like email, mobile number (10 digit), empty field, alphabet validations for name etc :

                     
Step-1) We need to add the library to for called android edittext validator.
Add the following line in dependencies section of your project’s app level build.gradle file and Sync the project.

    compile 'com.andreabaccega:android-edittext-validator:1.3.+'

Step-2) The library has been added. So we just need to use it now to validate any existing layouts or create new layout with editText validation. If you already have created your layout then you can make small changes to validate your existing layout. Lets have a look at an example below:
For example, if you have a layout files containing editTexts like this:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    
    android:orientation="vertical" 
    android:layout_width="match_parent"
    android:layout_height="match_parent">


    <EditText
        android:id="@+id/email_fet"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:ems="10"
        android:hint="email" />
</LinearLayout>

Then make the changes to replace it with this one for email validation:

<?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"
    xmlns:whatever="http://schemas.android.com/apk/res-auto"

    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <com.andreabaccega.widget.FormEditText
        android:id="@+id/email_fet"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:ems="10"
        android:inputType="textEmailAddress"
        android:hint="email"

        app:emptyAllowed="true"
        whatever:emptyErrorString="Empty String not allowed"
        whatever:testErrorString="Enter a valid email"
        whatever:testType="email" />
</LinearLayout>

The changes we have made can be visualised as green boxes in the below image:

We have added below lines in the rootView of the layout file:

 xmlns:app="http://schemas.android.com/apk/res-auto"
 xmlns:whatever="http://schemas.android.com/apk/res-auto"

and the replaced the EditText View with com.andreabaccega.widget.FormEditText.
Explanation of the attributes:

app:emptyAllowed="true"

Its used for allowing empty string or not.

whatever:emptyErrorString="Empty String not allowed"

Its used for showing error message when editText is left empty and is validated. It is only called when app:emptyAllowed is set false.

whatever:testErrorString="Enter a valid email"

This is used for showing error message when the text entered in the Editext is valided for the testType provided below.

whatever:testType="email"

The test type defines the validation type for example phone,email,alpha etc..
There are following other whatever:testTypes values that can be used using this library for validation:

alpha, alphaNumeric, creditCard, custom, date, domainName, email, floatNumericRange, ipAddress, nocheck, numeric, numericRange, personFullName, personName, phone, regexp, webUrl

Step-3) Now we need to invoke the validation on a submit button’s OnClickListener using java code.
You can access the FormEditText views in your Activity’s OnCreate() or Fragment’s OnViewCreated() similar to any other view as shown below:

FormEditText  firstname = (FormEditText) view.findViewById(R.id.firstname_fet);
FormEditText  email = (FormEditText) view.findViewById(R.id.email_fet);
FormEditText  mobile = (FormEditText) view.findViewById(R.id.mobile_fet);

Now call the below method to check for validation during a submit call in any of your form’s submit button’s OnClickListener:

 private boolean validate() {
        FormEditText[] allFields={firstname, mobile, email};
        boolean allValid = true;
        for (FormEditText field : allFields) {
            allValid = field.testValidity() && allValid;
        }
        return allValid;
    }

If everything is valid, this method will return true and you can proceed with submitting the form details to your server. Otherwise the tooltip like error messages will and exclamation signs will be shown for invalid inputs.

456 total views, 7 views today

Android Profile Activity Layout Sample Example Tutorial

android profile
 

In this tutorial we will simply create a layout file for showing profile information of a user or contact in your android application. This layout can be used in any activity or fragment. We will created a profile imageview in a circular shape or image cropped in rounded shape using a library which we will include in build.gradle file.

Add following to your dependencies section of app level build.gradle file and Sync the project.

    compile 'de.hdodenhof:circleimageview:2.1.0'

 
Copy the given contents of below file in any layout of your activity or fragment.

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

    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/layout">


        <ImageView
            android:id="@+id/header_cover_image"
            android:layout_width="match_parent"
            android:layout_height="150dp"
            android:background="?attr/selectableItemBackgroundBorderless"
            android:scaleType="centerCrop"

            android:src="@drawable/nav_menu_header_bg"
            app:srcCompat="@drawable/nav_menu_header_bg" />

        <de.hdodenhof.circleimageview.CircleImageView
            xmlns:app="http://schemas.android.com/apk/res-auto"

            android:clickable="true"
            app:civ_border_width="3dp"
            app:civ_border_color="#FFFFFFFF"

            android:id="@+id/profile"
            android:layout_width="200dp"
            android:layout_height="200dp"
            android:layout_below="@+id/header_cover_image"
            android:layout_centerHorizontal="true"
            android:layout_marginTop="-130dp"
            android:elevation="5dp"
            android:padding="20dp"
            android:scaleType="centerCrop"
            android:src="@drawable/man" />

        <RelativeLayout
            android:id="@+id/profile_layout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@+id/header_cover_image"
            android:background="#ebca0707"
            android:elevation="4dp"
            android:paddingBottom="24dp">


            <ImageView
                android:id="@+id/edit"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentRight="true"
                android:layout_marginLeft="16dp"
                android:layout_marginRight="16dp"
                android:layout_marginTop="16dp"
                android:clickable="true"

                android:src="@android:drawable/ic_menu_edit" />

            <TextView
                android:id="@+id/name"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerHorizontal="true"
                android:layout_marginTop="70dp"
                android:text="Laxman Marothiya"
                android:textColor="#fff"
                android:textSize="24sp"
                android:textStyle="bold" />

            <TextView
                android:id="@+id/location"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_below="@+id/designation"
                android:layout_centerHorizontal="true"
                android:layout_marginTop="10dp"
                android:text="Surat"
                android:textColor="#fff"
                android:textSize="16sp" />

            <TextView
                android:id="@+id/designation"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_below="@+id/name"
                android:layout_centerHorizontal="true"
                android:layout_marginTop="10dp"
                android:text="(Adhyaksh)"
                android:textColor="#fff"
                android:textSize="18sp" />
        </RelativeLayout>


        <android.support.constraint.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_below="@+id/profile_layout"
            android:layout_margin="5dp"
            android:layout_marginTop="5dp"
            android:background="#fff"
            android:elevation="4dp"
            android:orientation="vertical"
            android:paddingTop="20dp"
            android:paddingBottom="20dp"
            android:paddingRight="5dp"
            android:paddingLeft="5dp"

            >

            <TextView
                android:id="@+id/textView5"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="5dp"
                android:clickable="true"
                android:text="Education: "
                android:textStyle="bold"
                android:layout_marginLeft="25dp"
                app:layout_constraintLeft_toLeftOf="parent"
                android:layout_marginTop="8dp"
                app:layout_constraintTop_toBottomOf="@+id/textView10" />

            <TextView
                android:id="@+id/textView7"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="5dp"
                android:clickable="true"
                android:text="Work: "
                android:textStyle="bold"
                android:layout_marginLeft="8dp"
                app:layout_constraintLeft_toLeftOf="parent"
                android:layout_marginTop="8dp"
                app:layout_constraintTop_toBottomOf="@+id/textView5" />

            <TextView
                android:id="@+id/textView16"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="5dp"
                android:clickable="true"
                android:text="DOB: "
                android:textStyle="bold"
                app:layout_constraintTop_toBottomOf="@+id/textView15"
                android:layout_marginLeft="8dp"
                app:layout_constraintLeft_toLeftOf="parent" />

            <TextView
                android:id="@+id/textView15"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="4dp"
                android:clickable="true"
                android:text="Marriage:"
                android:textStyle="bold"
                app:layout_constraintTop_toBottomOf="@+id/textView11"
                android:layout_marginLeft="8dp"
                app:layout_constraintLeft_toLeftOf="parent" />

            <TextView
                android:id="@+id/textView11"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:clickable="true"
                android:text="Gender: "
                android:textStyle="bold"

                android:layout_margin="5dp"
                android:layout_marginLeft="10dp"
                app:layout_constraintLeft_toLeftOf="parent"
                android:layout_marginTop="8dp"
                app:layout_constraintTop_toBottomOf="@+id/textView22" />

            <TextView
                android:id="@+id/textView10"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="5dp"
                android:layout_marginLeft="8dp"
                android:layout_marginTop="8dp"
                android:clickable="true"
                android:text="Blood Group: "
                android:textStyle="bold"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintTop_toTopOf="parent" />

            <TextView
                android:id="@+id/blood_group"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="5dp"
                android:clickable="true"
                android:text="O+"
                app:layout_constraintLeft_toRightOf="@+id/textView10"
                android:layout_marginLeft="8dp"
                app:layout_constraintTop_toTopOf="parent"
                android:layout_marginTop="8dp" />

            <TextView
                android:id="@+id/dob"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:clickable="true"
                android:text="01/01/2017"
                android:layout_margin="5dp"
                android:layout_marginLeft="8dp"
                android:layout_marginTop="8dp"
                app:layout_constraintTop_toBottomOf="@+id/marriage"
                app:layout_constraintLeft_toRightOf="@+id/textView16" />

            <TextView
                android:id="@+id/marriage"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="8dp"
                android:layout_marginTop="5dp"
                android:clickable="true"
                android:text="Married"
                app:layout_constraintLeft_toRightOf="@+id/textView15"
                app:layout_constraintTop_toBottomOf="@+id/gender" />

            <TextView
                android:id="@+id/gender"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:clickable="true"
                android:text="Male"
                app:layout_constraintLeft_toRightOf="@+id/textView11"
                android:layout_margin="5dp"
                android:layout_marginLeft="5dp"
                android:layout_marginTop="8dp"
                app:layout_constraintTop_toBottomOf="@+id/mobileNumber" />

            <TextView
                android:id="@+id/occupation"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="5dp"
                android:layout_marginLeft="5dp"
                android:layout_marginTop="8dp"
                android:clickable="true"
                android:text="Business"
                app:layout_constraintLeft_toRightOf="@+id/textView7"
                app:layout_constraintTop_toBottomOf="@+id/textView5" />

            <TextView
                android:id="@+id/mobileNumber"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:clickable="true"
                android:text="9876543210"
                android:layout_margin="5dp"
                android:layout_marginLeft="5dp"
                android:layout_marginTop="8dp"
                app:layout_constraintTop_toBottomOf="@+id/occupation"
                app:layout_constraintLeft_toRightOf="@+id/textView22" />

            <TextView
                android:id="@+id/approved_by"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:clickable="true"
                android:text="ABCD XYZ"
                app:layout_constraintLeft_toRightOf="@+id/textView26"
                android:layout_marginLeft="8dp"
                android:layout_marginTop="8dp"
                app:layout_constraintTop_toBottomOf="@+id/email" />

            <TextView
                android:id="@+id/email"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:clickable="true"
                android:text="marothiatechs@gmail.com"
                app:layout_constraintLeft_toRightOf="@+id/textView27"
                android:layout_marginLeft="8dp"
                android:layout_marginTop="0dp"
                app:layout_constraintTop_toBottomOf="@+id/dob" />

            <TextView
                android:id="@+id/textView26"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:clickable="true"
                android:text="Approved by: "
                android:textStyle="bold"

                android:layout_marginLeft="8dp"
                android:layout_marginTop="5dp"
                app:layout_constraintTop_toBottomOf="@+id/textView27"
                app:layout_constraintLeft_toLeftOf="parent" />

            <TextView
                android:id="@+id/textView27"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:clickable="true"
                android:text="Email: "
                android:textStyle="bold"
                android:layout_marginTop="5dp"
                app:layout_constraintTop_toBottomOf="@+id/textView16"
                android:layout_marginLeft="8dp"
                app:layout_constraintLeft_toLeftOf="parent" />

            <TextView
                android:id="@+id/textView22"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:clickable="true"
                android:text="Mobile: "
                android:textStyle="bold"
                android:layout_margin="5dp"
                android:layout_marginLeft="8dp"
                android:layout_marginTop="5dp"
                app:layout_constraintTop_toBottomOf="@+id/textView7"
                app:layout_constraintLeft_toLeftOf="parent" />

            <TextView
                android:id="@+id/education"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="5dp"
                android:clickable="true"
                android:text="B.Tech"
                android:layout_marginTop="8dp"
                app:layout_constraintTop_toBottomOf="@+id/textView10"
                app:layout_constraintLeft_toRightOf="@+id/textView5"
                android:layout_marginLeft="8dp" />

        </android.support.constraint.ConstraintLayout>
    </RelativeLayout>
</ScrollView>

Add the following files to your projects res/drawable directory:

man.jpg

nav_menu_header_bg.png

Thats it! Just run your activity or fragment to test the about layout.

1,116 total views, 20 views today

Shoot Girl’s Fruits : Archery – non stop action game on Android

shoot girls fruits archery shoot girls fruits archery shoot girls fruits archery shoot girls fruits archery

 

 

 

 

 

 

 

 

 

DOWNLOAD: https://play.google.com/store/apps/details?id=com.marothiatechs.archery

Shoot Girl’s Fruits : Archery is a sequel game for Shoot Girl’s Fruits : Gulel.
Gulel i.e. Slingshot is replaced by Bow and Arrow in this game. So you will use your archery skills instead of stone shooting by a slingshot.

This time you have unlimited arrows for your archer. There are many attacker birds holding canons or mortars. Shoot them too to survive the round.

You need to shoot down fruits or the birds and make sure not to let the birds take away three fruits.

There are different types of arrows available:
Triple Arrows : Three shots in a go.
Row Arrows : Three shots one by one
Strong Arrows : One shot kill arrow.

You can submit your score to compete with your friends for high score.

If you feel like shooting everything in sight then enjoy shooting the birds as well but be careful as you will lose your girl’s fruit if the bird gets hit!
DOWNLOAD: https://play.google.com/store/apps/details?id=com.marothiatechs.archery

935 total views, 2 views today

Purge! An innovative puzzle game.

    

This is a puzzle game with a new and original concept of matching same two numbers or colors in a row of column. You need to cross a line on any two blocks of same number or color. The other block between the two blocks will be eliminated. So the goal is to cut all the cells of the board such that not a single cell is left.

The game is available in three modes:

1) Packages Mode: Many different packages containing hundreds of levels in each of them.
2) Time Trial Mode: In this mode you have to solve the boards as fast as possible. There are two type of games within this mode:
-Timer Mode: Solve as many boards as possible in given time frame.
– Boards Mode: Solve fixed number of boards in minimum time.
You can choose the grid size of your choice in this mode. Grid sizes are available from 3×3 to 9×9.
3) Daily Challenge: Solve an exciting puzzle of challenging difficulty every day and earn some hammers.

Hammers: This is a power in the game which can be used to break any line draw during the gameplay i.e. you can break any line whenever you want using a hammer. Just double tap on the line to use a hammer.

This game is brought to you by the developers of Shoot Girl’s Fruits : Gulel

DOWNLOAD: http://onelink.to/purge

714 total views, 2 views today

Encrypt String in PHP and Decrypt in JAVA Sample Example Tutorial

In this tutorial, We will learn about how to encrypt a string data using RSA algorithm through PHP and decrypt the same using Java project.

We need phpseclib library for encrypting the data. This can be downloaded from :

https://github.com/phpseclib/phpseclib/tree/master/phpseclib

Now lets create php scripts to encrypt a simple string “Hello World!”.

We need two .php files for this :

  1. keypair.php – for generating public key & private key required by RSA Algorithm for encryption.
  2. encrypt.php – for encrypting the string “Hello world!”.

Now copy the below code into keypair.php:

<?php

set_time_limit(0);
if( file_exists('private.key') )
{
    echo base64_encode(file_get_contents('private.key'));
}
else
{
    include('Crypt/RSA.php');

    $rsa = new Crypt_RSA();
    $rsa->setHash('sha1');
    $rsa->setMGFHash('sha1');
    $rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_OAEP);
    $rsa->setPrivateKeyFormat(CRYPT_RSA_PRIVATE_FORMAT_PKCS1);
    $rsa->setPublicKeyFormat(CRYPT_RSA_PUBLIC_FORMAT_PKCS1);

    $res = $rsa->createKey(1024);

    $privateKey = $res['privatekey'];
    $publicKey  = $res['publickey'];

    file_put_contents('public.key', $publicKey);
    file_put_contents('private.key', $privateKey);

    echo base64_encode($privateKey);
}

?>

And the code for encrypt.php is as follows:

<?php
    include('Crypt/RSA.php');
    set_time_limit(0);

    $rsa = new Crypt_RSA();
    $rsa->setHash('sha1');
    $rsa->setMGFHash('sha1');
    $rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_OAEP);

    $rsa->loadKey(file_get_contents('public.key')); // public key

    $plaintext  = 'Hello World!';
    $ciphertext = $rsa->encrypt($plaintext);
    $md5        = md5($ciphertext);
    file_put_contents('md5.txt', $md5);
    file_put_contents('encrypted.txt', base64_encode($ciphertext));

    echo base64_encode($ciphertext);

?>

NOTE: If there is an error on include statement, Simply copy the whole directory structure with files from phpseclib library to resolve: include(‘Crypt/RSA.php’)

Now we are done for the (server side) PHP part of code.

I am using cpanel on a hosting platform and my project structure for php side is as follows:

string encrypt php & java

string encrypt php & java

Now lets work on the Java Part:

We need two libraries for our java project to decrypt the string we encrypt in encrypt.php:

  1. bcprov.jar
  2. sun.misc.BASE64Decoder.jar

Download this zip which contains both these files: libs

Create a new java project in Eclipse (I have used eclipse IDE for this java project).  Now extract the libs.zip and copy the libs folder in root directory of your java project. Add both the jar files to build path of your java project.

 

Now create a new file Main.java with following code:

package testEncryption;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.StringReader;
import java.net.URL;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.Security;

import javax.crypto.Cipher;

import org.bouncycastle.openssl.PEMReader;

import Decoder.BASE64Decoder;


public class Main {

    /**
     * @param args
     */
    public static void main(String[] args)
    {
        Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());

        try {
            BASE64Decoder decoder   = new BASE64Decoder();
            
            String b64PrivateKey    = getContents("http://www.yourdoamin.com/pathto/keypair.php").trim();
            String b64EncryptedStr  = getContents("http://www.yourdoamin.com/pathto/encrypt.php").trim();
         
            System.out.println("PrivateKey (b64): " + b64PrivateKey);
            System.out.println(" Encrypted (b64): " + b64EncryptedStr);

            byte[] decodedKey           = decoder.decodeBuffer(b64PrivateKey);
            byte[] decodedStr           = decoder.decodeBuffer(b64EncryptedStr);
            PrivateKey privateKey       = strToPrivateKey(new String(decodedKey));

            Cipher cipher               = Cipher.getInstance("RSA/None/OAEPWithSHA1AndMGF1Padding", "BC");
            cipher.init(Cipher.DECRYPT_MODE, privateKey);


            byte[] plainText            = cipher.doFinal(decodedStr);

            System.out.println("         Message: " + new String(plainText));
        }
        catch( Exception e )
        {
            System.out.println("           Error: " + e.getMessage());
        }

    }

    public static String getContents(String url)
    {
        try {
            String result = "";
            String line;
            URL u = new URL(url);
            DataInputStream theHTML = new DataInputStream(u.openStream());
            while ((line = theHTML.readLine()) != null)
                result = result + "\n" + line;

            return result;
        }
        catch(Exception e){}

        return "";
    }

    public static PrivateKey strToPrivateKey(String s)
    {
        try {
            BufferedReader br   = new BufferedReader( new StringReader(s) );
            PEMReader pr        = new PEMReader(br);
            KeyPair kp          = (KeyPair)pr.readObject();
            pr.close();
            return kp.getPrivate();
        }
        catch( Exception e )
        {

        }

        return null;
    }
}

NOTE: Please provide the URLs for the PHP files we just created in this tutorial in Main.java file.

My project structure for java project:
rsa decryption java

Now the Main.java file as Java Application and you will see that
hello world!
is printed on the console!

We have successfully encrypted and decrypted the string between PHP and JAVA!

2,154 total views, 5 views today

Stone Pillar – A game about stacking stones

You will love this game if you have ever played with mountain stones to create balanced structures.
Stack stones wherever you want by simply touching the screen. Its just your creativity that will decide the structure of your building.
– Pile Up the blocks as high as you can.
– Complete Levels in classic mode.
– Arrange stones to create highest tower of balanced wall.
– Simple & Beautiful graphics designed
– Compete for the best score in the world.
– Share beautiful buildings constructed..

DOWNLOAD FROM GOOGLE PLAY STORE

 

2,461 total views, 3 views today

How to use Jasper Reports in JavaFX 8 – Sample Example Tutorial

Jasper Reports are used for showing information that need to be printed or saved as document file.

Use Cases:

– For printing Reciepts
– Bill/ Invoice
– Detailed Reports
– and so on..

If you have already developed some Java application/ Software using JavaFx and now need to print some data from the software, then this is the tutorial for you.

Jasper Reports are designed in the form of .jrxml files similar to .fxml files of javaFX.
We need to access these .jrxml files in java class and pass the data to be filled in the Jasper report using Java Objects(List) or through an SQL query.

Steps required to achieve this:

1) Install Jaspersoft Studio for creating .jrxml file using drag and drop.
2) Get Jasper Reports Library .jar files to be added in libs folder of your JavaFX project.
4) Design .jrxml file using JasperSoft Studio.
3) Write Java code to show .jrxml file as Report.

Install Jaspersoft Studio

You can either download Jaspersoft studio plugin for eclipse OR download Standalone Jasper soft Studio. We just need the .jrxml report files designed using either of the above.

1) Eclipse Plugin: Search JasperSoft in Eclipse MarketPlace and install the latest release.
jaspersoft studio javafx download plugin

2) Standalone JasperSoft Studio: Download


Get Jasper Reports Library

We need jasper library for java project. To get the library files. Download the Jasper Reports Library from here.

jasper Reports Library for Java download

Download the “jasperreports-6.3.1-project.zip” in the above screenshot.

After extracting the zip file you will get the project folder in which “dist” folder is of our concern.
jasper dist folder
There are 3 .jar files in this dist folder. Add all the three files to the libs folder of your javaFX project.
But these 3 jar files are not enough. There are many other dependencies require by Jasper Reports which should be again added to the libs folder of your project.

The Jasper Reports Project uses Apache Ant, Apache Ivy – as the dependency Manager. We need to get the Apache Ant/Ivy for getting the remaing .jar files.

We have to Download Apache Ant and run the commands on Jasper Reports Project’s root directory using Terminal/Command Prompt.

Download Apache Ivy, Apache Ant from here:
Ant
(You can alway get the latest releases by searching on Google)

Extract the downloaded .zip file and copy the folder ant anywhere near the Jasper Reports Project folder.
Directory structure of ant and jasper project

Now run the following command in the root directory of the Jasper Reports project:

java -jar ../ant/ant-launcher.jar retrievelibs

Look at the screenshot showing how I ran the above command:

terminal showing ant retrieving Jasper reports library for java

The required dependency .jar files will be downloaded into the dist/libs folder of the JasperReports project.
Copy all the .jar files from this lib folder to the libs folder of your java project.

jasper dependency jar files

NOTE: Add all the jar files to the Build Path of your Java project.
Here is the list of all the jar files that will be added to the libs folder of your JavaFX Project:

  1. ant-1.7.1.jar
  2. antlr-2.7.5.jar
  3. asm-all-4.0.jar
  4. barbecue-1.5-beta1.jar
  5. barcode4j-2.1.jar
  6. batik-anim-1.8.jar
  7. batik-awt-util-1.8.jar
  8. batik-bridge-1.8.jar
  9. batik-css-1.8.jar
  10. batik-dom-1.8.jar
  11. batik-gvt-1.8.jar
  12. batik-svg-dom-1.8.jar
  13. batik-svggen-1.8.jar
  14. batik-util-1.8.jar
  15. bsh-2.0b4.jar
  16. castor-core-1.3.3.jar
  17. castor-xml-1.3.3.jar
  18. commons-beanutils-1.9.0.jar
  19. commons-collections-3.2.2.jar
  20. commons-digester-2.1.jar
  21. commons-javaflow-20160505.jar
  22. commons-lang-2.6.jar
  23. commons-logging-1.1.1.jar
  24. core-3.2.1.jar
  25. ecj-4.3.1.jar
  26. groovy-all-2.4.5.jar
  27. hibernate-core-3.3.2.GA.jar
  28. httpclient-4.3.4.jar
  29. httpcore-4.3.2.jar
  30. icu4j-57.1.jar
  31. itext-2.1.7.js5.jar
  32. jackson-annotations-2.1.4.jar
  33. jackson-core-2.1.4.jar
  34. jackson-databind-2.1.4.jar
  35. jasperreports-6.3.1.jar
  36. jasperreports-fonts-6.3.1.jar
  37. jasperreports-javaflow-6.3.1.jar
  38. jaxen-1.1.1.jar
  39. jcommon-1.0.23.jar
  40. jfreechart-1.0.19.jar
  41. jxl-2.6.10.jar
  42. lucene-analyzers-common-4.5.1.jar
  43. lucene-core-4.5.1.jar
  44. lucene-queryparser-4.5.1.jar
  45. mondrian-3.1.1.12687.jar
  46. olap4j-0.9.7.309-JS-3.jar
  47. persistence-api-1.0.jar
  48. poi-3.10.1.jar
  49. poi-ooxml-3.10.1.jar
  50. rhino-1.7.6.jar
  51. servlet-api-2.4.jar
  52. spring-beans-2.5.jar
  53. spring-core-2.5.jar
  54. velocity-1.7.jar
  55. xalan-2.7.2.jar
  56. xml-apis-ext-1.3.04.jar
  57. xmpcore-5.1.1.jar

Design .jrxml file using JasperSoft Studio.

Open Jasper Studio and create a new Jasper Report as shown below:

Creating new Jasper Report

Now select Blank A4 as the Report Template as shown below:

Jasper Report Template

Choose the name and directory for the jrxml file and at the screen asking for Data Source, select “New Data Adapter – Empty Rows” from the drop down as shown below:

Selecting data source for jasper report

Click Next->Finish to create the jrxml file. Look at the screenshot below:

Jasper new reports

You can download the sample .jrxml file here: Blank_A4.jrxml
Create a folder named data in your java project and Copy the created .jrxml file there.
Now create a java file named PrintReport.java as follows:

package com.marothiatechs.reports;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;

import javax.swing.JFrame;

import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperCompileManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import net.sf.jasperreports.swing.JRViewer;

public class PrintReport extends JFrame {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	public void showReport() throws JRException, ClassNotFoundException, SQLException {

		String reportSrcFile = "data/Blank_A4.jrxml";

		// First, compile jrxml file.
		JasperReport jasperReport = JasperCompileManager.compileReport(reportSrcFile);
		// Fields for report
		HashMap<String, Object> parameters = new HashMap<String, Object>();

		parameters.put("company", "MAROTHIA TECHS");
		parameters.put("receipt_no", "RE101".toString());
		parameters.put("name", "Khushboo");
		parameters.put("amount", "10000");
		parameters.put("receipt_for", "EMI Payment");
		parameters.put("date", "20-12-2016");
		parameters.put("contact", "98763178".toString());

		ArrayList<HashMap<String, Object>> list = new ArrayList<HashMap<String, Object>>();
		list.add(parameters);

		JRBeanCollectionDataSource beanColDataSource = new JRBeanCollectionDataSource(list);
		JasperPrint print = JasperFillManager.fillReport(jasperReport, null, beanColDataSource);
		JRViewer viewer = new JRViewer(print);
		viewer.setOpaque(true);
		viewer.setVisible(true);
		this.add(viewer);
		this.setSize(700, 500);
		this.setVisible(true);
		System.out.print("Done!");

	}

}

Now call the source code for the Main.Java is as follows:

package com.marothiatechs.finance;

import java.sql.SQLException;

import com.marothiatechs.reports.PrintReport;

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import net.sf.jasperreports.engine.JRException;

public class Main extends Application {

	Stage window;
	Scene scene;
	Button button;

	public static void main(String[] args) {
		launch(args);
	}

	@Override
	public void start(Stage primaryStage) throws Exception {
		window = primaryStage;
		window.setTitle("Jasper Report Tutorial");
		button = new Button("Show Receipt");
		button.setOnAction(e -> {
			try {
				// --- Show Jasper Report on click-----
				new PrintReport().showReport();
			} catch (ClassNotFoundException | JRException | SQLException e1) {
				e1.printStackTrace();
			}
		});

		VBox layout = new VBox(10);
		layout.setPadding(new Insets(20, 20, 20, 20));
		layout.getChildren().addAll(button);
		scene = new Scene(layout, 300, 250);
		window.setScene(scene);
		window.show();
	}

}

Now Run the Main.java file as Java Application:
Jasper Report running in JavaFX JFrame

8,665 total views, 26 views today