2015년 12월 20일 일요일

Android ANR Debugging


In Android, application responsiveness is monitored by the Activity Manager and Window Manager system services.
and android will display the Application Not Responding (ANR) dialog for a particular application when it detects one of the following conditions:
  • No response to an input event (within 5 seconds.
  • A BroadcastReceiver hasn't finished executing within 10 seconds.


In case ANR happens, through the method dumpStackTraces() of ActivityManagerService all the information of the thread stack will be saved in /data/anr/ directory.

Then, what we need to find or look at to ?
The following is the testing log snippet...basic investigation steps would be to look for a pattern like "waiting to lock........held by tid=xxx"..
Here Thread ID 12 is hold the task.. so we need to look more closely the problematic method.



"main" prio=5 tid=1 MONITOR
| group="main" sCount=1 dsCount=0 obj=0x410a8c40 self=0xa73c98
| sysTid=704 nice=0 sched=0/0 cgrp=default handle=1075004808
| schedstat=( 0 0 0 ) utm=31475 stm=3384 core=1
  at com.test.studio.TestNativeSAP.synchronizedInvoke(TestNativeSAP.java:~246)
  - waiting to lock <0x42472270> (a com.test.studio.TestNativeSAP) held by tid=12 (AsyncTask #2)

"AsyncTask #2" prio=5 tid=12 NATIVE
  at com.test.studio.TestNativeSAP.startPreview(Native Method)
  at com.test.studio.TestNativeSAP.synchronizedInvoke(TestNativeSAP.java:286)
  at com.test.studio.TestNativeSAP.invokeStartPreview(TestNativeSAP.java:169)

This is the only example.. trace does not always contain "waiting to lock"
so sometimes it is really hard to find main reason.



Thread States:
- running: executing application code
- sleeping: called Thread.sleep()
- monitor: waiting to acquire a monitor lock
- wait: in Object.wait()
- native: executing native code
- vmwait: waiting on a VM resource
- zombie: thread is in the process of dying
- init: thread is initializing
- starting: thread is about to start


Android Testing Library


Android testing support library includes the followings:
1) AndroidJunitRunner: JUnit4 compatible test runner for Android
2) Espresso: UI testing framework, suitable for functional UI testing within an app
3) UI Automator: UI testing framework, suitable for cross-app functional UI testing


1) AndroidJunitRunner
- Looks really familiar with Junit, but should avoid mixing JUnit3 and JUnit4
- For use JUnit4, must use @RunWith(AndroidJUnit4.class) annotation


import android.support.test.runner.AndroidJUnit4;
import android.support.test.runner.AndroidJUnitRunner;
import android.test.ActivityInstrumentationTestCase2;

@RunWith(AndroidJUnit4.class)
public class CalculatorInstrumentationTest
        extends ActivityInstrumentationTestCase2 {

    @Before
    public void setUp() throws Exception {
        super.setUp();

        // Injecting the Instrumentation instance is required
        // for your test to run with AndroidJUnitRunner.
        injectInstrumentation(InstrumentationRegistry.getInstrumentation());
        mActivity = getActivity();
    }

    @Test
    public void typeOperandsAndPerformAddOperation() {
        // Call the CalculatorActivity add() method and pass in some operand values, then
        // check that the expected value is returned.
    }

    @After
    public void tearDown() throws Exception {
        super.tearDown();
    }
}



2) Espresso
In order for the Android Plug-in for Gradle to correctly build and run your Espresso tests,
you must specify the following libraries in the build.gradle file of your Android app module:

dependencies {
    androidTestCompile 'com.android.support:support-annotations:23.0.1'
    androidTestCompile 'com.android.support.test:runner:0.4.1'
    androidTestCompile 'com.android.support.test:rules:0.4.1'
    androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.1'
    // Set this dependency if you want to use Hamcrest matching
    androidTestCompile 'org.hamcrest:hamcrest-library:1.3'
}

Steps for writing codes are easy, check the below steps.
- Find the UI component to test in an Activity by calling onView(), onData()
- Simulate a specific user interaction by calling ViewInteraction.perform(), DataInteraction.perform()
- Make sure everything works as expected

// find a view by looking for a text string it displays 
onView(withText("Sign-in"));

// find a view with resource id
onView(withId(R.id.button_signin));

// allOf() combines multiple matchers together
// find a view that has resource id of button_signin and contain the string "Sign-in"
onView(allOf(withId(R.id.button_signin), withText("Sign-in")));

// with not keyword can filter those views do not matchers
// find a view that has resource id of button_signin but do not contain the string "Sign-in"
onView(allOf(withId(R.id.button_signin), not(withText("Sign-out"))));


In an AdapterView widget, the view is dynamically populated with child views at runtime. If the target view you want to test is inside an AdapterView (such as a ListView, GridView, or Spinner), the onView() method might not work because only a subset of the views may be loaded in the current view hierarchy.

Instead, call the onData() method to obtain a DataInteraction object to access the target view element.
onData(allOf(is(instanceOf(Map.class)),
        hasEntry(equalTo(LongListActivity.ROW_TEXT), is(str))));


The ViewActions class provides a list of helper methods for specifying common actions. You can perform actions like:
- ViewActions.click(): Clicks on the view.
- ViewActions.typeText(): Clicks on a view and enters a specified string.
- ViewActions.scrollTo(): Scrolls to the view. The target view must be subclassed from ScrollView
- ViewActions.pressKey(): Performs a key press using a specified keycode.
- ViewActions.clearText(): Clears the text in the target view.

Lastly call the ViewInteraction.check() or DataInteraction.check() method to assert that the view in the UI matches some expected state.

// Check that the text was changed.
    onView(withId(R.id.textToBeChanged))
            .check(matches(withText(STRING_TO_BE_TYPED)));


3) UI Automator
In order for the Android Plug-in for Gradle to correctly build and run your UI Automator tests, you must specify the following libraries in the build.gradle file of your Android app module:
dependencies {
    androidTestCompile 'com.android.support:support-annotations:23.0.1'
    androidTestCompile 'com.android.support.test:runner:0.4.1'
    androidTestCompile 'com.android.support.test.uiautomator:uiautomator-v18:2.1.1'
    // Set this dependency if you want to use Hamcrest matching
    androidTestCompile 'org.hamcrest:hamcrest-library:1.3'
}


// Initialize UiDevice instance
private UiDevice mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());

// find Cancel/OK button object
UiObject cancelButton = mDevice.findObject(new UiSelector()
        .text("Cancel"))
        .className("android.widget.Button"));
UiObject okButton = mDevice.findObject(new UiSelector()
        .text("OK"))
        .className("android.widget.Button"));

// Simulate a user-click on the OK button, if found.
if(okButton.exists() && okButton.isEnabled()) {
    okButton.click();
}


// With UiSelector, it is possible to access a specific UI component in an app
// the first list view in the currently displayed UI
// then find UI element with the text property "Apps"
UiObject appItem = new UiObject(new UiSelector()
        .className("android.widget.ListView")
        .instance(1)
        .childSelector(new UiSelector()
        .text("Apps")));

Once your test has obtained a UiObject object, you can call the methods in the UiObject class to perform user interactions on the UI component
represented by that object. You can specify such actions as:

- click(): Clicks the center of the visible bounds of the UI element.
- dragTo(): Drags this object to arbitrary coordinates.
- setText(): Sets the text in an editable field, after clearing the field's content.
- swipeUp(): Performs the swipe up action on the UiObject.
Similarly, the swipeDown(), swipeLeft(), and swipeRight() methods perform corresponding actions.


Lastly use standard JUnit Assert methods to test that UI components in the app return the expected results.

private static final String CALC_PACKAGE = "com.myexample.calc";

public void testTwoPlusThreeEqualsFive() {
    // Enter an equation: 2 + 3 = ?
    mDevice.findObject(new UiSelector()
            .packageName(CALC_PACKAGE).resourceId("two")).click();
    mDevice.findObject(new UiSelector()
            .packageName(CALC_PACKAGE).resourceId("plus")).click();
    mDevice.findObject(new UiSelector()
            .packageName(CALC_PACKAGE).resourceId("three")).click();
    mDevice.findObject(new UiSelector()
            .packageName(CALC_PACKAGE).resourceId("equals")).click();

    // Verify the result = 5
    UiObject result = mDevice.findObject(By.res(CALC_PACKAGE, "result"));
    assertEquals("5", result.getText());
}


Reference:
Android Testing Support Library

2015년 12월 16일 수요일

SVG in Android


I believe vector graphics native supports for android had long been on the wish list and good news(?) is that from the release of API 21 (Android 5.0) VectorDrawable has been included. if used properly I don't think we have to prepare all the images for each different device resolutions, however still there exist some problems.
Android supports only basic level of vector graphics..

  • VectorDrawable supports paths using the ‘d’ attribute like the SVG format
  • VectorDrawable does not read/support the SVG format
  • VectorDrawable does not support gradients
  • VectorDrawable does not support numbers using scientific E notation (as commonly used in SVG)


Even though SVG format is not supported, we can still convert SVG files to VectorDrawables with Android Studio and open source tools like Inkscape, svg2android

Menu in Android Studio:
File > New > Vector Asset > Local Asset file > change options if required

Link:
Inkscape: https://inkscape.org/
svg2android: http://inloop.github.io/svg2android/


Maybe SVG not only helps to save some time for development, but also increase the visual quality, we need to be careful of using it, because it is rendered at runtime, so always need to keep the complexity of SVG files to minimum.

2015년 12월 7일 월요일

How to use LRU cache in Android


Android provides LRU cache, that is to evict the least recently used item from the data.
https://developer.android.com/reference/android/util/LruCache.html

1. The size of the cache can be adjusted like the following (depends on the purpose of having cache and the resolution of the devices):
// Cache Size 
ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
int availableMemoryInBytes = am.getMemoryClass() * 1024 * 1024;

// Need to adjust size
LruCache bitmapCache = new LruCache(availableMemoryInBytes / 8); 


2. In the example we need to override sizeOf() methods with bitmap size
public class MyCache extends LruCache(String, Bitmap) {
    @Override
    protected int sizeOf(String Key, Bitmap value) {
        // return the size of the in-memory bitmap
        // counted against maxSizeBytes
        return value.getByteCount();
    }
    ...
}      


3. The usage of the LRU cache:
Bitmap bitmap = mCache.get(filename);
if (bitmap == null) {
    bitmap = BitmapFactory.decodeFile(filename);
    mCache.put(filename, bitmap );
}

2015년 10월 16일 금요일

7 Mobile development skills

I have just read an article about the skills that can make my salary a little bit higher.

Event if it is true or not, reading this kind of writings make me awake to find out some trends of industry (?)...


7 mobile development skills that mean higher pay By Sarah K. White

According to the article, the following is the list of the skills you need to make your salary even higher.

1. Apache Cordova

2. F#

3. Grails

4. Drupal

5. iRise

6. Oracle Certified Professional Java SE Programmer

7. jBoss Certified developer

Some of them are really familiar to me, but some of them are not,
so I will go and check some skills, if it turns out to be really interesting, why not study

2015년 2월 2일 월요일

How to set your app to open a file in Google Drive

To make sure your app is included in the list of apps that can open a file in Google Drive app, you need to make some additions to your AndroidManiest.xml. The activity for opening Drive files & MIME Types that activity can open must be specified.
The following example code shows the manifest for "ViewerActivity". Your own app manifest must include a similar intent with your own appropriate values and MIME types that your app can open:

<activity
android:name="ViewerActivity"
android:label="@string/my_viewer"
android:icon="@drawable/app_icon"
android:exported="true">

<intent-filter>
<action android:name="com.google.android.apps.drive.DRIVE_OPEN">
<data android:mimetype="image/png">
<data android:mimetype="image/jpeg">
<data android:mimetype="image/jpg">
</intent-filter>
</activity>




Reference:
https://developers.google.com/drive/android/java-client




2014년 9월 12일 금요일

Signing in with Google+ for Android

First step is to go to the Google Developers Console (https://console.developers.google.com/project) and create project as well as Client ID.



Second step would be adding some permissions in AndroidManifest.xml to access Google+ API, account name as part of sign in, OAuth 2.0 tokens or invalidate tokens to disconnect. The following permissions should be requested.
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.USE_CREDENTIALS" />

Now we're ready to add some codes to initialize GoogleApiClient.
Some might wonder what GoogleApiClient really does, it basically wraps a ServiceConnection to Google Play services, this GoogleApiClient object is used to communicate with Google+ API and becomes functional after the asynchronous connection has been established with the service, and typically GoogleApiClient is managed like this:
- initialize GoogleApiClient in Activity.onCreate()
- invoke GoogleApiClient.connect() during Activity.onStart()
- invoke GoolgeApiClient.disconnect() during Acitivity.onStop()


import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.GoogleApiClient.ConnectionCallbacks;
import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener;
import com.google.android.gms.plus.Plus;

public class PlusActivity extends Activity 
        implements ConnectionCallbacks, OnConnectionFailedListener {

 /* Request code used to invoke sign in user interactions. */
 private static final int RC_SIGN_IN = 0;

 private GoogleApiClient mGoogleClient;

 private ProgressDialog mConnectionProgressDialog;

 /*
  * A flag indicating that a PendingIntent is in progress and prevents us
  * from starting further intents.
  */
 private boolean mIntentInProgress;

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

  mGoogleClient = new GoogleApiClient.Builder(this).addApi(Plus.API)
    .addScope(Plus.SCOPE_PLUS_LOGIN).addConnectionCallbacks(this)
    .addOnConnectionFailedListener(this).build();

  mConnectionProgressDialog = new ProgressDialog(this);
  mConnectionProgressDialog.setMessage("Signing in...");
 }

 @Override
 protected void onStart() {
  super.onStart();
  mGoogleClient.connect();
 }

 @Override
 protected void onStop() {
  super.onStop();

  if (mGoogleClient.isConnected()) {
   mGoogleClient.disconnect();
  }
 }

 @Override
 protected void onActivityResult(int requestCode, int responseCode, Intent intent) {
  if (requestCode == RC_SIGN_IN) {
   mIntentInProgress = false;

   if (!mGoogleClient.isConnecting()) {
    mGoogleClient.connect();
   }
  }
 }

 @Override
 public void onConnectionFailed(ConnectionResult connectionResult) {
  Toast.makeText(this, "GoogleAPIClient Failed to Connect", Toast.LENGTH_SHORT).show();

  if (!mIntentInProgress && connectionResult.hasResolution()) {
   try {
    mIntentInProgress = true;
    startIntentSenderForResult(connectionResult.getResolution().getIntentSender(), RC_SIGN_IN, null, 0, 0, 0);
   } catch (SendIntentException e) {
    mIntentInProgress = false;
    mGoogleClient.connect();
   }
  }
 }

 @Override
 public void onConnected(Bundle bundle) {
  Toast.makeText(this, "GoogleAPIClient Connected", Toast.LENGTH_SHORT).show();
  mConnectionProgressDialog.dismiss();
 }

 @Override
 public void onConnectionSuspended(int arg0) {
  Toast.makeText(this, "GoogleAPIClient Connection Suspended", Toast.LENGTH_SHORT).show();
  mGoogleClient.connect();
 }
}

This is it, we done signing in Google+, will try to add some codes for accessing Google+ API to post some comments, retrieving friends list next time.





2014년 9월 10일 수요일

Add Maps to application (Google Maps)

The key class when working with a map object is the GoogleMap class, models the map object within application. Within UI, a map will be represented by either a MapFragment or MapView object.

Google Map handles the following operations automatically

  • connecting to the Google Maps service
  • downloading map tiles
  • displaying tiles on the device screen
  • displaying various controls such as pan & zoom
  • responding to pan & zoom gestures by moving the map and zooming in/out


Google Maps provides four types of maps: Normal, Hybrid, Satellite, Terrain.
To set the type of a map, use setMapType() of GoogleMap object.
mGoogleMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);

Basic steps for adding a map to an Android application
1. Add a fragment
Add a <fragment> element to the Activity's layout file to define a Fragment object, and set android:name attribute to "com.google.android.gms.maps.MapFragment. This will attach a MapFragment to the Activity automatically.
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
  android:id="@+id/map"
  android:name="com.google.android.gms.maps.MapFragment"
  android:layout_width="match_parent"
  android:layout_height="match_parent" />
We can also add a MapFragment to an Activity in code like the following:
mMapFragment = MapFragment.newInstance();
FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
fragmentTransaction.add(R.id.my_container, mMapFragment);
fragmentTransaction.commit();

2. Add map code
After setting the layout file as the content view for the Activity, get a handle to the map by calling findFragmentById() to set some initial options for the map.

mGoogleMap = ((MapFragment) getFragmentManager().findFragmentById(R.id.map)).getMap();

3. Verify map availability
Before interacting with a GoogleMap object, we need to make sure that an object can be instantiated.
Check the following example code snippets, this methods can be called from both onCreate() and onResume() to ensure that the map is always available.

private void setupMapIfNeeded() {
  // null check to confirm that the map has not been instantiated
  if (mGoolgeMap == null) {
    mGoogleMap = ((MapFragment) getFragmentManager().findFragmentById(R.id.map)).getMap();
    
    if (mGoogleMap != null) {
       // verified, it's ok to manipulate the map
    }
  }
}


2014년 9월 9일 화요일

Supporting different layouts & bitmaps

Create different layouts for each screen size you want to support to optimize user experience. Each layout file should be saved into the appropriate resource directory, named with a -<screen_size> suffix.

e.g.
My Project
       - res/
             - layout/                     ==> default portrait
                         main.xml
             - layout-land              ==> landscape
                         main.xml
             - layout-large/            ==> large portrait
                         main.xml
             - layout-large-land     ==> large landscape
                         main.xml

The file names must be exactly the same, but their contents are different in order to provide an optimized UI for the corresponding screen size.


Providing bitmap resources that are properly scaled to each of generalized densities: low, medium, high, etc. will help to achieve good graphical quality and performance on all screen densities.

To generate images, start with raw resources in vector format and generate the images for each density using the following size scales:

  • xxxhdpi: 4.0
  • xxhdpi: 3.0
  • xhdpi: 2.0
  • hdpi: 1.5
  • mdpi: 1.0 (baseline)
  • ldpi: 0.75
If we generate a 200x200 image for xhdpi, we should generate the same resources in 150x150 for hdpi, 100x100 for mdpi, 300x300 for xxhdpi and then place them in the appropriate drawable resource directory:

e.g.

My Project
       - res/
             - drawable-xxhdpi/                  
                         example.png
             - drawable-xhdpi            
                         example.png
             - drawable-hdpi/
                         example.png
             - drawable-mdpi
                         example.png



Controlling App's Availability to Devices

Android supports a variety of features, some of them are hardware-based, some are software-based, and some are dependent on platform version. So app developer may need to control app's availability to devices based on app's required features.

We can restrict app's availability to devices through Google Play Store based on the following device characteristics:

  1. Device features
  2. Platform version
  3. Screen configuration

Device features:
Android defines feature IDs for any hardware or software feature that may not be available on all devices. So we can prevent users from installing app when their devices don't provide a given feature by declaring it with a <uses-feature> element in app's manifest file.

e.g. declaring the compass sensor as required
<uses-feature android:name="android.hardware.sensor.compass"
                       android:required="true" />

Google Play Store compares the features app requires to the features available on user's device to determine whether the app is compatible with each device. If the device does not provide all the features, the user cannot install the app.

In case device features are not required for running app's primary functionality, then set the required attribute to "false"  and check for device feature at runtime.
PackageManager pm = getPackageManager();
if (!pm.hasSystemFeature(PackageManager.FEATURE_SENSOR_COMPASS)) {
  // No compass available on this device, turn off the compass feature
  disableCompassFeature();
}


Platform version:
Different devices may run different versions of Android, which means new APIs of newer Android version may not be available on older versions of Android.

API level allows to declare the minimum version with which your app is compatible using <uses-sdk> element in app's manifest file.

e.g.
<uses-sdk android:minSdkVersion="14"
                 android:targetSdkVersion="19" />

minSdkVersion: declares the minimum version with which app is compatible
targetSdkVersion: declares the highest version on which app has been optimized

We can check the API level at runtime and gracefully degrade the corresponding features when the API level is too low.
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
  // running on something older than API 11, so disable features
  disableSomeFeature();
}

Screen configuration:
Android runs on devices of various sizes from smart phones to TVs. In order to categorize devices by screen type, Android defines two characteristics for each devices: screen size (physical size) and screen density (DPI)

  • generalized sizes: small, normal, large and xlarge
  • generalized densities: mdpi (medium), hdpi, xhdpi (extra high), xxhdpi (extra-extra high)
By default most apps are compatible with all screen sizes and densities because the system makes all the adjustments to UI layout and image resources as necessary for each screen. However we can optimize the user experience for each screen configuration by adding specialized layouts for different screen sizes and optimized bitmap images for common screen densities.

For more information in detail, check the following developers site:



How to use ActionProvider Or ShareActionProvider

ActionProvider can generate action views for use in the action bar, dynamically populate submenus of a MenuItem, and handle default menu item invocations.

Two ways to use an action provider:
- Set the action provider on a MenuItem directly by calling setActionProvider (ActionProvider)
- Declare the action provider in an XML menu resource.   e.g.
  <item
    android:id="@+id/action_search"
    android:title="Search"
    android:icon="@drawable/search_icon"
    android:showasaction="ifRoom"
    android:actionproviderclass="com.my.CustomActionProvider" />

Making a custom action provider is straightforward, simply extend ActionProvider class and implement its callback methods as appropriate. It should be implemented like below code example:

public class MyCustomActionProvider extends ActionProvider {
   private Context mContext;
   private EditText mEditText;

   public MyCustomActionProvider (Context context) {
     super(context);
     mContext = context;
   }

   @override
   public View onCreateActionView() {
     // Make & return View that will be shown when action bar icon pressed
     // Here we have a custom layout that contains EditText for Search

     LayoutInflator layout = LayoutInflator.from(mContext);
     View view = layout.inflate(R.layout.search_layout, null);
     mEditText = (EditText) view.findViewById(R.id.edit_search);
     ...................
   }

   ................
}

public class MainActivity extends Activity {
  private MyCustomActionProvider mActionProvider;
  ...........

  @override
  public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.items, menu);
    MenuItem item = menu.findItem(R.id.action_search);
    mActionProvider = (MyCustomActionProvider) item.getActionProvider();
    ..............
  }
  
  ...........
}

Android also provides an implementation of ActionProvider for Share actions: ShareActionProvider, which facilitates a share action by showing a list of possible apps for sharing directly in the action bar.
To add a share action with ShareActionProvider, just define the tag  for an <item> android:actionproviderclass="android.widget.ShareActionProvider".

The last step left to do is to define the Intent what we want to use for sharing. How we do it? just modify onCreateOptionMenu() method.
// In Activity#onCreateOptionsMenu
 public boolean onCreateOptionsMenu(Menu menu) {
     // Get the menu item.
     MenuItem menuItem = menu.findItem(R.id.my_menu_item);
     // Get the provider and hold onto it to set/change the share intent.
     mShareActionProvider = (ShareActionProvider) menuItem.getActionProvider();
     // Set history different from the default before getting the action
     // view since a call to MenuItem.getActionView() calls
     // onCreateActionView() which uses the backing file name. Omit this
     // line if using the default share history file is desired.
     mShareActionProvider.setShareHistoryFileName("custom_share_history.xml");
     . . .
 }

 // Somewhere in the application.
 public void doShare(Intent shareIntent) {
     // When you want to share set the share intent.
     mShareActionProvider.setShareIntent(shareIntent);
 }

5. Project Scope Management (3)

5.3 Define Scope
Define Scope is the process of developing a detailed description of the project and product. The key benefit of this process is that it describes the product, service, or result boundaries by defining which of the requirements collected will be included in and excluded from the project scope.


Since all of the requirements identified in Collect Requirements may not be included in the project, the Define Scope process selects the final project requirements from the requirements documentation delivered during the Collect Requirements process. It then develops a detailed description of the project and product, service, or result.

The preparation of a detailed project scope statement is critical to project success and builds upon the major deliverables, assumptions, and constraints that are documented during project initiation. During project planning, the project scope is defined and described with greater specificity as more information about the project is known. Existing risks, assumptions, and constraints are analyzed for completeness and added or updated as necessary. The Define Scope process can be highly iterative. In iterative life cycle projects, a high-level vision will be developed for the overall project, but the detailed scope is determined one iteration at a time and the detailed planning for the next iteration is carried out as work progresses on the current project scope and deliverables.

Inputs
1) Scope management plan: a component of the project management plan that establishes the activities for developing, monitoring, and controlling the project scope.

2) Project charter: provides the high-level project description and product characteristics. It also contains project approval requirements. If a project charter is not used in the performing organization, then comparable information needs to be acquired or developed, and used as a basis for the detailed project scope management statement. Organizations that do not produce a formal project charter will usually perform an informal analysis to identify the content necessary for further scope planning.

3) Requirements documentation:  will be used to select the requirements that will be included in the project.

4) Organizational process assets: can influence how scope is defined
- Policies, procedures, and templates for a project scope statements;
- Project files from previous project; and
- Lessons learned from previous phrases or projects.

Tools & Techniques
1) Expert Judgment: used to analyze the information needed to develop the project scope statement. such judgement and expertise is applied to any technical detail.

2) Product Analysis: Each application area has one or more generally accepted methods for translating high-level product descriptions into tangible deliverables. Product analysis includes techniques such as product breakdown, systems analysis, requirements analysis, system engineering, value engineering, and value analsyis.

3) Alternatives Generation: used to develop as many potential options as possible in order to identify different approaches to execute and perform the work of the project. A variety of general management technique can be used, such as brainstorming, lateral thinking, analysis of alternatives, etc.

4) Facilitated Workshops: The participation of key players with a variety of expectations and/or fields of expertise in these intensive working sessions helps to reach a cross-functional and common understanding of the project objectives and its limits.

Outputs
1) Project Scope Statement: description of the project scope, major deliverables, assumptions, and constraints. The project scope statement documents the entire scope, including project and product scope. It describes, in detail, the project's deliverables and the work required to create those deliverables. It also provides a common understanding of the project scope among project stakeholders. It may contain explicit scope exclusions that can assist in managing stakeholder expectations. It enables the project team to peform more detailed planning, guides the project team's work during execution, and provides the baseline for evaluating whether requests for changes or additional work are contained within or outside the project's boundaries.

2) Project Document Updates: may be include
- Stakeholder register
- Requirements documentation and
- Requirements traceability matrix.



2014년 9월 2일 화요일

How to set/get Meta Data in AndroidManifest

In AndroidManifest.xml


Meta data defined in AndroidManifest.xml can be retrieved with some codes like this:

try {
    ApplicationInfo ai = getPackageManager().getApplicationInfo(activity.getPackageName(), PackageManager.GET_META_DATA);
    Bundle bundle = ai.metaData;
    String myApiKey = bundle.getString("com.myapp.version.api.key");
} catch (NameNotFoundException e) {
    Log.e(TAG, "Failed to load meta data : " + e.getMessage());
} catch (NullPointerException e) {
    Log.e(TAG, "Failed to load meta data : " + e.getMessage());         
}

2014년 8월 27일 수요일

How to check the package name of current launcher


Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
ResolveInfo resolveInfo = getPackageManager().resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);
String packageName = resolveInfo.activityInfo.packageName;

2014년 8월 3일 일요일

How to take a snapshot in Google Map v2

// Once everything has loaded, cache the map’s image for fast display later
// Note: the map loaded callback is only called once.
mMap.setOnMapLoadedCallback(new GoogleMap.OnMapLoadedCallback() {
    public void onMapLoaded() {
        mMap.snapshot(new GoogleMap.SnapshotReadyCallback() {
            public void onSnapshotReady(Bitmap bitmap) {
                // Write image to disk
            }
        });
    }
});
Reference: http://googlegeodevelopers.blogspot.sg/2013/10/ghost-markers-in-your-neighborhood-new.html

How to change text color of SearchView

int textViewId = mSearchView.getContext().getResources().getIdentifier("android:id/search_src_text", null, null);
TextView textView = (TextView) mSearchView.findViewById(textViewId);
textView.setTextColor(Color.GRAY);

2014년 7월 13일 일요일

Useful Android Intents

Useful Android Intent List

1. Google Maps - get directions between two points
Uri uri = Uri.parse("http://maps.google.com/maps?f=d&saddr=0,0&daddr=10,10"));
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
intent.setComponent(new ComponentName("com.google.android.apps.maps", "com.google.android.maps.MapsActivity"));
startActivity(intent);

2. Google Maps - show map
Uri uri = Uri.parse("geo:11.899533,-77.036476");
Intent it = new Intent(Intent.Action_VIEW, uri);
startActivity(it);
3. Call
Uri uri = Uri.parse("tel:xxxxxx");
Intent it = new Intent(Intent.ACTION_DIAL, uri);  
startActivity(it); 
OR
with permission 

Uri uri = Uri.parse("tel.xxxxxx");
Intent it = new Intent(Intent.ACTION_CALL,uri);
4. SMS/MMS
Uri uri = Uri.parse("smsto:0800000123");   
Intent it = new Intent(Intent.ACTION_SENDTO, uri);   
it.putExtra("sms_body", "The SMS text");   
startActivity(it); 

Uri uri = Uri.parse("content://media/external/images/media/23");   
Intent it = new Intent(Intent.ACTION_SEND);   
it.putExtra("sms_body", "some text");   
it.putExtra(Intent.EXTRA_STREAM, uri);   
it.setType("image/png");   
startActivity(it);
5. Email
Uri uri = Uri.parse("mailto:xxx@abc.com");
Intent it = new Intent(Intent.ACTION_SENDTO, uri);
startActivity(it);


Intent it = new Intent(Intent.ACTION_SEND);   
it.putExtra(Intent.EXTRA_EMAIL, "me@abc.com");   
it.putExtra(Intent.EXTRA_TEXT, "The email body text");   
it.setType("text/plain");   
startActivity(Intent.createChooser(it, "Choose Email Client")); 


Intent it = new Intent(Intent.ACTION_SEND);     
String[] tos = {"me@abc.com"};     
String[] ccs = {"you@abc.com"};     
it.putExtra(Intent.EXTRA_EMAIL, tos);     
it.putExtra(Intent.EXTRA_CC, ccs);     
it.putExtra(Intent.EXTRA_TEXT, "The email body text");     
it.putExtra(Intent.EXTRA_SUBJECT, "The email subject text");     
it.setType("message/rfc822");     
startActivity(Intent.createChooser(it, "Choose Email Client"));  


// Adding extra
Intent it = new Intent(Intent.ACTION_SEND);   
it.putExtra(Intent.EXTRA_SUBJECT, "The email subject text");   
it.putExtra(Intent.EXTRA_STREAM, "file:///sdcard/mysong.mp3");   
sendIntent.setType("audio/mp3");   
startActivity(Intent.createChooser(it, "Choose Email Client"));
6. Play Music
Intent it = new Intent(Intent.ACTION_VIEW);
Uri uri = Uri.parse("file:///sdcard/song.mp3");
it.setDataAndType(uri, "audio/mp3");
startActivity(it);


Uri uri = Uri.withAppendedPath(
MediaStore.Audio.Media.INTERNAL_CONTENT_URI, "1");   
Intent it = new Intent(Intent.ACTION_VIEW, uri);   
startActivity(it); 
7. Uninstall apk
Uri uri = Uri.fromParts("package", PackageName, null);   
Intent it = new Intent(Intent.ACTION_DELETE, uri);   
startActivity(it);
8. Search application in Google Play Store
Uri uri = Uri.parse("market://search?q=pname:pkg_name");  
Intent it = new Intent(Intent.ACTION_VIEW, uri);  
startActivity(it);  
9. Google Search
Intent intent = new Intent();
intent.setAction(Intent.ACTION_WEB_SEARCH);
intent.putExtra(SearchManager.QUERY,"searchString")
startActivity(intent);

2014년 7월 8일 화요일

5. Project Scope Management (2)

5.2 Collect Requirements
Collect Requirements is the process of determining, documenting, and managing stakeholder needs and requirements to meet project objectives.


The project success directly influenced by active stakeholder involvement in the discovery and decomposition of needs into requirements and by the care taken in determining, documenting, and managing the requirements of the product, service or results of the project. Requirements include conditions or capabilities that are to be met by the project or present in the product, service or result to satisfy an agreement or other formally imposed specification. Requirements become the foundation of the WBS, cost, schedule, quality planning and sometimes procurement are all based upon these requirements. The development of requirements begins with an analysis of the information contained in the project charter, the stakeholder register and stakeholder management plan.

Inputs
1) Scope management plan: provides clarity as to how project teams will determine which type of requirements need to be collected for the project.

2)Requirements management plan: provides the processes that will be used throughout the Collect Requirement process to define and document the stakeholder needs.

3)Stakeholder management plan: used to understand stakeholder communication requirements and the level of stakeholder engagement in order to assess and adapt to the level of stakeholder participation in requirement activities.

4) Project charter: used to provide the high level description of the product, service, or result of the project so that detailed requirements can be developed.

Tools & Techniques
1) Interview: Talking to stakeholders directly, typically performed by asking prepared and spontaneous questions and recording the responses.

2) Focus groups: trained moderator guides the group through an interactive discussion, designed to be more conversational than a one-to-one interview.

3) Facilitated workshop: focused sessions that bring key stakeholders together to define product requirements. Workshops are considered a primary technique for quickly defining cross-functional requirements and reconciling stakeholder differences. Because of their interactive group nature, well facilitated sessions can build trust, foster relationships, and improve communication among the participants, which can lead to increased stakeholder consensus. In addition issues can be discovered earlier and resolved more quickly than in individual sessions.

Joint application development (JAD)

  • used in software development industry
  • focus on bringing business subject matter experts and the development team together to improve software development process
Quality function deployment (QFD)
  • helps determine critical characteristics for new product development
  • starts by collection customer needs, also known as Voice of the Customer (VoC)
  • collected needs are then objectively sorted and prioritized
4) Group creativity techniques: group activities can be organized to identify project and product requirements.

  • Brainstorming - used to generate and collect multiple ideas, not include voting or prioritization.
  • Nominal group technique - enhances brainstorming with a voting process used to rank most useful ideas
  • Idea/mind mapping - ideas created through brainstorming are consolidated in a single map to reflect commonality and differences
  • Affinity diagram - large numbers of ideas to be classified into groups for review and analysis
  • Multicriteria decision analysis - utilizes a decision matrix to provide a systematic analytical approach for establishing criteria, such as risk levels, uncertainty, and valuation, to evaluate and rank many ideas


5) Group decision making techniques: can be used to generate, classify and prioritize product requirements

  • Unanimity - everyone agrees on a single course of action, one way to reach unanimity is the Delphi technique.
  • Majority - more than 50%
  • Plurality - largest block in a group decides, even if a majority is not achieved
  • Dictatorship - one individual makes the decision

The experts answer questionnaires in two or more rounds. After each round, a facilitator provides an anonymous summary of the experts’ forecasts from the previous round as well as the reasons they provided for their judgments. Thus, experts are encouraged to revise their earlier answers in light of the replies of other members of their panel. It is believed that during this process the range of the answers will decrease and the group will converge towards the "correct" answer. Finally, the process is stopped after a pre-defined stop criterion.
(keywords: experts, questionnaire, anonymous

6) Questionnaires and surveys: written set of questions designed to quickly accumulate information from large number of respondents, appropriate with varied audiences, when respondents are geographically dispersed and where statistical analysis is appropriate.

8) Prototypes: obtains early feedback on requirements by providing a working model of the expected product before actually building it. allows stakeholders to experiment with a model of the final product rather than being limited to discussing abstract representations of their requirements.


Outputs
1) Requirements documentation: describes how individual requirements meet the business need for the project. Requirements may start out at a high level and become progressively more detailed as more about the requirements is known.

2) Requirements traceability matrix: a grid that links product requirements from their origin to the deliverables that satisfy them. The implementation of a requirements traceability matrix helps ensure that each requirement adds business value by linking it to the business and project objectives. It provides a meas to track requirements throughout the project life cycle, helping to ensure that requirements approved in the requirements documentation are delivered at the end of the project. Finally it provides a structure for managing changes to the product scope.

Tracing includes Business needs, goals, objectives, project scope/WBS deliverables, etc.



2014년 7월 7일 월요일

5. Project Scope Management (1)

Project Scope management includes the processes required to ensure that the project includes all the work required, and only the work required, to complete the project successfully. Managing the project scope is primarily concerned with defining and controlling what is and is not included in the project.

In the project context, the term scope can refer to:
  • Product scope: the features and functions that characterize a product, service or result
  • Project scope: the work performed to deliver a product, service, or result with the specified features and functions. The term project scope is sometimes viewed as including product scope.
The scope baseline for the project is the approved version of the project scope statement, work breakdown structure (WBS), and its associated WBS dictionary. A baseline can be changed only through formal change control procedures and is used as a basis for comparison while performing Validate Scope and Control Scope processes as well as other controlling processes.

Completion of the project scope is measured against the Project management plan. Completion of the product scope is measured against the product requirements. The project scope management processes need to be well integrated with the other knowledge area processes, so that the work of the project will result in delivery of the specified product scope.

5.1 Plan Scope Management
Plan Scope Management is the process of creating a scope management plan that documents how the project scope will be defined, validated, and controlled.


The scope management plan is a component of the project or program management plan that describes how the scope will be defined, developed, monitored, controlled, and verified. The development of the scope management plan and the detailing of the project scope begin with the analysis of information contained in the project charter, the latest approved subsidiary plans of the project management plan, historical information contained in the organizational process assets, and any other relevant enterprise environment factors. This plan helps reduce the risk of project scope creep.


Inputs
1) Project management plan
Approved subsidiary plans of the project management plan are used to create the scope management plan and influence the approach taken for planning scope and managing project scope.

2) Project charter
Project charter is used to provide the project context needed to plan the scope management processes. It provides the high level project description and product characteristics from the project statement of work.

Outputs
1) Scope management plan
Scope management plan describes how the scope will be defined, developed, monitored, controlled and verified. Major input into the Develop Project Management Plan process, and the other scope management processes.

2) Requirements management plan
Requirement management plan is a component of the project management plan that describes how requirements will be analyzed, documented, and managed. 



2014년 7월 4일 금요일

4. Project Integration Management (6)

4.6 Close Project or Phase
Close Project or Phase is the process of finalizing all activities across all of the Project management process groups to formally complete the project or phase.


When closing the project, Project Manager reviews all prior information from the previous phase closures to ensure that all project work is completed and that the project has met its objectives. Since project scope is measured against the project management plan, the project manager reviews the scope baseline to ensure completion before considering the project closed. Close Project or Phase process also establishes the procedures to investigate and document the reason for actions taken if a project is terminated before completion. In order to successfully achieve this, the project manager needs to engage all the proper stakeholders in the process.

Inputs
1) Project management plan: agreement between the project manager and project sponsor, defining what constitutes project completion

2) Accepted deliverables: include approved product specifications, delivery receipts and work performance documents, Partial or interim deliverables may also be included for phased or cancelled projects.

3) Organizational process assets: OPA that can influence the Close Project or Phase process incl.
- Project or phase closure guidelines or requirements (e.g. admin procedures, project audits etc.)
- Historical information and lessons learned knowledge base (e.g. project records and documents etc.)

Tools & Techniques
1) Expert judgement: applied when performing administrative closure activities, these exports ensure that project or phase closure is performed to the appropriate standards.

2) Analytical technique:examples of analytical techniques used in project closeout are
- Regression analysis
- Trend analysis

3) Meetings: may be face-to-face, virtual, formal or informal. Types of meetings include lessons learned, closeout, user group and review meetings.

Outputs
1) Final product, service or result transition: this output refers to the transition of the final product, service or result that the project was authorized to produce.

2) OPA updates: OPA that are updated as a result of the Close Project or Phase process include project files, closure documents and historical information