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

Tuesday, September 4, 2012

Android dynamic load library

There are two tricks to create dynamic load library in Android
  1. Use of sharedUserId in AndroidManifest for your applications and library project
  2. Use of dalvik.system.DexClassLoader to load library

Library Code:

It contains just java code without any Android specific entry points. AndroidManifest.xml just contains this android:sharedUserId attribute

AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.testlib"
    android:sharedUserId="com.example.testlib"
    android:versionCode="1"
    android:versionName="1.0">
    <uses-sdk android:minsdkversion="15" android:targetsdkversion="15" />

    <application android:label="@string/app_name"
        android:icon="@drawable/ic_launcher"
        android:theme="@style/AppTheme">
    </application>
</manifest>

TestCore.java

package com.example.testlib;
public class TestCore implements ITestCore{
    private int count = 0;
    public String testString(String arg) {
        String res = arg + count;
        count++;
        return res;
    }
}

Sample Application Code

Application that uses the library. Here is just the AndroidManifest.xml and TestApplication.java which do the trick. All other application staff is as usual.

AndroidManifest.xml

Be carefull to use same android:sharedUserId value in AndroidManifest.xml as library one
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.testapp"
    android:sharedUserId="com.example.testlib"
    android:versionCode="1"
    android:versionName="1.0">

    <uses-sdk= android:minsdkversion="15" android:targetsdkversion="15" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme"
        android:name=".TestApplication" >
        <activity
            android:name=".MainActivity"
            android:label="@string/title_activity_main" >
            <meta-data
                android:name="android.support.PARENT_ACTIVITY"
                android:value="android.app.Activity" />
           <intent-filter
                <action android:name="android.intent.action.MAIN"/ >
                <category android:name="android.intent.category.LAUNCHER" />
                <category android:name="android.intent.category.DEFAULT" /&gt
            </intent-filter>
        &lt/activity>
    </application>
</manifest>

ITestCore.java

Library interface has to be declared in application to avoid use reflection

    package com.example.testlib;
 
    public interface ITestCore {
    String testString(String arg);
    }

TestApplication.java

In applicatiopn's onCreate handler there is real work happens
package com.example.testapp;

import com.example.testlib.ITestCore;
import dalvik.system.DexClassLoader;
import android.app.Application;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.util.Log;

public class TestApplication extends Application {
    ClassLoader libClassLoader;
   
    @Override
    public void onCreate() {
        PackageManager pm = getPackageManager();
        String libSrcPath = null;
        for (ApplicationInfo app : pm.getInstalledApplications(0)) {
            if (app.packageName.equals("com.rhomobile.testlibrary")) {
                libSrcPath = app.sourceDir;
                Log.d("TestApplication", "package: " + app.packageName + ", sourceDir: " + app.sourceDir);
            }
        }
        try {
            libClassLoader = new DexClassLoader(libSrcPath, getDir("dex", 0).getAbsolutePath(), null, getClassLoader());
            Class clazz = libClassLoader.loadClass("com.rhomobile.testlib.TestCore");
            ITestCore core = (ITestCore)clazz.newInstance();
            String str = core.testString("TestApplication 1:");
            Log.i("TestApplication", "output: " + str);
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            Log.e("TestApplication", libClassLoader.toString());
            e.printStackTrace();
        }
    }
}

Central idea is borrowed from here: Android Developers Blog: Custom Class Loading in Dalvik

Monday, April 4, 2011

Disable screen rotation at runtime on Android

It's strange I found no ready solution in Net...

There are two sources that help me:
http://stackoverflow.com/questions/2795833/check-orientation-on-android-phone
http://www.anddev.org/rotate_screen_from_code_change_screen_orientation-t2687.html

Finally, the next code is really works (I tested it):


public class MyActivity extends Activity {

   private int mRuntimeOrientation;
   private boolean mDisableScreenRotation;

   protected int getScreenOrientation() {
      Display display = getWindowManager().getDefaultDisplay();
      int orientation = display.getOrientation();

      if (orientation == Configuration.ORIENTATION_UNDEFINED) {
         orientation = getResources().getConfiguration().orientation;

         if (orientation == Configuration.ORIENTATION_UNDEFINED) {
            if (display.getWidth() == display.getHeight())
               orientation = Configuration.ORIENTATION_SQUARE;
            else if(display.getWidth() < display.getHeight())

               orientation = Configuration.ORIENTATION_PORTRAIT;
            else
               orientation = Configuration.ORIENTATION_LANDSCAPE;
            }
         }
      return orientation;
   }

   @Override
   protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      mRuntimeOrientation = this.getScreenOrientation();
   }

   @Override
   public void onConfigurationChanged(Configuration newConfig) {
      if (mDisableScreenRotation) {
         super.onConfigurationChanged(newConfig);
         this.setRequestedOrientation(mRuntimeOrientation);
      } else {
         mRuntimeOrientation = this.getScreenOrientation();
         super.onConfigurationChanged(newConfig);
      }
   }
}