Showing posts with label android. Show all posts
Showing posts with label android. Show all posts

Friday, June 17, 2016

How to Convert Drawable to Bitmap in Android




In this tutorial I will explain how to read Drawable from resources as Bitmap and than I will write down some common techniques for processing Bitmaps.


public final static Integer[] imageResIds = new Integer[]{
R.drawable.a, R.drawable.b, R.drawable.c,
R.drawable.d, R.drawable.e, R.drawable.f,
R.drawable.k, R.drawable.l, R.drawable.m};


loadBitmap(imageResIds[index], mImageView);



public void loadBitmap(int resId, ImageView imageView) {
 //Now we have bitmap object from drawable resource. we can scale this bitmap
 //according to device screen density.
    Bitmap bitmap = BitmapFactory.decodeResource(getResources(), data);

}

Note: This method can cause out of memory error.
- If you want to avoid this exception use scaled down version of bitmap in memory.
- Process Bitmaps Off the UI thread (Use Async Task).




Author:
Hammad Tariq
Android Developer




Tuesday, May 24, 2016

Check if your Android app is in foreground or background


Now I have my Own Blog. Follow Link to learn more about Android Development.


In this example I will explain how to check if your Android Application is running in foreground or it is in background.

Note: we do not need to add any permission for this code. we will be using ActivityManager class
and its method getRunningAppProcesses()
getRunningAppProcesses() Returns a list of application processes that are running on the device.

Also I am using AsyncTask because we should not call ActivityManager.getRunningAppProcesses()
from UI thread it will return importance IMPORTANCE_FOREGROUND for your task no matter whether it is actually in the foreground or not.


 private class CheckIfForeground extends AsyncTask<Void, Void, Void> {
    @Override
    protected Void doInBackground(Void... voids) {

        ActivityManager activityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
        List<ActivityManager.RunningAppProcessInfo> appProcesses = activityManager.getRunningAppProcesses();
        for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) {
            if (appProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
                Log.i("Foreground App", appProcess.processName);

                if (mContext.getPackageName().equalsIgnoreCase(appProcess.processName)) {
                    Log.i(Constants.TAG, "foreground true:" + appProcess.processName);
                    foreground = true;
                    // close_app();
                }
            }
        }
        Log.d(Constants.TAG, "foreground value:" + foreground);
        if (foreground) {
            foreground = false;
            close_app();
            Log.i(Constants.TAG, "Close App and start Login Activity:");

        } else {
            //if not foreground
            close_app();
            foreground = false;
            Log.i(Constants.TAG, "Close App");

        }

        return null;
    }
}
and execute AsyncTask like this.
new CheckIfForeground().execute();
Please Note this code is tested on Android Version 5.0.2


Author:
Hammad Tariq
Android Developer

Monday, April 4, 2016

How to Integrate Google Analytics SDK Localytics and Mix Panel to Your Android Application


In this tutorial I will explain how to add google analytics, localytics, mix panle in your Android application using Android Studio.

let's start from Google Analytics:

If you have tried adding google analytics from developers.google and getting Gradle version conflict exceptions and other exceptions then this post will be useful for you. It will follow same steps at official Google documentation but with different versions so you don't get errors.

Step 1: Add INTERNET AND ACCESS_NETWORK_STATE permission in manifest file.
Step 2Add the dependency to your project-level build.gradle:


dependencies {
    classpath 'com.android.tools.build:gradle:1.3.0'

    classpath 'com.google.gms:google-services:1.3.0-beta1'
}

Step 3:  Add the plugin to your app-level build.gradle file

  apply plugin: 'com.google.gms.google-services'

Step 4: Now add below dependency in app-level build,gradle file for google analytics

    compile 'com.google.android.gms:play-services-analytics:8.3.0'

Step 5: Download configuration file from your account. And add it in your project "app" folder.


Thats it :)

Now I will guide how to initialize Google Analytics so you get events at your account when user interact with your application.



Create a new class name GlobalClass and add it in your manifest file in name tag under application.
e.g. <application android:name=".GlobalClass"/>

Your GlobalClass should look like below.


public class GlobalClass extends Application {

    /*.............................................................
    * This class contains Localytics, Mix Panel, and Crash Lytics, and Google Analytics .

    * .............................................................    */

    private Tracker mTracker;
    synchronized public Tracker getDefaultTracker() {
        if (mTracker == null) {
            GoogleAnalytics analytics = GoogleAnalytics.getInstance(this);
            mTracker = analytics.newTracker(R.xml.global_tracker);
        }
        return mTracker;
    }

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



I will guide you how to add screen tracking for google analytics, for localytics and for mix panel at the END :)

Reference: https://developers.google.com/analytics/devguides/collection/android/v4/#activity-or-fragment

Now we will add Localytics :

Step 1: Download Localytics jar file and add it in libs folder inside app folder of your project.

Step 2:  Add your application ID in manifest file like below:
<meta-data    android:name="LOCALYTICS_APP_KEY"
android:value="54beea42876aa84xxxx1fbb-ec8xxx2c-4b1a-11e5-b7b7-xx13x62afxxx" />

Don't forget to change value(app-id) according to yours.

Step 3: Add below code in onCreate() method of GlobalClass.
registerActivityLifecycleCallbacks(
        new LocalyticsActivityLifecycleCallbacks(this));

Thats it :) Localytics has been integrated in your application :) enjoy :)

Now we will add MixPanel API

Step 1: Add dependency in build.gradle file. This will install MixPanel library for your project.

compile "com.mixpanel.android:mixpanel-android:4.6.4"

Step 2: Initialize library in GlobalClass onCreate() method like below.

String projectToken = "6107e97e4xxxxf22cddc822xxxxxxxx";
MixpanelAPI mixpanel = MixpanelAPI.getInstance(this, projectToken);

**Change your project token**

Now we are done with adding Google Analytics, Mix Panel and Localytics integration. Now I will teach you how to track events in your Android Application.

Let say we want to track following events:






Thursday, March 10, 2016

How to use RecyclerView in Android efficiently



In this tutorial I will not explain you how to use RecyclerView  and what is it. Infact I will share some important tips on when to use which overriden method of RecyclerView.

first of all let me add basic code for RecyclerView Adapter and then I will explain when to use which method of RecyclerView. I will explain it with the help of an example so you better understand what am trying to say :)

Because most of the time people use onBindViewHolder and ViewHolder for initializing and other implementation because in these methods we can easily get position of an item for getting data from model position wise. but we do not have position variable or getPosition() method in onCreateViewHolder so I have used global variable position  for this purpose :)

Hope it will help someone, you can also add your findings about RecycelerView in comments below :)

some thing more about recycelerView:

RecyclerView uses LayoutManager for positioning of an items in adapter.
LayoutManager has subclasses which are
Linear Layout Managaer (Similar to ListView, can be used for vertical scrolling or horizontal scrolling)
Grid Layout Manager (Similar to GridView)
StaggeredGridLayoutManager (shows items in a staggered grid)

RecyclerView and CardView are part of android support library so you need to add dependencies in your module build.gradle file. like below

    compile 'com.android.support:cardview-v7:21.0.+'
    compile 'com.android.support:recyclerview-v7:21.0.+'

Now come to point :)
public class UsageDetailsAdapter extends RecyclerView.Adapter<UsageDetailsAdapter.ViewHolder> {

Context mContext;
int position;
DecoView decoView;

public UsageDetailsAdapter(Context context) {
    this.mContext = context;
}

@Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_adapter_usage_details, parent, false);
    decoView = (DecoView) view.findViewById(R.id.dynamicArcView);
    decoView.configureAngles(357, 52);
    ArrayList<Integer> colorsList = new ArrayList<>();
    colorsList.add(mContext.getResources().getColor(R.color.DigitalService1));


 //   Toast.makeText(mContext,""+ position, Toast.LENGTH_SHORT).show();        
    SeriesItem seriesItem = new SeriesItem.Builder(Color.parseColor("#FFE2E2E2"))
            .setRange(0, 70, 50)
            .build();
    int backIndex = decoView.addSeries(seriesItem);
    /*        * seriesItem2, it's second value will be used for calculating percentage.        * */        int newPosition = (position % 7);

    SeriesItem seriesItem2 = null;
    seriesItem2 = new SeriesItem.Builder(colorsList.get(newPosition))
            .setRange(0, 70, 0).setCapRounded(true).setChartStyle(SeriesItem.ChartStyle.STYLE_DONUT)
            .setInterpolator(new AccelerateInterpolator()).setSpinClockwise(true)
            .build();
    SeriesItem seriesItemText = new SeriesItem.Builder(Color.argb(255, 64, 196, 0))
            .setSeriesLabel(new SeriesLabel.Builder("Percent %.0f%%")
                    .setColorBack(Color.argb(218, 0, 0, 0))
                    .setColorText(Color.argb(255, 255, 255, 255))
                    .build())
            .build();
    SeriesItem seriesItemTest = new SeriesItem.Builder(Color.argb(255, 64, 196, 0))
            .setRange(0, 25, 0)
            .addEdgeDetail(new EdgeDetail(EdgeDetail.EdgeType.EDGE_OUTER, Color.parseColor("#22000000"), 0.4f))
            .build();
    //int seriesIndexText =   decoView.addSeries(seriesItemText);        int series1Index = decoView.addSeries(seriesItem2);
    int series1Test = decoView.addSeries(seriesItemTest);
 decoView.addEvent(new    DecoEvent.Builder(25).setIndex(series1Index).setDelay(100).build());
   // decoView.addEvent(new DecoEvent.Builder(25).setIndex(seriesIndexText).setDelay(100).build());//        decoView.addEvent(new DecoEvent.Builder(25).setIndex(series1Test).setDelay(100).build());

    position++;
    return new ViewHolder(view);


}

@Override    public void onBindViewHolder(ViewHolder holder, int position) {

    /*        * onBindViewHolder will be called every time user scroll up or down        *        * */
}

@Override    public int getItemCount() {
    return 10;
}

public class ViewHolder extends RecyclerView.ViewHolder {

    public ViewHolder(View itemView) {
        super(itemView);
        decoView = (DecoView) itemView.findViewById(R.id.dynamicArcView);
        decoView.setBackgroundColor(mContext.getResources().getColor(R.color.textColorPrimary));
        /*            * View holder will be called once, but if user scroll before completing arc view            * animation will not be completed.            *            * */        }
}
}
ViewHolder
ViewHolder provides a reference to the views.

I am using DecoView library for making arc veiw animation in my app. the problem which I faced here is I added all my code for making animation in ViewHolder (constructor) of ViewHolder class.

but if you scroll down your RecyclerView (items in RecycelerView) before the completion of animation , animation will not be completed and it will be stoped where it was for those items which has been scrolled up.


onBindViewHolder
replace the content of a view

then I added my code for making animation in onBindViewHolder method of RecycelerView adapter.

problem which I faced here is every time user scroll items in RecyclerView onBindViewHolder is called and animation again starts from zero.


onCreateViewHolder
create a new view, you can set margins, and other parameters here.

then I moved code inside onCreateViewHolder method and it worked for me as I wanted. means onCreateViewHolder is called only once. and arc view animates only once and it animates completely as you want.



Monday, February 15, 2016

Android Information security Guidelines with code examples


Following are requirements which should be met before submitting any APK file to Information security or before publishing app at play store.  

Always Use Proguard

Proguard will obfuscate your code. If someone decompiles your code, Your code will be useless. Because proguard will change classes, methods, variables names.


1. Add these lines in build.gradle file to enable proguard.

 minifEnabled must be true.

buildTypes {
    release {
        minifyEnabled true

        proguardFiles getDefaultProguardFile('proguard-android.txt'),
                'proguard-rules.pro'    }
    debug {
        minifyEnabled false    
}
}


2. Configure proguard-rules.pro file in your project

If you are using libraries in your project. Proguard will replace classes or remove classes. And you will get ClassDefNotFoundException.

To avoid this. Add proguard rules in Pro-guard rules.pro file. Check all dependencies in project build.gradle file and add rules for each of them.

I am using volley, mix panel, ACRA, sliding menu, jackson libraries in my project for which I am using below rules.

Example:

-keep class android.support.v4.app.** { *; }
 -keep interface android.support.v4.app.** { *; }
-keep class android.support.v7.app.** { *; }
-keep interface android.support.v7.app.** { *; }
 -keep class android.support.v13.app.** { *; }
 -keep interface android.support.v13.app.** { *; }
-dontwarn android.support.design.**
-keep class android.support.design.** { *; }
-keep interface android.support.design.** { *; }
-keep public class android.support.design.R$* { *; }
#-dontwarn android.support.design.internal.NavigationMenu.**
android.support.design.widget.NavigationView -dontwarn org.apache.http.**
 -dontwarn com.mixpanel.**
-dontwarn org.codehaus.jackson.**
-dontwarn org.acra.ErrorReporter.**
-dontwarn com.jeremyfeinstein.slidingmenu.**
-keepnames class com.fasterxml.jackson.** { *; }
 -keepclassmembers public final enum org.codehaus.jackson.annotate.JsonAutoDetect$Visibility {

 public static final org.codehaus.jackson.annotate.JsonAutoDetect$Visibility *; } -keep class  com.tozny.crypto.android.AesCbcWithIntegrity$PrngFixes$* { *; }  


4. I used allatori  for String encryption and for hiding static code blocks in my application. as proguard do not obfuscate Strings so I had to use allotri for that purpose.

5. To avoid Intent Injection
    I will explain how to do this later.

6. Remove logs from application before publishing it to play store.

7. Do not allow application to be installed on rooted devices. so that your application sensitive  information is not exposed to other apps.

To do this below is code to check if device is rooted or not. finish splash activity or application is below code returns true.

public boolean isRooted() {

    // get from build info    String buildTags = android.os.Build.TAGS;
    if (buildTags != null && buildTags.contains("test-keys")) {
        return true;
    }

    // check if /system/app/Superuser.apk is present    try {
        File file = new File("/system/app/Superuser.apk");
        if (file.exists()) {
            return true;
        }
    } catch (Exception e1) {
        // ignore    }

    // try executing commands    return canExecuteCommand("/system/xbin/which su")
            || canExecuteCommand("/system/bin/which su") || canExecuteCommand("which su");
}

// executes a command on the systemprivate boolean canExecuteCommand(String command) {
    boolean executedSuccesfully;
    try {
        Runtime.getRuntime().exec(command);
        executedSuccesfully = true;
    } catch (Exception e) {
        executedSuccesfully = false;
    }

    return executedSuccesfully;
} 


Always Sign APK before giving it to Information Security team. Do not give APK in debug mode. It should be in release mode.

8. Sensitive information stored in Database and SharedPreferences should be encrypted. Because any one can read this on rooted devices or using different tools they can break APK file and can get all files.

9. compile 'com.scottyab:secure-preferences-lib:0.1.4'
I used above mentioned library for encrypting data stored in sharedPreferences. You can read its documentation for further information. There are many other libraries for SqliteDB and sharedPreferences encryption.

This is proguard rule which I am using for above library. To make sure that it do not obfuscate classes in this library. So my app do not crash.

-keep class com.tozny.crypto.android.AesCbcWithIntegrity$PrngFixes$* { *; }

You can check/search proguard rules against other libraries which you are using in your project.

10. Error messages in case of incorrect username/password should be general. We should never tell explicitly if username is not valid or password is not valid.

Further information can be found at below links.

References:
http://developer.android.com/training/articles/security-tips.html 
http://developer.android.com/training/best-security.html

Kotlin Android MVP Dagger 2 Retrofit Tutorial

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