Wednesday, January 30, 2019

Install Linux Mint 19.1 Tessa - Xfce (64-bit) on VirtuaBox 6/Windows 10

To download Linux Mint, visit https://linuxmint.com/download.php. The current release is 19.1.

This video show steps to download and install Linux Mint 19.1 Tessa - Xfce (64-bit) on Windows 10 with VirtualBox 6.

And then, you are suggested to install Guest Additions, for better performance and functions.



may be interested:
Install OpenJDK on Linux Mint/Ubuntu
Install JetBrains Toolbox App on Linux, and also Android Studio and IntelliJ IDEA (Java IDE)



Tuesday, January 22, 2019

Google + Wikipedia

Announced on 22 January 2019,
Wikimedia Foundation is partnering with Google on a set of initiatives to support a shared commitment of making information more accessible to more people around the world.

Through these partnerships, Google and Wikimedia will be working together to create new and expanded programs to empower editors to create local language content on Wikipedia, as well as developing improved translation tools. To strengthen and support Wikipedia and its mission for generations to come, Google.org will also be contributing $1.1 million to the Wikimedia Foundation and $2 million to the Wikimedia Endowment

Source: Google and Wikimedia Foundation partner to increase knowledge equity online

Monday, January 14, 2019

What is 5G?

What is 5G? | CNBC Explains



Everything You Need to Know About 5G


5G in 2019: The benefits, rollout and challenges at CES 2019

Stable release of Android Studio 3.3 released

Android Studio 3.3 released, with Navigation editor, support Instant Apps in App bundle, as well as build system updates such as lazy task configuration, better debug info when using obsolete APIs, improved incremental Java compilation when using annotation processors, and a preview of the new R8 code shrinker. Also added more granularity in the profiler options and added slow frame highlighting to help debug quicker.

You can download it today from https://developer.android.com/studio/.

Or, if you already installed previous release of Android Studio,  you can simply update to the latest version.

What’s new in Android Studio 3.3

~ Android Developers Blog post Android Studio 3.3


Tuesday, January 1, 2019

Mix using of ImageDecoder and ObjectAnimator

Last posts show how to "Display animated GIF using ImageDecoder" and "Apply PostProcess for ImageDecoder". This example I try to mix using of ImageDecoder and ObjectAnimator, to apply animation on animated GIF.



Modify MainActivity.java
package com.blogspot.android_er.androidimagedecoder;

import android.animation.ObjectAnimator;
import android.animation.TimeInterpolator;
import android.app.Activity;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ImageDecoder;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.PostProcessor;
import android.graphics.drawable.AnimatedImageDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.widget.ImageView;
import android.widget.Toast;

import java.io.IOException;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ImageView imageView1 = findViewById(R.id.gifimage1);
        ImageView imageView2 = findViewById(R.id.gifimage2);

        loadGif(imageView1);
        loadRoundGif(imageView2);

        imageView1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                prepareObjectAnimatorRotate((ImageView)v);
            }
        });

        imageView2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                prepareObjectAnimatorAlpha((ImageView)v);
            }
        });
    }

    PostProcessor myPostProcessor =
            new PostProcessor(){
                @Override
                public int onPostProcess(
                        Canvas canvas) {
                    // This will create rounded corners.
                    Path path = new Path();
                    path.setFillType(Path.FillType.INVERSE_EVEN_ODD);
                    int width = canvas.getWidth();
                    int height = canvas.getHeight();
                    path.addRoundRect(0, 0,
                            width, height, 150, 150,
                            Path.Direction.CW);
                    Paint paint = new Paint();
                    paint.setAntiAlias(true);
                    paint.setColor(Color.TRANSPARENT);
                    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
                    canvas.drawPath(path, paint);
                    return PixelFormat.TRANSLUCENT;
                }
            };


    ImageDecoder.OnHeaderDecodedListener myOnHeaderDecodedListener =
            new ImageDecoder.OnHeaderDecodedListener(){
                @Override
                public void onHeaderDecoded
                        (ImageDecoder decoder,
                         ImageDecoder.ImageInfo info,
                         ImageDecoder.Source source) {
                    decoder.setPostProcessor(myPostProcessor);
                }
            };

    private void loadGif(ImageView iv){

        try {
            ImageDecoder.Source source =
                    ImageDecoder.createSource(getResources(), R.drawable.android_er);

            Drawable drawable = ImageDecoder.decodeDrawable(source);

            iv.setImageDrawable(drawable);

            if (drawable instanceof AnimatedImageDrawable) {
                ((AnimatedImageDrawable) drawable).start();
                Toast.makeText(getApplicationContext(),
                        "loadGif: Animation started",
                        Toast.LENGTH_LONG).show();
            }

        } catch (IOException e) {
            e.printStackTrace();
            Toast.makeText(getApplicationContext(),
                    "loadGif: IOException: \n" + e.getMessage(),
                    Toast.LENGTH_LONG).show();
        }

    }

    private void loadRoundGif(ImageView iv){

        try {
            ImageDecoder.Source source =
                    ImageDecoder.createSource(getResources(), R.drawable.android_er);

            //Drawable drawable = ImageDecoder.decodeDrawable(source);
            Drawable drawable = ImageDecoder.decodeDrawable(source,
                    myOnHeaderDecodedListener);

            iv.setImageDrawable(drawable);

            if (drawable instanceof AnimatedImageDrawable) {
                ((AnimatedImageDrawable) drawable).start();
                Toast.makeText(getApplicationContext(),
                        "loadRoundGif: Animation started",
                        Toast.LENGTH_LONG).show();
            }

        } catch (IOException e) {
            e.printStackTrace();
            Toast.makeText(getApplicationContext(),
                    "loadRoundGif: IOException: \n" + e.getMessage(),
                    Toast.LENGTH_LONG).show();
        }

    }

    private void prepareObjectAnimatorRotate(ImageView image){
        TimeInterpolator timeInterpolator =
                new AccelerateDecelerateInterpolator();
        float propertyStart = 0f;
        float propertyEnd = 360f;
        String propertyName = "rotation";
        ObjectAnimator objectAnimator
                = ObjectAnimator.ofFloat(
                        image, propertyName, propertyStart, propertyEnd);
        objectAnimator.setDuration(5000);
        objectAnimator.setRepeatCount(1);
        objectAnimator.setRepeatMode(ObjectAnimator.REVERSE);
        objectAnimator.setInterpolator(timeInterpolator);
        objectAnimator.start();
    }

    private void prepareObjectAnimatorAlpha(ImageView image){
        TimeInterpolator timeInterpolator =
                new AccelerateDecelerateInterpolator();
        float propertyStart = 1f;
        float propertyEnd = 0f;
        String propertyName = "alpha";
        ObjectAnimator objectAnimator
                = ObjectAnimator.ofFloat(
                        image, propertyName, propertyStart, propertyEnd);
        objectAnimator.setDuration(5000);
        objectAnimator.setRepeatCount(1);
        objectAnimator.setRepeatMode(ObjectAnimator.REVERSE);
        objectAnimator.setInterpolator(timeInterpolator);
        objectAnimator.start();
    }
}


Keep using the layout in last post "Apply PostProcess for ImageDecoder".

If you target to animated GIF and it cannot shown, try to disable hardwareAccelerated, refer to "Display animated GIF using ImageDecoder".


Related old post:
Interpolator effect on ObjectAnimator