Android Coverflow Widget
http://www.inter-fuser.com/2010/01/android-coverflow-widget.html
Android Coverflow Widget V2
http://www.inter-fuser.com/2010/02/android-coverflow-widget-v2.html
Android Coverflow Widget V2
It's been a while now and I've been pretty busy with life, work, and other things, but at last here's a new version of the coverflow widget that I released a while back. There's not really much new functionality here, but I have cut down the amount of code needed by a lot. Gone are the CoverAbsSpinner and the CoverAdapterView classes and now we are left with just the CoverFlow class weighing in at less than 200 lines of code. Of course, you still have to instantiate it and populate it using an ImageAdapter so I'll also include the activity class for doing those tasks as well.
Background
The basic idea is that the Coverflow widget works very much like the standard Android Gallery widget, but with the addition of the rotation of the images. For more background information on the Coverflow widget see my original post here.
How to use
In your Android project create a package called com.example.coverflow, and in this place the CoverFlow class. Now all you need is an activity to instantiate the Coverflow widget in this example the activity class is called CoverflowExample. CoverFlowExample simply extends Activity and instantiates a Coverflow class in it's onCreate method. It also has an internal Class, ImageAdapter which we use as the adapter for the Coverflow widget, much as we would for a Gallery widget. It is also possible to use the Coverflow widget when it is specified in an XML layout file.
The CoverFlow and CoverflowExample classes are here:
/*
* Copyright (C) 2010 Neil Davies
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This code is base on the Android Gallery widget and was Created
* by Neil Davies neild001 'at' gmail dot com to be a Coverflow widget
*
* @author Neil Davies
*/
package com.example.coverflow;
import android.content.Context;
import android.graphics.Camera;
import android.graphics.Matrix;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.Transformation;
import android.widget.Gallery;
import android.widget.ImageView;
public class CoverFlow extends Gallery {
/**
* Graphics Camera used for transforming the matrix of ImageViews
*/
private Camera mCamera = new Camera();
/**
* The maximum angle the Child ImageView will be rotated by
*/
private int mMaxRotationAngle = 60;
/**
* The maximum zoom on the centre Child
*/
private int mMaxZoom = -120;
/**
* The Centre of the Coverflow
*/
private int mCoveflowCenter;
public CoverFlow(Context context) {
super(context);
this.setStaticTransformationsEnabled(true);
}
public CoverFlow(Context context, AttributeSet attrs) {
super(context, attrs);
this.setStaticTransformationsEnabled(true);
}
public CoverFlow(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
this.setStaticTransformationsEnabled(true);
}
/**
* Get the max rotational angle of the image
* @return the mMaxRotationAngle
*/
public int getMaxRotationAngle() {
return mMaxRotationAngle;
}
/**
* Set the max rotational angle of each image
* @param maxRotationAngle the mMaxRotationAngle to set
*/
public void setMaxRotationAngle(int maxRotationAngle) {
mMaxRotationAngle = maxRotationAngle;
}
/**
* Get the Max zoom of the centre image
* @return the mMaxZoom
*/
public int getMaxZoom() {
return mMaxZoom;
}
/**
* Set the max zoom of the centre image
* @param maxZoom the mMaxZoom to set
*/
public void setMaxZoom(int maxZoom) {
mMaxZoom = maxZoom;
}
/**
* Get the Centre of the Coverflow
* @return The centre of this Coverflow.
*/
private int getCenterOfCoverflow() {
return (getWidth() - getPaddingLeft() - getPaddingRight()) / 2 + getPaddingLeft();
}
/**
* Get the Centre of the View
* @return The centre of the given view.
*/
private static int getCenterOfView(View view) {
return view.getLeft() + view.getWidth() / 2;
}
/**
* {@inheritDoc}
*
* @see #setStaticTransformationsEnabled(boolean)
*/
protected boolean getChildStaticTransformation(View child, Transformation t) {
final int childCenter = getCenterOfView(child);
final int childWidth = child.getWidth() ;
int rotationAngle = 0;
t.clear();
t.setTransformationType(Transformation.TYPE_MATRIX);
if (childCenter == mCoveflowCenter) {
transformImageBitmap((ImageView) child, t, 0);
} else {
rotationAngle = (int) (((float) (mCoveflowCenter - childCenter)/ childWidth) * mMaxRotationAngle);
if (Math.abs(rotationAngle) > mMaxRotationAngle) {
rotationAngle = (rotationAngle < 0) ? -mMaxRotationAngle : mMaxRotationAngle;
}
transformImageBitmap((ImageView) child, t, rotationAngle);
}
return true;
}
/**
* This is called during layout when the size of this view has changed. If
* you were just added to the view hierarchy, you're called with the old
* values of 0.
*
* @param w Current width of this view.
* @param h Current height of this view.
* @param oldw Old width of this view.
* @param oldh Old height of this view.
*/
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
mCoveflowCenter = getCenterOfCoverflow();
super.onSizeChanged(w, h, oldw, oldh);
}
/**
* Transform the Image Bitmap by the Angle passed
*
* @param imageView ImageView the ImageView whose bitmap we want to rotate
* @param t transformation
* @param rotationAngle the Angle by which to rotate the Bitmap
*/
private void transformImageBitmap(ImageView child, Transformation t, int rotationAngle) {
mCamera.save();
final Matrix imageMatrix = t.getMatrix();;
final int imageHeight = child.getLayoutParams().height;;
final int imageWidth = child.getLayoutParams().width;
final int rotation = Math.abs(rotationAngle);
mCamera.translate(0.0f, 0.0f, 100.0f);
//As the angle of the view gets less, zoom in
if ( rotation < mMaxRotationAngle ) {
float zoomAmount = (float) (mMaxZoom + (rotation * 1.5));
mCamera.translate(0.0f, 0.0f, zoomAmount);
}
mCamera.rotateY(rotationAngle);
mCamera.getMatrix(imageMatrix);
imageMatrix.preTranslate(-(imageWidth/2), -(imageHeight/2));
imageMatrix.postTranslate((imageWidth/2), (imageHeight/2));
mCamera.restore();
}
}
// -----------------------------------------
/*
* Copyright (C) 2010 Neil Davies
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This code is base on the Android Gallery widget and was Created
* by Neil Davies neild001 'at' gmail dot com to be a Coverflow widget
*
* @author Neil Davies
*/
package com.example.coverflow;
import java.io.FileInputStream;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PorterDuffXfermode;
import android.graphics.Bitmap.Config;
import android.graphics.PorterDuff.Mode;
import android.graphics.Shader.TileMode;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
public class CoverFlowExample extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
CoverFlow coverFlow;
coverFlow = new CoverFlow(this);
coverFlow.setAdapter(new ImageAdapter(this));
ImageAdapter coverImageAdapter = new ImageAdapter(this);
//coverImageAdapter.createReflectedImages();
coverFlow.setAdapter(coverImageAdapter);
coverFlow.setSpacing(-25);
coverFlow.setSelection(4, true);
coverFlow.setAnimationDuration(1000);
setContentView(coverFlow);
}
public class ImageAdapter extends BaseAdapter {
int mGalleryItemBackground;
private Context mContext;
private FileInputStream fis;
private Integer[] mImageIds = {
R.drawable.kasabian_kasabian,
R.drawable.starssailor_silence_is_easy,
R.drawable.killers_day_and_age,
R.drawable.garbage_bleed_like_me,
R.drawable.death_cub_for_cutie_the_photo_album,
R.drawable.kasabian_kasabian,
R.drawable.massive_attack_collected,
R.drawable.muse_the_resistance,
R.drawable.starssailor_silence_is_easy
};
private ImageView[] mImages;
public ImageAdapter(Context c) {
mContext = c;
mImages = new ImageView[mImageIds.length];
}
public boolean createReflectedImages() {
//The gap we want between the reflection and the original image
final int reflectionGap = 4;
int index = 0;
for (int imageId : mImageIds) {
Bitmap originalImage = BitmapFactory.decodeResource(getResources(),
imageId);
int width = originalImage.getWidth();
int height = originalImage.getHeight();
//This will not scale but will flip on the Y axis
Matrix matrix = new Matrix();
matrix.preScale(1, -1);
//Create a Bitmap with the flip matrix applied to it.
//We only want the bottom half of the image
Bitmap reflectionImage = Bitmap.createBitmap(originalImage, 0, height/2, width, height/2, matrix, false);
//Create a new bitmap with same width but taller to fit reflection
Bitmap bitmapWithReflection = Bitmap.createBitmap(width
, (height + height/2), Config.ARGB_8888);
//Create a new Canvas with the bitmap that's big enough for
//the image plus gap plus reflection
Canvas canvas = new Canvas(bitmapWithReflection);
//Draw in the original image
canvas.drawBitmap(originalImage, 0, 0, null);
//Draw in the gap
Paint deafaultPaint = new Paint();
canvas.drawRect(0, height, width, height + reflectionGap, deafaultPaint);
//Draw in the reflection
canvas.drawBitmap(reflectionImage,0, height + reflectionGap, null);
//Create a shader that is a linear gradient that covers the reflection
Paint paint = new Paint();
LinearGradient shader = new LinearGradient(0, originalImage.getHeight(), 0,
bitmapWithReflection.getHeight() + reflectionGap, 0x70ffffff, 0x00ffffff,
TileMode.CLAMP);
//Set the paint to use this shader (linear gradient)
paint.setShader(shader);
//Set the Transfer mode to be porter duff and destination in
paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
//Draw a rectangle using the paint with our linear gradient
canvas.drawRect(0, height, width,
bitmapWithReflection.getHeight() + reflectionGap, paint);
ImageView imageView = new ImageView(mContext);
imageView.setImageBitmap(bitmapWithReflection);
imageView.setLayoutParams(new CoverFlow.LayoutParams(120, 180));
imageView.setScaleType(ScaleType.MATRIX);
mImages[index++] = imageView;
}
return true;
}
public int getCount() {
return mImageIds.length;
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
//Use this code if you want to load from resources
ImageView i = new ImageView(mContext);
i.setImageResource(mImageIds[position]);
i.setLayoutParams(new CoverFlow.LayoutParams(130, 130));
i.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
//Make sure we set anti-aliasing otherwise we get jaggies
BitmapDrawable drawable = (BitmapDrawable) i.getDrawable();
drawable.setAntiAlias(true);
return i;
//return mImages[position];
}
/** Returns the size (0.0f to 1.0f) of the views
* depending on the 'offset' to the center. */
public float getScale(boolean focused, int offset) {
/* Formula: 1 / (2 ^ offset) */
return Math.max(0, 1.0f / (float)Math.pow(2, Math.abs(offset)));
}
}
}
Code explanation
The CoverflowExample Code contains some extra code for creating reflections of the images, but apart from this is a standard activity class of the kind used with the Gallery widget.
The CoverFlow class extends the Gallery widget , but now we override a few methods to allow us to transform the images before they are displayed. The most important method that we override is the getChildStaticTransformation method. Here I have to say thank you to a user called Nerdrow on the Android developers group who first showed me an example of overriding this method. By setting setStaticTransformationsEnabled in the constructors, we are telling the parent ViewGroup of the Coverflow class to invoke getChildStaticTransformation every time one of our images in drawn. In getChildStaticTransformation we simply calculate and apply a rotation and scale to the ImageView depending on it's position relative to the centre of the Coverflow widget. We also override the onSizeChanged method. This method is called every time the widget changes size e.g. when we change the orientation of the phone from portrait to landscape. In the onSizeChanged method we just get the centre position of the coverflow widget. There are also a few parameters that we can set, mZoomMax controls the maximum zoom of the central image and mMaxRotationAngle sets the maximum rotation angle of each image.
Thanks
Lastly, I just wanted to say thanks to everyone who has commented and given me feedback on the coverflow widget. It's be really positive and great to hear that people have got it working successfully on a range of devices such as the HTC magic , Motorolla droid and Nexus 1. There's still more to do for the coverflow widget and I'll release new version as and when I make updates. If anyone has anymore suggests for cool widgets or enhancements to this Coverflow widget then please do get in touch.
-----
Great work!
Cheers,
June
목요일, 8월 12, 2010
Win32-GuiTest - Perl GUI Test Utilities
Win32-GuiTest - Perl GUI Test Utilities
Source: http://search.cpan.org/~karasik/Win32-GuiTest-1.57/
SYNOPSIS
use Win32::GuiTest qw(FindWindowLike GetWindowText
SetForegroundWindow SendKeys);
$Win32::GuiTest::debug = 0; # Set to "1" to enable verbose mode
my @windows = FindWindowLike(0, "^Microsoft Excel", "^XLMAIN\$");
for (@windows) {
print "$_>\t'", GetWindowText($_), "'\n";
SetForegroundWindow($_);
SendKeys("%fn~a{TAB}b{TAB}{BS}{DOWN}");
}
DESCRIPTION
Most GUI test scripts I have seen/written for Win32 use some variant of
Visual Basic (e.g. MS-VB or MS-Visual Test). The main reason is the
availability of the SendKeys function.
...
-----
This is a great utilities. we can handling a win32 app GUI as a perl script.
This means you don't need to yourself test anymore for app test (i.e., in QA).
Just make a script then do the test. easy ?
visit above the site.
Cheers,
June
Source: http://search.cpan.org/~karasik/Win32-GuiTest-1.57/
SYNOPSIS
use Win32::GuiTest qw(FindWindowLike GetWindowText
SetForegroundWindow SendKeys);
$Win32::GuiTest::debug = 0; # Set to "1" to enable verbose mode
my @windows = FindWindowLike(0, "^Microsoft Excel", "^XLMAIN\$");
for (@windows) {
print "$_>\t'", GetWindowText($_), "'\n";
SetForegroundWindow($_);
SendKeys("%fn~a{TAB}b{TAB}{BS}{DOWN}");
}
DESCRIPTION
Most GUI test scripts I have seen/written for Win32 use some variant of
Visual Basic (e.g. MS-VB or MS-Visual Test). The main reason is the
availability of the SendKeys function.
...
-----
This is a great utilities. we can handling a win32 app GUI as a perl script.
This means you don't need to yourself test anymore for app test (i.e., in QA).
Just make a script then do the test. easy ?
visit above the site.
Cheers,
June
수요일, 8월 11, 2010
[Android] MediaPlayer Time Format
MediaPlayer Time Format
// See below site
http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob_plain;f=core/java/android/widget/MediaController.java;hb=71beeab14a891297b6658c4aeb47557083091aa1
int position = mediaPlayer.getCurrentPosition();
int duration = mediaPlayer.getDuration();
int timeMs = position;
or
int timeMs = duration;
int totalSeconds = timeMs / 1000;
int seconds = totalSeconds % 60;
int minutes = (totalSeconds / 60) % 60;
int hours = totalSeconds / 3600;
-----
Cheers,
June
// See below site
http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob_plain;f=core/java/android/widget/MediaController.java;hb=71beeab14a891297b6658c4aeb47557083091aa1
int position = mediaPlayer.getCurrentPosition();
int duration = mediaPlayer.getDuration();
int timeMs = position;
or
int timeMs = duration;
int totalSeconds = timeMs / 1000;
int seconds = totalSeconds % 60;
int minutes = (totalSeconds / 60) % 60;
int hours = totalSeconds / 3600;
-----
Cheers,
June
금요일, 8월 06, 2010
[Android] Resize SurfaceView
Android Resize SurfaceView
:: in Activity Java Source Code
// Get SurfaceView LayoutParams info
android.view.ViewGroup.LayoutParams lp = m_SurfaceView.getLayoutParams();
// Set to params
lp.width = 320;
lp.height = 240;
// Apply to new dimension
m_SurfaceView.setLayoutParams( lp );
// Set left, top margin
int l = (getWindowManager().getDefaultDisplay().getWidth() - lp.width) / 2;
int t = (getWindowManager().getDefaultDisplay().getHeight() - lp.height) / 2;
((android.widget.RelativeLayout.LayoutParams)m_SurfaceView.getLayoutParams()).setMargins( l, t, 0, 0 );
// Restore to Full size
/*
lp.width = getWindowManager().getDefaultDisplay().getWidth();
lp.height = getWindowManager().getDefaultDisplay().getHeight();
m_SurfaceView.setLayoutParams( lp );
((android.widget.RelativeLayout.LayoutParams)m_SurfaceView.getLayoutParams()).setMargins( 0, 0, 0, 0 );
*/
-----
Cheers,
June
:: in Activity Java Source Code
// Get SurfaceView LayoutParams info
android.view.ViewGroup.LayoutParams lp = m_SurfaceView.getLayoutParams();
// Set to params
lp.width = 320;
lp.height = 240;
// Apply to new dimension
m_SurfaceView.setLayoutParams( lp );
// Set left, top margin
int l = (getWindowManager().getDefaultDisplay().getWidth() - lp.width) / 2;
int t = (getWindowManager().getDefaultDisplay().getHeight() - lp.height) / 2;
((android.widget.RelativeLayout.LayoutParams)m_SurfaceView.getLayoutParams()).setMargins( l, t, 0, 0 );
// Restore to Full size
/*
lp.width = getWindowManager().getDefaultDisplay().getWidth();
lp.height = getWindowManager().getDefaultDisplay().getHeight();
m_SurfaceView.setLayoutParams( lp );
((android.widget.RelativeLayout.LayoutParams)m_SurfaceView.getLayoutParams()).setMargins( 0, 0, 0, 0 );
*/
-----
Cheers,
June
목요일, 8월 05, 2010
[Android] Show or Hide Panel layout on SurfaceView such as MediaController layout
Show or Hide Panel layout on SurfaceView such as MediaController layout
// NOTE: You have to simple layout that
// LinearLayout_MyPanel(layout_width="fill_parent", layout_height="50dp", ...) or whatever
// in order to applying below code.
// Show Panel layout on SurfaceView
private boolean ShowMyPanel(boolean isRunnable) {
Log.d( "FUNC", "ShowMyPanel()" );
boolean ret = true;
android.widget.LinearLayout rl = (android.widget.LinearLayout)findViewById( R.id.LinearLayout_MyPanel );
if( rl.getVisibility() != rl.VISIBLE ) {
if( isRunnable )
return false;
rl.setVisibility( 0 );
ret = true;
Log.d( "LOG", "Show" );
}
else {
rl.setVisibility( 4 );
ret = false;
Log.d( "LOG", "Hidden" );
}
//rl.invalidate();
return ret;
}
// SurfaceView Touch Event
// Show or Hide the Panel layout on SurfaceView after 3 seconds
View.OnClickListener surfaceViewListener = new View.OnClickListener() {
Handler handlerMyPanel = null;
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
//Toast.makeText( myClass.this, "SurfaceView...", Toast.LENGTH_LONG ).show();
Log.d( "LOG", "SurfaceView Touch Event" );
/*
android.widget.LinearLayout rl = (android.widget.LinearLayout)findViewById( R.id.LinearLayout_MyPanel );
if( rl.getVisibility() != rl.VISIBLE )
rl.setVisibility( 0 );
else
rl.setVisibility( 4 );
//rl.invalidate();
*/
if( !ShowMyPanel(false) )
return;
if( handlerMyPanel != null ) {
Log.d( "LOG", "handlerMyPanel != null" );
handlerMyPanel.removeCallbacksAndMessages( null );
handlerMyPanel = null;
}
handlerMyPanel = new Handler();
handlerMyPanel.postDelayed( new Runnable() {
public void run() {
Log.d( "RUNNABLE", "MyPanel start" );
ShowMyPanel(true);
Log.d( "THREAD", "MyPanel finish" );
}
}, 3000
);
}
};
m_SurfaceView.setOnClickListener( surfaceViewListener );
-----
Cheers,
June
// NOTE: You have to simple layout that
// LinearLayout_MyPanel(layout_width="fill_parent", layout_height="50dp", ...) or whatever
// in order to applying below code.
// Show Panel layout on SurfaceView
private boolean ShowMyPanel(boolean isRunnable) {
Log.d( "FUNC", "ShowMyPanel()" );
boolean ret = true;
android.widget.LinearLayout rl = (android.widget.LinearLayout)findViewById( R.id.LinearLayout_MyPanel );
if( rl.getVisibility() != rl.VISIBLE ) {
if( isRunnable )
return false;
rl.setVisibility( 0 );
ret = true;
Log.d( "LOG", "Show" );
}
else {
rl.setVisibility( 4 );
ret = false;
Log.d( "LOG", "Hidden" );
}
//rl.invalidate();
return ret;
}
// SurfaceView Touch Event
// Show or Hide the Panel layout on SurfaceView after 3 seconds
View.OnClickListener surfaceViewListener = new View.OnClickListener() {
Handler handlerMyPanel = null;
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
//Toast.makeText( myClass.this, "SurfaceView...", Toast.LENGTH_LONG ).show();
Log.d( "LOG", "SurfaceView Touch Event" );
/*
android.widget.LinearLayout rl = (android.widget.LinearLayout)findViewById( R.id.LinearLayout_MyPanel );
if( rl.getVisibility() != rl.VISIBLE )
rl.setVisibility( 0 );
else
rl.setVisibility( 4 );
//rl.invalidate();
*/
if( !ShowMyPanel(false) )
return;
if( handlerMyPanel != null ) {
Log.d( "LOG", "handlerMyPanel != null" );
handlerMyPanel.removeCallbacksAndMessages( null );
handlerMyPanel = null;
}
handlerMyPanel = new Handler();
handlerMyPanel.postDelayed( new Runnable() {
public void run() {
Log.d( "RUNNABLE", "MyPanel start" );
ShowMyPanel(true);
Log.d( "THREAD", "MyPanel finish" );
}
}, 3000
);
}
};
m_SurfaceView.setOnClickListener( surfaceViewListener );
-----
Cheers,
June
토요일, 7월 31, 2010
DPCs high CPU usage (동영상 재생시 CPU 100% 점유율)
DPCs high CPU usage (동영상 재생시 CPU 100% 점유율)
If you found your CPU usage is more than 40%
when playing video(no requires high performance) file on Windows xx then,
checks that DPCs process in procexp (you can download this at http://technet.microsoft.com/en-us/sysinternals/bb896653.aspx ).
[Solution]
Source: http://oshiete.goo.ne.jp/qa/3288831.html
This great solution is works for me... ^^
I've had a stuck that CPU overloads when video file playback every time.
then found solution. (see the above quotation)
Just set "ProcessorAffinityMask" to zero in ([HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services/NDIS/Parameters]
June
If you found your CPU usage is more than 40%
when playing video(no requires high performance) file on Windows xx then,
checks that DPCs process in procexp (you can download this at http://technet.microsoft.com/en-us/sysinternals/bb896653.aspx ).
[Solution]
Source: http://oshiete.goo.ne.jp/qa/3288831.html
(3)解決策Translate Japanese to English through Google Translation:
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\NDIS\Parameters
にあるProcessorAffinityMaskの値を0にする(無ければ追加)して再起動。割り込みを処理したCPUが、そのCPUに対応するDPCの処理も実行される。1つまたは複数のネットワークインタフェースカードが特定のCPUに固定されないようになる。その結果、割り込みとネットワークインタフェースカードで生成されるDPCに対するCPUの処理が改善される。再発の際は再度同作業を行う。一度試してみてください。改善されるはずです。基本的にスリープ時に起こりがちな現象ですからMSではビスタはスリープを推奨されていますが、シャットダウンを基本にするのも一つの手です。(苦笑)
(3) solutionHKEY_LOCAL_MACHINE \ System \ CurrentControlSet \ Services \ NDIS \ ParametersProcessorAffinityMask in value to zero (if no additional) and reboot. CPU interrupts are processed, the CPU can be executed corresponding to the DPC process. One or more specific network interface 1 CPU will not be fixed so. As a result, the interrupt generated by the DPC for CPU and network interface is improved handling. When do the re-recurrence. Please try it once. Should be improved. It is prone to symptoms during sleep in the essentially MS Vista is recommended, but sleep is also a hand to shut down the base. (Laughs)
This great solution is works for me... ^^
I've had a stuck that CPU overloads when video file playback every time.
So, i've tried delete video codecs, registry key ([HKEY_LOCAL_MACHINE/SOFTWARE/Classes/CLSID] {87D62D94-71B3-4b9a-9489-5FE6850DC73E}InProcServer32) and to install another player, checks system informations, ... and so forth. (-_-;).
So, i've tried find a process for details which have a high CPU usage through "procexp" application. It was DPCs process.
But i couldn't get any effects despite try these.
(에휴... -_-;;;)
then found solution. (see the above quotation)
Just set "ProcessorAffinityMask" to zero in ([HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services/NDIS/Parameters]
"ProcessorAffinityMask"=dword:ffffffff).
Finally i've a peace... lol
try this...
-----
Cheers,June
토요일, 7월 24, 2010
Freez 3GP Video Converter 2.0 Registration
Freez 3GP Video Converter 2.0 Registration
Source: http://freemedia.realgage.com/freez-3gp-video-converter.html
I've found this.
Damn... very useful tip...
-----
Cheers,
June
Source: http://freemedia.realgage.com/freez-3gp-video-converter.html
Dr.Edelon Says:
July 24th, 2008 at 7:21 am
for malik:
u don’t need reg-code! to use for free this soft u must delite(or set to 0) some varible in registry
part of REG file for this:
[HKEY_CURRENT_USER\Software\Microsoft\MSUpdate]
“3gpCoun”=dword:00000000
and for other software of Freeze this workebele!
enjoy!
I've found this.
Damn... very useful tip...
-----
Cheers,
June
금요일, 7월 23, 2010
“선한 앨리스가 만드는 SNS, 상상했더니”
“선한 앨리스가 만드는 SNS, 상상했더니”
Source: http://www.bloter.net/archives/35248
간만에 신선한 아이디어를 주었다.
이런 신선한 상상력(?)은 나에게 큰 활력을 불어 넣어 주는 것 같아 참 좋다.
-----
Cheers,
June
Source: http://www.bloter.net/archives/35248
앨리스가 집에 가다가 지갑을 잃어버렸다. 앨리스는 이 사실을 알고 슬픔에 빠졌다.
지갑을 어떡하면 찾을 수 있을까. 고민하는 앨리스 앞에 한 남자가 나타났다.
길에서 우연히 앨리스 지갑을 주워 연락처를 보고 전화를 걸었고,
앨리스와 연락이 닿아 나타난 것이다. 앨리스는 말했다. “어떻게 보답해야 하죠?”
남자는 종이 한 장을 남기고 자리를 떠났다. 어떤 종이일까. 앨리스는 궁금했다.
종이엔 이렇게 적혀 있었다. ‘만약 당신이 선행을 받았다면, 아래 웹사이트를 방문해주세요’
앨리스는 웹사이트에 접속해 종이에 적힌 일련번호를 입력했다.
그랬더니 종이가 세상을 돌아다닌 발자취가 나타났다. 앨리스는 감동을 받았다.
‘나도 이 종이를 버리지 않고 다른 사람에게 전달해야지.’
간만에 신선한 아이디어를 주었다.
이런 신선한 상상력(?)은 나에게 큰 활력을 불어 넣어 주는 것 같아 참 좋다.
-----
Cheers,
June
[Android] Lifecycle
Android Lifecycle of Activity
:: LANDSCAPE mode
[Incoming Call Event]
-> public void onSaveInstanceState(Bundle savedInstanceState) {}
[Restore]
-> public void onConfigurationChanged(Configuration newConfig) {}
:: Portrait mode
[Incoming Call Event]
-> public void onSaveInstanceState(Bundle savedInstanceState) {}
[Restore]
-> public void onRestoreInstanceState(Bundle savedInstanceState) {}
for Example,
- Lifecycle of VideoView and SurfaceView (Landscape, Portrait)
:: VideoView(with MediaController; LANDSCAPE mode)
[Incoming Call Event]
-> public void onSaveInstanceState(Bundle savedInstanceState) {}
[Restore]
-> public void onConfigurationChanged(Configuration newConfig) {}
:: SurfaceView(with MediaPlayer; Portrait mode)
[Incoming Call Event]
-> public void onSaveInstanceState(Bundle savedInstanceState) {}
[Restore]
-> public void onRestoreInstanceState(Bundle savedInstanceState) {}
-----
Cheers,
June
:: LANDSCAPE mode
[Incoming Call Event]
-> public void onSaveInstanceState(Bundle savedInstanceState) {}
[Restore]
-> public void onConfigurationChanged(Configuration newConfig) {}
:: Portrait mode
[Incoming Call Event]
-> public void onSaveInstanceState(Bundle savedInstanceState) {}
[Restore]
-> public void onRestoreInstanceState(Bundle savedInstanceState) {}
for Example,
- Lifecycle of VideoView and SurfaceView (Landscape, Portrait)
:: VideoView(with MediaController; LANDSCAPE mode)
[Incoming Call Event]
-> public void onSaveInstanceState(Bundle savedInstanceState) {}
[Restore]
-> public void onConfigurationChanged(Configuration newConfig) {}
:: SurfaceView(with MediaPlayer; Portrait mode)
[Incoming Call Event]
-> public void onSaveInstanceState(Bundle savedInstanceState) {}
[Restore]
-> public void onRestoreInstanceState(Bundle savedInstanceState) {}
-----
Cheers,
June
목요일, 7월 22, 2010
K-ON! (けいおん!, 2009)
K-ON! (けいおん!, 2009)
Source: http://optsol.tistory.com/81?srchid=BR1http://optsol.tistory.com/81
- 히라사와 유이 독백
-----
이 글 참 마음에 든다.
아직 K-ON! 이라는 Ani 는 보지 못했지만,
꼭 봐야겠다...
Cheers,
June
Source: http://optsol.tistory.com/81?srchid=BR1http://optsol.tistory.com/81
- 히라사와 유이 독백
そう言えば入学式の時もこの道を走った。
- 그러고 보면 입학식 때도 이 길을 달렸어.
何かしなきゃって思いながら、
- 뭔가 해야겠다고 생각하면서,
何をすればいいんだろうって思いながら、
- 무얼 하면 좋을까 생각하면서,
このまま… 大人になっちゃうのかなって思いながら。
- 이대로... 어른이 돼 버리는 걸까 생각하면서.
-----
이 글 참 마음에 든다.
아직 K-ON! 이라는 Ani 는 보지 못했지만,
꼭 봐야겠다...
Cheers,
June
수요일, 7월 21, 2010
[Android] My Tip - SeekBar
My Android Tip
- Use at your own risk! lol, ㅋㅋㅋ
내가 작업한 것 중에서 유용한 Tip 들을 정리 해본다.
// ---------------------------------------------
// :: SeekBar
// ---------------------------------------------
- main.xml
android:layout_width="fill_parent"
android:layout_height="wrap_contents"
android:clickable="true"
android:paddingLeft="5px"
android:paddingRight="5px"
android:maxHeight="20px" // this means ProgressiveBar Height
android:max="1000"
android:progress="0"
android:fitsSystemWindows="true"
android:thumb="@drawable/seekbar_thumb"
android:progressDrawable="@drawable/seekbar"
android:secondaryProgress="0">
- seekbar.xml: Change "(" to "<"
(layer-list xmlns:android="http://schemas.android.com/apk/res/android")
(item android:id="@android:id/background")
(clip android:drawable="@drawable/bg" /)
(/item)
/*
(item android:id="@android:id/secondaryProgress")
(clip android:drawable="@drawable/progress2" /)
(/item)
*/
(item android:id="@android:id/progress")
(clip android:drawable="@drawable/progress" /)
(/item)
(/layer-list)
- seekbar_thumb.xml: Change "(" to "<"
(selector xmlns:android="http://schemas.android.com/apk/res/android")
(item android:state_pressed="true"
android:drawable="@drawable/thumb_button_pressed" /)
(item android:state_focused="true"
android:drawable="@drawable/thumb_button_focused" /)
(item android:state_focused="false"
android:drawable="@drawable/thumb_button_normal" /)
(/selector)
- main.xml
android:layout_width="fill_parent"
android:layout_height="wrap_contents"
android:clickable="true"
android:paddingLeft="5px"
android:paddingRight="5px"
android:maxHeight="20px" // this means ProgressiveBar Height
android:max="1000"
android:progress="0"
android:fitsSystemWindows="true"
android:thumb="@drawable/seekbar_thumb"
android:progressDrawable="@drawable/seekbar"
android:secondaryProgress="0">
- seekbar.xml: Change "(" to "<"
(layer-list xmlns:android="http://schemas.android.com/apk/res/android")
(item android:id="@android:id/background")
(clip android:drawable="@drawable/bg" /)
(/item)
/*
(item android:id="@android:id/secondaryProgress")
(clip android:drawable="@drawable/progress2" /)
(/item)
*/
(item android:id="@android:id/progress")
(clip android:drawable="@drawable/progress" /)
(/item)
(/layer-list)
- seekbar_thumb.xml: Change "(" to "<"
(selector xmlns:android="http://schemas.android.com/apk/res/android")
(item android:state_pressed="true"
android:drawable="@drawable/thumb_button_pressed" /)
(item android:state_focused="true"
android:drawable="@drawable/thumb_button_focused" /)
(item android:state_focused="false"
android:drawable="@drawable/thumb_button_normal" /)
(/selector)
- Thread:
Thread.sleep( 1000 );
if( m_MediaPlayer.isPlaying() == false )
break;
m_Handler.sendMessage( m_Handler.obtainMessage() );
- SeekBar:
// SeekBar
m_SeekBar = (SeekBar)findViewById( R.id.SeekBar01 );
m_SeekBar.setProgress( 0 );
m_SeekBar.setClickable( true );
- Handler:
m_Handler = new Handler() {
public void handleMessage(android.os.Message msg) {
if( (m_MediaPlayer == null) ) {
m_SeekBar.setProgress( 0 );
// something
// ...
return;
}
if( m_MediaPlayer.isPlaying() ) {
int position = m_MediaPlayer.getCurrentPosition();
int duration = m_MediaPlayer.getDuration();
if( m_SeekBar != null ) {
if( duration > 0 ) {
long pos = m_MediaPlayer.getDuration() * position / duration;
m_SeekBar.setProgress( m_MediaPlayer.getCurrentPosition() );
}
// something
// ...
// NOTE: below code are just sample...
// ...
int m = (int) Math.floor(m_MediaPlayer.getCurrentPosition()/(1000*60));
int s = (int) Math.floor((m_MediaPlayer.getCurrentPosition()-(1000*60)*m)/1000);
m_CurrentSec = (m * 60) + s;
String strM = m < 10 ? "0" + Integer.toString( m ) : Integer.toString( m );
String strS = s < 10 ? "0" + Integer.toString( s ) : Integer.toString( s );
m_strCurrentMS = strM + ":" + strS;
Log.d( "THREAD", "Cur = " + m_CurrentSec + ", Duration = " + m_DurationSec );
if( ((m_CurrentSec+1) >= m_DurationSec) || ((m_CurrentSec+1) >= m_DurationSec) ) {
Log.d( "THREAD", "THREAD END..." );
m_strCurrentMS = "00:00";
if( m_MediaPlayer != null ) {
m_MediaPlayer.release();
m_MediaPlayer = null;
}
m_SeekBar.setProgress( 0 ); // reset
// something
// ...
}
}
}
else {
Log.d( "THREAD", "Playing == false" );
m_strCurrentMS = "00:00";
if( m_MediaPlayer != null ) {
m_MediaPlayer.release();
m_MediaPlayer = null;
}
m_SeekBar.setProgress( 0 ); // reset
// something
// ...
}
};
};
- SeekBarListener:
NOTE: http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob_plain;f=core/java/android/widget/MediaController.java;hb=71beeab14a891297b6658c4aeb47557083091aa1
NOTE: http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob_plain;f=core/java/android/widget/MediaController.java;hb=71beeab14a891297b6658c4aeb47557083091aa1
m_SeekBar.setOnSeekBarChangeListener( new OnSeekBarChangeListener() {
public void onStopTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
if( m_MediaPlayer != null )
m_CurrentPosition = m_MediaPlayer.getCurrentPosition();
else
m_SeekBar.setProgress( 0 );
else
m_SeekBar.setProgress( 0 );
}
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
// TODO Auto-generated method stub
if( !fromUser )
return;
if( m_MediaPlayer != null ) {
long duration = m_MediaPlayer.getDuration();
//long newposition = (duration * progress) / 1000L;
long newposition = (duration * progress) / m_MediaPlayer.getDuration();
m_MediaPlayer.seekTo( (int) newposition);
}
}
}
}
);
// ---------------------------------------------
:: Disable SeekBar Touch Event
seekBar.setOnTouchListener(new OnTouchListener() {@Override
public boolean onTouch(View v, MotionEvent event) {
//return false;
return true;
}
});
-----
Cheers,
June
화요일, 7월 13, 2010
[Android] My Tip
My Android Tip
- Use at your own risk! lol, ㅋㅋㅋ
내가 작업한 것 중에서 유용한 Tip 들을 정리 해본다.
// ---------------------------------------------
// :: AndroidManifest.xml
// ---------------------------------------------
* android:sharedUserId="..."
* for Froyo (Android 2.2 API Level 8 ~)
android:installLocation = {
"internalOnly",
"preferExternal",
"auto"
};
android:installLocation="auto"
* android:launchMode="singleTask"
* Prevent to restart Activity Life-Cycle when slide-out QWERTY keypad
* Landscape/Portrait mode event
android:screenOrientation="portrait"
android:configChanges="keyboardHidden|orientation"
* android:theme="@android:style/Theme.Translucent"
// ---------------------------------------------
// ---------------------------------------------
// :: Slide Strings
// ---------------------------------------------
// NOTE: Slide Strings
android:ellipsize = {
"marquee" -> slide
"end" -> "..."
}
android:singleLine="true"
android:ellipsize="marquee"
android:focusable="true"
android:focusableInTouchMode="true"
// main.xml
// ----------------------------------------------
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="12.00sp"
android:gravity="left|center_vertical"
android:height="20.0dp"
android:width="300.0dp"
android:singleLine="true"
android:ellipsize="end"
android:focusable="true"
android:focusableInTouchMode="true"
android:text="">
// TextView Click Event
// ----------------------------------------------
// TextViewStr1
View.OnClickListener TextViewStr1Listener = new View.OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
Log.d( "LOG", "TextViewStr1Listener: focus = false" );
//m_TextViewStr_xxx.clearFocus();
m_TextViewStr1.setEllipsize( TruncateAt.MARQUEE );
m_TextViewStr1.setFocusable( true );
};
};
m_TextViewStr1.setOnClickListener( TextViewStr1Listener );
// Focus
View.OnFocusChangeListener focusTextViewStr1Listener = new View.OnFocusChangeListener() {
public void onFocusChange(View v, boolean hasFocus) {
// TODO Auto-generated method stub
if( hasFocus ) {
Log.d( "LOG", "[FOCUS] TextViewStr1Listener: focus = true" );
//m_TextViewStr_xxx.clearFocus();
m_TextViewStr1.setEllipsize( TruncateAt.MARQUEE );
m_TextViewStr1.setFocusable( true );
}
else {
Log.d( "LOG", "[FOCUS] TextViewStr1Listener: focus = false" );
m_TextViewStr1.setEllipsize( TruncateAt.END );
}
}
};
m_TextViewStr1.setOnFocusChangeListener( focusTextViewStr1Listener );
// ---------------------------------------------
// ---------------------------------------------
// :: ViewControl Visibility
// ---------------------------------------------
// VISIBLE: 0x00000000, INVISBLE: 0x00000004, GONE: 0x00000008
ImageView.setVisibility( 0 );
ImageView.invalidate();
// ---------------------------------------------
// ---------------------------------------------
// :: Events
// ---------------------------------------------
@Override
public void onConfigurationChanged(Configuration newConfig) {
// TODO Auto-generated method stub
super.onConfigurationChanged(newConfig);
Log.d( "FUNC", "onConfigurationChanged" );
if( m_isFullScreen ) {
Log.d( "LOG", "Full Screen -> restore" );
m_isFullScreen = false;
//getWindow().setFlags( WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR, WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR );
//setRequestedOrientation( ActivityInfo.SCREEN_ORIENTATION_PORTRAIT );
getWindow().clearFlags( WindowManager.LayoutParams.FLAG_FULLSCREEN );
}
else {
Log.d( "LOG", "Full Screen" );
m_isFullScreen = true;
getWindow().setFlags( WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN );
}
}
/*
* Activity Status(Activity Lifecycle)
run1: app
onStart -> onResume
run2-1: app -> no work -> home
onSaveInstanceState -> onStop
run2-2: app
onStop -> onRestart -> onStart -> onResume
run3-1: work -> home
onSaveInstanceState -> onStop
run3-2: app
onRestart -> onStart -> onResume
*/
Figure Source: http://developer.android.com/guide/topics/fundamentals.html
// NOTE: Activity LifeCycle method 들의 한글 주석은 출처가 없다.
// onCreate가 호출이 된 후 GUI 상태 복구를 위해서 사용을 하는 함수
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
// savedInstaceState로부터 GUI 상태를 복구를 한다.
// 인수로 받는 Bundle은 onCreate에도 전달된다.
Log.d( "FUNC", "onRestoreInstanceState" );
if( !m_isPauseBySystem ) {
Log.d( "PLAY", "keep state: pauseBySystem == false" );
return;
}
if( m_MediaPlayer == null ) {
Log.d( "LOG", "m_MediaPlayer == null" );
return;
}
else {
Log.d( "LOG", "now restart..." );
m_MediaPlayer.start();
}
}
/// visible lifetime으로 가기 전 activity 처리를 위해서 호출이 된다.
public void onRestart(){
super.onRestart();
// activity가 이미 화면에 보이고
// 여기서 변경된 것들만 읽어들인다.
Log.d( "FUNC", "onRestart" );
}
/// visible lifetime start시에 호출된다.
public void onStart(){
super.onStart();
// 여기서는 activity가 화면에 보이므로
// 필요한 GUI 변경 사항을 적용한다.
Log.d( "FUNC", "onStart" );
}
/// active lifetime시에 호출이 된다.
public void onResume(){
super.onResume();
/// 일시 중지된 모든 GUI update나 thread
/// activity에 의해서 필요하지만 activity가 비활성화
/// 되면서 일시 중단된 것들을 처리를 다시 시작을 할 때
Log.d( "FUNC", "onResume" );
Intent intt = new Intent( "com.android.music.musicservicecommand" );
intt.putExtra( "command", "pause" );
sendBroadcast( intt );
if( !m_isPauseBySystem ) {
Log.d( "PLAY", "keep state: pauseBySystem == false" );
return;
}
if( m_MediaPlayer == null ) {
Log.d( "LOG", "m_MediaPlayer == null" );
return;
}
else {
Log.d( "LOG", "now restart..." );
m_MediaPlayer.start();
}
// for Some Interrupt
// ...
}
/// GUI 상태를 저장을 하기 위해서 호출이된다.
public void onSaveInstanceState(Bundle savedInstanceState){
/// GUI state를 savedInstanceState에 저장한다.
/// 프로세스가 중료되거나 재시작될 경우
/// 이 번들이 onCreate에 전달이 되서
/// 그 시점부터 다시 시작이 될 것이다.
super.onSaveInstanceState(savedInstanceState);
Log.d( "FUNC", "onSaveInstanceState" );
if( m_MediaPlayer == null ) {
Log.d( "LOG", "m_MediaPlayer == null" );
return;
}
else {
Log.d( "LOG", "now pause... by System" );
m_isPauseBySystem = true;
m_MediaPlayer.pause();
// save m_MediaPlayer.getCurrentPosition()...
}
// for Some Interrupt
// ...
}
/// active lefetime 끝에서 호출된다.
public void onPuase() {
super.onPause();
/// activity가 포그라운드 상태가 아닐 경우
/// 다시 update 되거나 필요가 없는 GUI및 Thread
/// 프로세서 점유율이 높이는 처리는 일시 중지한다
Log.d( "FUNC", "onPuase" );
if( m_MediaPlayer == null ) {
Log.d( "LOG", "m_MediaPlayer == null" );
return;
}
else {
m_isPauseBySystem = true;
m_MediaPlayer.pause();
// save m_MediaPlayer.getCurrentPosition()...
}
// Try adding android:configChanges="keyboardHidden|orientation"
// to your AndroidManifest.xml. This tells the system what configuration changes
// you are going to handle yourself
// android:configChanges="keyboardHidden|orientation
// for Some Interrupt
// ...
}
/// visible lifetime 끝에서 호출
public void onStop() {
super.onStop();
/// 남아있는 GUI 업데이트나 쓰레드
/// activity가 화면에 보이지 않을 때 필요치 않은 처리를 일시 중단을 한다.
/// 이 메서드가 호출이 되고 난 뒤에는 프로세스가 종료될 가능성이 있으므로
/// 바뀐 모든 내용과 상태 변화를 지속시킨다.
Log.d( "FUNC", "onStop" );
}
// ---------------------------------------------
// ---------------------------------------------
// :: Surface and Media Player
// ---------------------------------------------
public class TESTAPP extends Activity implements
OnPreparedListener,
SurfaceHolder.Callback {
...
}
...
// SurfaceHolder
public void surfaceChanged(SurfaceHolder surfaceholder, int format, int width, int height) {
Log.d( "FUNC", "surfaceChanged()" );
}
public void surfaceDestroyed(SurfaceHolder surfaceholder) {
Log.d( "FUNC", "surfaceDestroyed()" );
if( m_MediaPlayer == null )
return;
else
m_MediaPlayer.pause();
}
public void surfaceCreated(SurfaceHolder holder) {
Log.d( "FUNC", "surfaceCreated()" );
// mediaPlayer not null ?
// then start to play or pause
// NOTE: update surface
//m_MediaPlayer.setDisplay( holder );
/*
if( m_MediaPlayer == null ) {
Log.d( "LOG", "m_MediaPlayer == null" );
return;
}
else {
Log.d( "LOG", "now Playing..." );
m_MediaPlayer.setDisplay( holder );
//m_MediaPlayer.pause();
//m_MediaPlayer.start();
*/
if( m_MediaPlayer == null ) {
Log.d( "LOG", "null; playing..." );
return;
}
else {
Log.d( "LOG", "playing..." );
/*
if( m_MediaPlayer.getCurrentPosition() == 0 )
m_MediaPlayer.start();
}
else {
Log.d( "LOG", "use the holder" );
m_MediaPlayer.setDisplay( holder );
m_MediaPlayer.start();
*/
m_SurfaceHolder = holder;
// re-create MediaPlayer, reset SurfaceView, seekTo(...), ...
// PlayVideo(); // see below code Video Player with SurfaceView
}
}
}
public void onPrepared(MediaPlayer mediaplayer) {
Log.d( "FUNC", "MediaPlayer: onPrepared()" );
// mediaPlayer not null ?
// then start to play
if( m_MediaPlayer != null )
m_MediaPlayer.start();
else
Log.d( "LOG", "m_MediaPlayer == null" );
}
// ---------------------------------------------
// ---------------------------------------------
// :: Handler
// ---------------------------------------------
private Handler m_Handler = null;
{
m_Handler = new Handler();
m_Handler = new Handler() {
public void handleMessage(android.os.Message msg) {
// update something
// or
// skip
};
};
}
// another
if( m_Handler != null ) {
Log.d( "LOG", "m_Handler != null" );
m_Handler.removeCallbacksAndMessages( null );
m_Handler = null;
}
m_Handler = new Handler();
m_Handler.postDelayed( new Runnable() {
public void run() {
Log.d( "RUNNABLE", "start" );
// Something...
Log.d( "THREAD", "finish" );
}
}, 5000
);
or
m_Handler = new Handler() {
public void handleMessage(android.os.Message msg) {
Log.d( "FUNC", "HANDLER: handleMessage()" );
switch( msg.what ) {
case 0:
// Something
break;
}
};
};
// ---------------------------------------------
// ---------------------------------------------
// :: Thread Start and Stop
// ---------------------------------------------
private void threadStop() {
Log.d( "FUNC", "threadStop()" );
m_ThreadRunFlag = false;
m_Thread = null;
}
private void threadStart() {
Log.d( "FUNC", "threadStart()" );
if( m_Thread != null ) {
Log.d( "THREAD", "m_Thread != NULL" );
return;
}
m_ThreadRunFlag = true;
m_Thread = new Thread() {
public void run() {
try {
// checks MediaPlayer Status
//
while( m_ThreadIsRunning == true ) {
Thread.sleep( 1000 );
// checks MediaPlayer Status
//
m_Handler.sendMessage( m_Handler.obtainMessage() );
}
m_ThreadRunFlag = false;
}
catch( Throwable t ) {
m_ThreadRunFlag = false;
}
}
if( m_Thread != null )
m_Thread.start();
else
Log.d( "THREAD", "m_Thread == NULL" );
};
// ---------------------------------------------
// ---------------------------------------------
// :: MessageBox
// ---------------------------------------------
private void dlgFail() {
final Builder winAlert;
Dialog winDialog;
LayoutInflater li = LayoutInflater.from( this );
View viewDlgFail = li.inflate( R.layout.dlgFail, null );
DialogInterface.OnClickListener okListener = new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
// Button 1
if( which == -1 ) {
Log.d( "Button", "Selected Button 1" );
//Toast.makeText( __MyActivity__.this, "Selected Button 1", Toast.LENGTH_LONG ).show();
}
// Button 2
else if( which == -3 ) {
Log.d( "Button", "Selected Button 2" );
//Toast.makeText( __MyActivity__.this, "Selected Button 2", Toast.LENGTH_LONG ).show();
}
// Button 3
else if( which == -2 ) {
Log.d( "Button", "Selected Button 3" );
//Toast.makeText( __MyActivity__.this, "Selected Button 3", Toast.LENGTH_LONG ).show();
}
dialog.cancel();
// Quit
// System.exit( 1 );
return;
}
};
winAlert = new AlertDialog.Builder( this )
.setIcon( R.drawable.icon )
.setTitle( getResources().getString(R.string."__FAIL_MESSAGE_TITLE__") )
.setMessage( testGMP.this.m_strResMsg )
.setPositiveButton( getResources().getString(R.string."__FAIL_MESSAGE_BUTTON_OK__"), okListener )
.setView( viewDlgFail );
winDialog = winAlert.create();
winDialog.show();
}
// ---------------------------------------------
// ---------------------------------------------
// :: Resource to Export
// ---------------------------------------------
// Get current mounted SD card path
String strFilePathExt = Environment.getExternalStorageDirectory().getPath();
String strFilePath = strFilePathExt + "/";
String strFilename = "_export_filename_";
// Get SD card State
Environment.getExternalStorageState()
// Checks Internal Storage Free Space
{
File path = Environment.getDataDirectory();
StatFs stat = new StatFs( path.getPath() );
long blockSize = stat.getBlockSize();
long availableBlocks = stat.getAvailableBlocks();
{
AssetFileDescriptor afd = getResources().openRawResourceFd( R.raw.__RAW_MEDIA_FILE__ );
if( (availableBlocks * blockSize) < afd.getLength() ) {
Toast.makeText( this, getResources().getString(Out of Internal Storage), Toast.LENGTH_LONG ).show();
afd.close();
return;
}
afd.close();
}
}
// Checks Mount State and External Storage Free Space
if( android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED) ) {
File path = Environment.getExternalStorageDirectory();
StatFs stat = new StatFs( path.getPath() );
long blockSize = stat.getBlockSize();
long availableBlocks = stat.getAvailableBlocks();
{
AssetFileDescriptor afd = getResources().openRawResourceFd( R.raw.__RAW_MEDIA_FILE__ );
if( (availableBlocks * blockSize) < afd.getLength() ) {
Toast.makeText( this, getResources().getString("Out of External Storage"), Toast.LENGTH_LONG ).show();
afd.close();
return;
}
afd.close();
}
}
// Resource file to Export to SD card
{
AssetFileDescriptor afd = this.getResources().openRawResourceFd( R.raw.__RAW_MEDIA_FILE__ );
if( (new File(strFilePath + strFilename).exists()) == true ) {
Log.d( "EXPORT", "Exist = " + strFilePath + strFilename + ", " + "Internal Resource File Size = " + afd.getLength() + ", External(Exported) Resource File Size = " + (new File(strFilePath + strFilename).length()) );
if( (new File(strFilePath + strFilename).length()) == afd.getLength()) {
Toast.makeText( this, getResources().getString("File existed already"), Toast.LENGTH_LONG ).show();
afd.close();
return;
}
}
byte[] buf_readBytes = new byte[1024];
int readBytes = 0;
int offset = 0;
int count = 1024;
OutputStream oStream = new FileOutputStream( strFilePath + strFilename );
FileInputStream fis = afd.createInputStream();
while( true ) {
int bytes = fis.read( buf_readBytes );
if( bytes <= 0 ) break;
oStream.write( buf_readBytes, 0, bytes );
}
oStream.flush();
oStream.close();
fis.close();
afd.close();
}
// ---------------------------------------------
// ---------------------------------------------
// :: Use Cache Directory and File
// ---------------------------------------------
private File m_TmpFile = null;
...
@Override
protected void onDestroy() {
super.onDestroy();
try {
if( m_TmpFile != null )
m_TmpFile.delete();
}
catch( Exception e ) {
Log.e( "FUNC", "onDestroy(): error: " + e.getMessage(), e );
}
}
{
try {
AssetFileDescriptor afd = getResources().openRawResourceFd( R.raw.__RAW_MEDIA_FILE__ );
FileInputStream fis = afd.createInputStream();
String strTmpFilename = "";
if( m_TmpFile != null )
m_TmpFile.delete();
Log.d( "CacheFile", "Full Resource Size = " + Long.toString(fis.getChannel().size()) );
Log.d( "CacheFile", "Current Resource Position = " + Long.toString(fis.getChannel().position()) );
Log.d( "CacheFile", "Current Resource Size = " + Long.toString(afd.getLength()) );
{
byte[] buf_readBytesFile = new byte[1024];
File cacheDir = getCacheDir();
String strFilename = "__CACHE_TMP_FILENAME__";
m_TmpFile = File.createTempFile( strFilename, ".tmp", cacheDir );
OutputStream oStream = new FileOutputStream( m_TmpFile );
Log.d( "CacheFile", "CacheTmpFilename = " + m_TmpFile.getPath() );
while( true ) {
int bytes = fis.read( buf_readBytesFile );
if( bytes <= 0 ) break;
oStream.write( buf_readBytesFile, 0, bytes );
}
oStream.flush();
strTmpFilename = m_TmpFile.getAbsolutePath();
oStream.close();
}
Log.d( "CacheFile", "CacheTmpFilename = " + strTmpFilename );
afd.close();
fis.close();
}
catch( Exception e ) {
// ...
}
}
// ---------------------------------------------
// ---------------------------------------------
// :: Play Video
// ---------------------------------------------
// See above code SurfaceView method
public class TESTAPP extends Activity implements
OnPreparedListener,
SurfaceHolder.Callback {
...
}
...
private MediaPlayer m_MediaPlayer = null;
private SurfaceView m_SurfaceView = null;
private SurfaceHolder m_SurfaceHolder = null;
// VideoView
m_VideoView = (VideoView)findViewById( R.id.VideoView01 );
// SurfaceView
m_SurfaceView = (SurfaceView)findViewById( R.id.SurfaceView01 );
m_SurfaceHolder = m_SurfaceView.getHolder();
m_SurfaceHolder.addCallback( this );
m_SurfaceHolder.setType( SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS );
m_SurfaceView.setClickable( false );
// Visibility
// VideoView
//m_VideoView.setVisibility( 0 );
//m_VideoView.invalidate();
// SurfaceView
m_SurfaceView.setVisibility( 0 );
m_SurfaceView.invalidate();
// Button: Play
Button btnPlay = (Button)findViewById( R.id.Button01 );
View.OnClickListener btnPlayListener = new View.OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
if( m_MediaPlayer == null ) {
Log.d( "PLAY", "OK, First time" );
PlayVideo();
}
else {
PlayVideo();
}
}
};
btnPlay.setOnClickListener( btnPlayListener );
public void PlayVideo() {
if( m_MediaPlayer != null )
m_MediaPlayer.release();
m_MediaPlayer = null;
m_MediaPlayer = new MediaPlayer();
AssetFileDescriptor afd = getResources().openRawResourceFd( R.raw.__RAW_MEDIA_FILE__ );
if( m_MediaPlayer == null ) {
Log.d( "MediaPlayer", "m_MediaPlayer == NULL" );
return;
}
// Use ViewoView
/*
if( m_VideoView == null ) {
Log.d( "VideoView", "m_VideoView == NULL" );
return;
}
*/
// Use SurfaceView
if( m_SurfaceView == null ) {
Log.d( "SurfaceView", "m_SurfaceView == NULL" );
return;
}
m_MediaPlayer.setAudioStreamType( AudioManager.STREAM_MUSIC );
m_MediaPlayer.setScreenOnWhilePlaying( true );
try {
m_MediaPlayer.setDataSource( afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength() );
// Use VideoView
//m_VideoView.getHolder().addCallback( this );
//m_MediaPlayer.setDisplay( m_VideoView.getHolder() );
// Use Surface
m_MediaPlayer.setDisplay( m_SurfaceHolder );
m_MediaPlayer.prepare();
}
catch( IllegalStateException e ) {
// ...
}
catch( IOException e ) {
// ...
}
if( m_CurrentPosition > 0 )
m_MediaPlayer.seekTo( m_CurrentPosition );
if( !isPause )
m_MediaPlayer.start();
}
}
if( m_MediaPlayer != null ) {
m_MediaPlayer.release();
m_MediaPlayer = null;
}
// ---------------------------------------------
// ---------------------------------------------
// :: Play Video (VideoView)
// ---------------------------------------------
// VideoView
int m_CurrentPosition = 0;
... onSaveInstanceState( ... ) {
m_VideoView.pause();
m_CurrentPosition = m_VideoView.getCurrentPosition();
}
... onRestoreInstanceState( ... ) {
m_VideoView.seekTo( m_CurrentPosition );
m_VideoView.start();
}
if( m_MediaController == null )
m_MediaController = new MediaController( this );
Uri uriVideo = Uri.parse( "android.resource://com.test.TESTAPP/" + R.raw.xxx );
m_VideoView.setVideoURI( uriVideo );
m_MediaController.setSaveEnabled( true );
m_VideoView.setMediaController( m_MediaController );
m_MediaController.show();
m_VideoView.requestFocus();
m_VIdeoView.start();
// ---------------------------------------------
// ---------------------------------------------
// :: Media Scan (SD card)
// ---------------------------------------------
sendBroadcast( new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://" + Environment.getExternalStorageDirectory())) );
// ---------------------------------------------
// ---------------------------------------------
// :: Restrict characters length (Korean/Japanese)
// - EditText 에서 한글/일본어 입력 시 byte 수 제한하기.
// - 간단한 테스트는 Emulator 에서 일본어 입력기로 해보면 된다.
// ---------------------------------------------
m_Editbox = (EditText)findViewById( R.id.EditText01 );
m_Editbox.addTextChangedListener( new TextWatcher() {
public void onTextChanged(CharSequence s, int start, int before, int count) {
// TODO Auto-generated method stub
//Log.d("LOG", s.toString() );
}
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// TODO Auto-generated method stub
//Log.d("LOG", s.toString() );
}
// byte to int, bytes to hex 는 internet 에서 그냥 찾아서 썼다.
// NOT my code (^^) --------------------
public int getInt(byte[] bytes) {
int newValue = 0;
newValue |= (((int) bytes[0]) << 24) & 0xFF000000;
newValue |= (((int) bytes[1]) << 16) & 0xFF0000;
newValue |= (((int) bytes[2]) << 8) & 0xFF00;
newValue |= (((int) bytes[3])) & 0xFF;
return newValue;
}
public String byteArrayToHex(byte[] ba) {
if (ba == null || ba.length == 0) {
return null;
}
StringBuffer sb = new StringBuffer(ba.length * 2);
String hexNumber;
for (int x = 0; x < ba.length; x++) {
hexNumber = "0" + Integer.toHexString(0xff & ba[x]);
sb.append(hexNumber.substring(hexNumber.length() - 2));
}
return sb.toString();
}
// NOT my code (^^) --------------------
public void afterTextChanged(Editable s) {
// TODO Auto-generated method stub
//Toast.makeText( myTest1App.this, m_Editbox.getText().toString(), Toast.LENGTH_LONG ).show();
// 여기에선 8 bytes 를 제한한다.
// 주의할 점은 한글/일본어는 2 bytes 가 아닌 3 bytes 로 된다.
// 아래 log 에서 해당 문자와 hex code 를 보면 안다.
int max_len = 8; // restrict 8 bytes. (Korean/Japanese may has 3 bytes. NOT 2 bytes.)
if( s.length() > 0 ) {
int c = s.charAt( s.length()-1 );
String str = Character.toString( s.charAt(s.length()-1) );
int cLen = str.length();
Log.d( "LOG", "s len = " + s.toString().getBytes().length + ", s str = " + s.toString() + ", s hex = " + byteArrayToHex(s.toString().getBytes()) );
//Log.d( "LOG", "byte = " + s.toString().getBytes() + ", len = " + cLen + ", ascii = " + s.charAt(0) + ", dec = " + c + ", hex = " + byteArrayToHex(s.toString().getBytes()) );
Log.d( "LOG", "s.charAt(" + (s.length()-1) + ") -> " + ", = " + str + ", len = " + cLen + ", dec = " + c + ", bytes = " + str.getBytes() + ", len = " + str.getBytes().length + ", hex = " + byteArrayToHex(str.getBytes()) );
if( s.toString().getBytes().length > max_len ) {
s.delete( s.length()-1, s.length() );
m_TextView.setText( s.toString() );
}
}
}
}
);
// ---------------------------------------------
// ---------------------------------------------
// :: Indicator: Notification
// ---------------------------------------------
// http://developer.android.com/guide/topics/ui/notifiers/notifications.html
// http://osdir.com/ml/Android-Beginners/2010-07/msg00649.html
// Path: /android-sdk-windows/platforms/android-4/samples/ApiDemos/src/com/example/android/apis/app
// Source: RemoteService.java
// - AndroidManifest.xml
// - < activity ... android:launchMode="singleTask">
//
// Show a notification while this service is running.
private NotificationManager mNM = null;
private void showNotification() {
// Indicator: Notification
if( mNM != null ) {
mNM.cancel( R.string.app_name );
// Use custom view
//mNM.cancel( R.layout.local_service_controller );
}
mNM = (NotificationManager)getSystemService( NOTIFICATION_SERVICE );
// In this sample, we'll use the same text for the ticker and the expanded notification
CharSequence text = getText( R.string.remote_service_started );
// Set the icon, scrolling text and timestamp
//Notification notification = new Notification(R.drawable.stat_sample, text, System.currentTimeMillis() );
Notification notification = new Notification( -1, text, System.currentTimeMillis() );
Intent intent = new Intent( this, testMyActivity.class );
intent.setFlags( Intent.FLAG_ACTIVITY_SINGLE_TOP );
// The PendingIntent to launch our activity if the user selects this notification
PendingIntent contentIntent = PendingIntent.getActivity( this, 0, intent, 0 );
// Set the info for the views that show in the notification panel.
//notification.setLatestEventInfo(this, getText(R.string.local_service_label),
notification.setLatestEventInfo( this, getText(R.string.Info), text, contentIntent );
/*
// Set custom view
* DELETE notification.setLatestEventInfo(...)
RemoteViews contentView = new RemoteViews( getPackageName(), R.layout.local_service_controller );
////contentView.setImageViewResource( R.id.image, R.drawable.notification_image );
////contentView.setTextViewText( R.id.text, "Hello, this message is in a custom expanded view" );
//contentView.setImageViewResource( R.id.image, R.drawable.imagefile );
contentView.setTextViewText( R.id.TextViewIndicator, getText(R.string.app_name) );
notification.contentView = contentView;
// Use custom view
notification.contentIntent = contentIntent;
*/
// Send the notification.
// We use a string id because it is a unique number. We use it later to cancel.
mNM.notify( R.string.remote_service_started, notification );
// Use custom view
//mNM.notify( R.layout.local_service_controller, notification );
}
// Use custom view (ImageView, TextView)
// local_service_controller.xml
// Change (, ) to <, >
(LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:padding="4dip"
android:id="@+id/LinearLayoutIndicator"
android:layout_width="fill_parent" android:layout_height="fill_parent")
(RelativeLayout android:orientation="horizontal"
android:layout_width="fill_parent" android:layout_height="fill_parent")
(TextView
android:id="@+id/TextViewIndicator"
android:layout_width="fill_parent" android:layout_height="wrap_content"
android:layout_weight="0"
android:paddingBottom="4dip"
android:text="local_service_controller")
(/TextView)
(Button android:id="@+id/start"
android:layout_below="@+id/TextViewIndicator"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:text="start_service")
(/Button)
(Button android:id="@+id/stop"
android:layout_below="@+id/TextViewIndicator"
android:layout_toRightOf="@+id/start"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:text="stop_service")
(/Button)
(/RelativeLayout)
(/LinearLayout)
// ---------------------------------------------
-----
Cheers,
June
- Use at your own risk! lol, ㅋㅋㅋ
내가 작업한 것 중에서 유용한 Tip 들을 정리 해본다.
// ---------------------------------------------
// :: AndroidManifest.xml
// ---------------------------------------------
* android:sharedUserId="..."
* for Froyo (Android 2.2 API Level 8 ~)
android:installLocation = {
"internalOnly",
"preferExternal",
"auto"
};
android:installLocation="auto"
* android:launchMode="singleTask"
* Prevent to restart Activity Life-Cycle when slide-out QWERTY keypad
* Landscape/Portrait mode event
android:screenOrientation="portrait"
android:configChanges="keyboardHidden|orientation"
* android:theme="@android:style/Theme.Translucent"
// ---------------------------------------------
// ---------------------------------------------
// :: Slide Strings
// ---------------------------------------------
// NOTE: Slide Strings
android:ellipsize = {
"marquee" -> slide
"end" -> "..."
}
android:singleLine="true"
android:ellipsize="marquee"
android:focusable="true"
android:focusableInTouchMode="true"
// main.xml
// ----------------------------------------------
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="12.00sp"
android:gravity="left|center_vertical"
android:height="20.0dp"
android:width="300.0dp"
android:singleLine="true"
android:ellipsize="end"
android:focusable="true"
android:focusableInTouchMode="true"
android:text="">
// TextView Click Event
// ----------------------------------------------
// TextViewStr1
View.OnClickListener TextViewStr1Listener = new View.OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
Log.d( "LOG", "TextViewStr1Listener: focus = false" );
//m_TextViewStr_xxx.clearFocus();
m_TextViewStr1.setEllipsize( TruncateAt.MARQUEE );
m_TextViewStr1.setFocusable( true );
};
};
m_TextViewStr1.setOnClickListener( TextViewStr1Listener );
// Focus
View.OnFocusChangeListener focusTextViewStr1Listener = new View.OnFocusChangeListener() {
public void onFocusChange(View v, boolean hasFocus) {
// TODO Auto-generated method stub
if( hasFocus ) {
Log.d( "LOG", "[FOCUS] TextViewStr1Listener: focus = true" );
//m_TextViewStr_xxx.clearFocus();
m_TextViewStr1.setEllipsize( TruncateAt.MARQUEE );
m_TextViewStr1.setFocusable( true );
}
else {
Log.d( "LOG", "[FOCUS] TextViewStr1Listener: focus = false" );
m_TextViewStr1.setEllipsize( TruncateAt.END );
}
}
};
m_TextViewStr1.setOnFocusChangeListener( focusTextViewStr1Listener );
// ---------------------------------------------
// ---------------------------------------------
// :: ViewControl Visibility
// ---------------------------------------------
// VISIBLE: 0x00000000, INVISBLE: 0x00000004, GONE: 0x00000008
ImageView.setVisibility( 0 );
ImageView.invalidate();
// ---------------------------------------------
// ---------------------------------------------
// :: Events
// ---------------------------------------------
@Override
public void onConfigurationChanged(Configuration newConfig) {
// TODO Auto-generated method stub
super.onConfigurationChanged(newConfig);
Log.d( "FUNC", "onConfigurationChanged" );
if( m_isFullScreen ) {
Log.d( "LOG", "Full Screen -> restore" );
m_isFullScreen = false;
//getWindow().setFlags( WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR, WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR );
//setRequestedOrientation( ActivityInfo.SCREEN_ORIENTATION_PORTRAIT );
getWindow().clearFlags( WindowManager.LayoutParams.FLAG_FULLSCREEN );
}
else {
Log.d( "LOG", "Full Screen" );
m_isFullScreen = true;
getWindow().setFlags( WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN );
}
}
/*
* Activity Status(Activity Lifecycle)
run1: app
onStart -> onResume
run2-1: app -> no work -> home
onSaveInstanceState -> onStop
run2-2: app
onStop -> onRestart -> onStart -> onResume
run3-1: work -> home
onSaveInstanceState -> onStop
run3-2: app
onRestart -> onStart -> onResume
*/
Figure Source: http://developer.android.com/guide/topics/fundamentals.html
// NOTE: Activity LifeCycle method 들의 한글 주석은 출처가 없다.
// onCreate가 호출이 된 후 GUI 상태 복구를 위해서 사용을 하는 함수
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
// savedInstaceState로부터 GUI 상태를 복구를 한다.
// 인수로 받는 Bundle은 onCreate에도 전달된다.
Log.d( "FUNC", "onRestoreInstanceState" );
if( !m_isPauseBySystem ) {
Log.d( "PLAY", "keep state: pauseBySystem == false" );
return;
}
if( m_MediaPlayer == null ) {
Log.d( "LOG", "m_MediaPlayer == null" );
return;
}
else {
Log.d( "LOG", "now restart..." );
m_MediaPlayer.start();
}
}
/// visible lifetime으로 가기 전 activity 처리를 위해서 호출이 된다.
public void onRestart(){
super.onRestart();
// activity가 이미 화면에 보이고
// 여기서 변경된 것들만 읽어들인다.
Log.d( "FUNC", "onRestart" );
}
/// visible lifetime start시에 호출된다.
public void onStart(){
super.onStart();
// 여기서는 activity가 화면에 보이므로
// 필요한 GUI 변경 사항을 적용한다.
Log.d( "FUNC", "onStart" );
}
/// active lifetime시에 호출이 된다.
public void onResume(){
super.onResume();
/// 일시 중지된 모든 GUI update나 thread
/// activity에 의해서 필요하지만 activity가 비활성화
/// 되면서 일시 중단된 것들을 처리를 다시 시작을 할 때
Log.d( "FUNC", "onResume" );
Intent intt = new Intent( "com.android.music.musicservicecommand" );
intt.putExtra( "command", "pause" );
sendBroadcast( intt );
if( !m_isPauseBySystem ) {
Log.d( "PLAY", "keep state: pauseBySystem == false" );
return;
}
if( m_MediaPlayer == null ) {
Log.d( "LOG", "m_MediaPlayer == null" );
return;
}
else {
Log.d( "LOG", "now restart..." );
m_MediaPlayer.start();
}
// for Some Interrupt
// ...
}
/// GUI 상태를 저장을 하기 위해서 호출이된다.
public void onSaveInstanceState(Bundle savedInstanceState){
/// GUI state를 savedInstanceState에 저장한다.
/// 프로세스가 중료되거나 재시작될 경우
/// 이 번들이 onCreate에 전달이 되서
/// 그 시점부터 다시 시작이 될 것이다.
super.onSaveInstanceState(savedInstanceState);
Log.d( "FUNC", "onSaveInstanceState" );
if( m_MediaPlayer == null ) {
Log.d( "LOG", "m_MediaPlayer == null" );
return;
}
else {
Log.d( "LOG", "now pause... by System" );
m_isPauseBySystem = true;
m_MediaPlayer.pause();
// save m_MediaPlayer.getCurrentPosition()...
}
// for Some Interrupt
// ...
}
/// active lefetime 끝에서 호출된다.
public void onPuase() {
super.onPause();
/// activity가 포그라운드 상태가 아닐 경우
/// 다시 update 되거나 필요가 없는 GUI및 Thread
/// 프로세서 점유율이 높이는 처리는 일시 중지한다
Log.d( "FUNC", "onPuase" );
if( m_MediaPlayer == null ) {
Log.d( "LOG", "m_MediaPlayer == null" );
return;
}
else {
m_isPauseBySystem = true;
m_MediaPlayer.pause();
// save m_MediaPlayer.getCurrentPosition()...
}
// Try adding android:configChanges="keyboardHidden|orientation"
// to your AndroidManifest.xml. This tells the system what configuration changes
// you are going to handle yourself
// android:configChanges="keyboardHidden|orientation
// for Some Interrupt
// ...
}
/// visible lifetime 끝에서 호출
public void onStop() {
super.onStop();
/// 남아있는 GUI 업데이트나 쓰레드
/// activity가 화면에 보이지 않을 때 필요치 않은 처리를 일시 중단을 한다.
/// 이 메서드가 호출이 되고 난 뒤에는 프로세스가 종료될 가능성이 있으므로
/// 바뀐 모든 내용과 상태 변화를 지속시킨다.
Log.d( "FUNC", "onStop" );
}
// ---------------------------------------------
// ---------------------------------------------
// :: Surface and Media Player
// ---------------------------------------------
public class TESTAPP extends Activity implements
OnPreparedListener,
SurfaceHolder.Callback {
...
}
...
// SurfaceHolder
public void surfaceChanged(SurfaceHolder surfaceholder, int format, int width, int height) {
Log.d( "FUNC", "surfaceChanged()" );
}
public void surfaceDestroyed(SurfaceHolder surfaceholder) {
Log.d( "FUNC", "surfaceDestroyed()" );
if( m_MediaPlayer == null )
return;
else
m_MediaPlayer.pause();
}
public void surfaceCreated(SurfaceHolder holder) {
Log.d( "FUNC", "surfaceCreated()" );
// mediaPlayer not null ?
// then start to play or pause
// NOTE: update surface
//m_MediaPlayer.setDisplay( holder );
/*
if( m_MediaPlayer == null ) {
Log.d( "LOG", "m_MediaPlayer == null" );
return;
}
else {
Log.d( "LOG", "now Playing..." );
m_MediaPlayer.setDisplay( holder );
//m_MediaPlayer.pause();
//m_MediaPlayer.start();
*/
if( m_MediaPlayer == null ) {
Log.d( "LOG", "null; playing..." );
return;
}
else {
Log.d( "LOG", "playing..." );
/*
if( m_MediaPlayer.getCurrentPosition() == 0 )
m_MediaPlayer.start();
}
else {
Log.d( "LOG", "use the holder" );
m_MediaPlayer.setDisplay( holder );
m_MediaPlayer.start();
*/
m_SurfaceHolder = holder;
// re-create MediaPlayer, reset SurfaceView, seekTo(...), ...
// PlayVideo(); // see below code Video Player with SurfaceView
}
}
}
public void onPrepared(MediaPlayer mediaplayer) {
Log.d( "FUNC", "MediaPlayer: onPrepared()" );
// mediaPlayer not null ?
// then start to play
if( m_MediaPlayer != null )
m_MediaPlayer.start();
else
Log.d( "LOG", "m_MediaPlayer == null" );
}
// ---------------------------------------------
// ---------------------------------------------
// :: Handler
// ---------------------------------------------
private Handler m_Handler = null;
{
m_Handler = new Handler();
m_Handler = new Handler() {
public void handleMessage(android.os.Message msg) {
// update something
// or
// skip
};
};
}
// another
if( m_Handler != null ) {
Log.d( "LOG", "m_Handler != null" );
m_Handler.removeCallbacksAndMessages( null );
m_Handler = null;
}
m_Handler = new Handler();
m_Handler.postDelayed( new Runnable() {
public void run() {
Log.d( "RUNNABLE", "start" );
// Something...
Log.d( "THREAD", "finish" );
}
}, 5000
);
or
m_Handler = new Handler() {
public void handleMessage(android.os.Message msg) {
Log.d( "FUNC", "HANDLER: handleMessage()" );
switch( msg.what ) {
case 0:
// Something
break;
}
};
};
// ---------------------------------------------
// ---------------------------------------------
// :: Thread Start and Stop
// ---------------------------------------------
private void threadStop() {
Log.d( "FUNC", "threadStop()" );
m_ThreadRunFlag = false;
m_Thread = null;
}
private void threadStart() {
Log.d( "FUNC", "threadStart()" );
if( m_Thread != null ) {
Log.d( "THREAD", "m_Thread != NULL" );
return;
}
m_ThreadRunFlag = true;
m_Thread = new Thread() {
public void run() {
try {
// checks MediaPlayer Status
//
while( m_ThreadIsRunning == true ) {
Thread.sleep( 1000 );
// checks MediaPlayer Status
//
m_Handler.sendMessage( m_Handler.obtainMessage() );
}
m_ThreadRunFlag = false;
}
catch( Throwable t ) {
m_ThreadRunFlag = false;
}
}
if( m_Thread != null )
m_Thread.start();
else
Log.d( "THREAD", "m_Thread == NULL" );
};
// ---------------------------------------------
// ---------------------------------------------
// :: MessageBox
// ---------------------------------------------
private void dlgFail() {
final Builder winAlert;
Dialog winDialog;
LayoutInflater li = LayoutInflater.from( this );
View viewDlgFail = li.inflate( R.layout.dlgFail, null );
DialogInterface.OnClickListener okListener = new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
// Button 1
if( which == -1 ) {
Log.d( "Button", "Selected Button 1" );
//Toast.makeText( __MyActivity__.this, "Selected Button 1", Toast.LENGTH_LONG ).show();
}
// Button 2
else if( which == -3 ) {
Log.d( "Button", "Selected Button 2" );
//Toast.makeText( __MyActivity__.this, "Selected Button 2", Toast.LENGTH_LONG ).show();
}
// Button 3
else if( which == -2 ) {
Log.d( "Button", "Selected Button 3" );
//Toast.makeText( __MyActivity__.this, "Selected Button 3", Toast.LENGTH_LONG ).show();
}
dialog.cancel();
// Quit
// System.exit( 1 );
return;
}
};
winAlert = new AlertDialog.Builder( this )
.setIcon( R.drawable.icon )
.setTitle( getResources().getString(R.string."__FAIL_MESSAGE_TITLE__") )
.setMessage( testGMP.this.m_strResMsg )
.setPositiveButton( getResources().getString(R.string."__FAIL_MESSAGE_BUTTON_OK__"), okListener )
.setView( viewDlgFail );
winDialog = winAlert.create();
winDialog.show();
}
// ---------------------------------------------
// ---------------------------------------------
// :: Resource to Export
// ---------------------------------------------
// Get current mounted SD card path
String strFilePathExt = Environment.getExternalStorageDirectory().getPath();
String strFilePath = strFilePathExt + "/";
String strFilename = "_export_filename_";
// Get SD card State
Environment.getExternalStorageState()
// Checks Internal Storage Free Space
{
File path = Environment.getDataDirectory();
StatFs stat = new StatFs( path.getPath() );
long blockSize = stat.getBlockSize();
long availableBlocks = stat.getAvailableBlocks();
{
AssetFileDescriptor afd = getResources().openRawResourceFd( R.raw.__RAW_MEDIA_FILE__ );
if( (availableBlocks * blockSize) < afd.getLength() ) {
Toast.makeText( this, getResources().getString(Out of Internal Storage), Toast.LENGTH_LONG ).show();
afd.close();
return;
}
afd.close();
}
}
// Checks Mount State and External Storage Free Space
if( android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED) ) {
File path = Environment.getExternalStorageDirectory();
StatFs stat = new StatFs( path.getPath() );
long blockSize = stat.getBlockSize();
long availableBlocks = stat.getAvailableBlocks();
{
AssetFileDescriptor afd = getResources().openRawResourceFd( R.raw.__RAW_MEDIA_FILE__ );
if( (availableBlocks * blockSize) < afd.getLength() ) {
Toast.makeText( this, getResources().getString("Out of External Storage"), Toast.LENGTH_LONG ).show();
afd.close();
return;
}
afd.close();
}
}
// Resource file to Export to SD card
{
AssetFileDescriptor afd = this.getResources().openRawResourceFd( R.raw.__RAW_MEDIA_FILE__ );
if( (new File(strFilePath + strFilename).exists()) == true ) {
Log.d( "EXPORT", "Exist = " + strFilePath + strFilename + ", " + "Internal Resource File Size = " + afd.getLength() + ", External(Exported) Resource File Size = " + (new File(strFilePath + strFilename).length()) );
if( (new File(strFilePath + strFilename).length()) == afd.getLength()) {
Toast.makeText( this, getResources().getString("File existed already"), Toast.LENGTH_LONG ).show();
afd.close();
return;
}
}
byte[] buf_readBytes = new byte[1024];
int readBytes = 0;
int offset = 0;
int count = 1024;
OutputStream oStream = new FileOutputStream( strFilePath + strFilename );
FileInputStream fis = afd.createInputStream();
while( true ) {
int bytes = fis.read( buf_readBytes );
if( bytes <= 0 ) break;
oStream.write( buf_readBytes, 0, bytes );
}
oStream.flush();
oStream.close();
fis.close();
afd.close();
}
// ---------------------------------------------
// ---------------------------------------------
// :: Use Cache Directory and File
// ---------------------------------------------
private File m_TmpFile = null;
...
@Override
protected void onDestroy() {
super.onDestroy();
try {
if( m_TmpFile != null )
m_TmpFile.delete();
}
catch( Exception e ) {
Log.e( "FUNC", "onDestroy(): error: " + e.getMessage(), e );
}
}
{
try {
AssetFileDescriptor afd = getResources().openRawResourceFd( R.raw.__RAW_MEDIA_FILE__ );
FileInputStream fis = afd.createInputStream();
String strTmpFilename = "";
if( m_TmpFile != null )
m_TmpFile.delete();
Log.d( "CacheFile", "Full Resource Size = " + Long.toString(fis.getChannel().size()) );
Log.d( "CacheFile", "Current Resource Position = " + Long.toString(fis.getChannel().position()) );
Log.d( "CacheFile", "Current Resource Size = " + Long.toString(afd.getLength()) );
{
byte[] buf_readBytesFile = new byte[1024];
File cacheDir = getCacheDir();
String strFilename = "__CACHE_TMP_FILENAME__";
m_TmpFile = File.createTempFile( strFilename, ".tmp", cacheDir );
OutputStream oStream = new FileOutputStream( m_TmpFile );
Log.d( "CacheFile", "CacheTmpFilename = " + m_TmpFile.getPath() );
while( true ) {
int bytes = fis.read( buf_readBytesFile );
if( bytes <= 0 ) break;
oStream.write( buf_readBytesFile, 0, bytes );
}
oStream.flush();
strTmpFilename = m_TmpFile.getAbsolutePath();
oStream.close();
}
Log.d( "CacheFile", "CacheTmpFilename = " + strTmpFilename );
afd.close();
fis.close();
}
catch( Exception e ) {
// ...
}
}
// ---------------------------------------------
// ---------------------------------------------
// :: Play Video
// ---------------------------------------------
// See above code SurfaceView method
public class TESTAPP extends Activity implements
OnPreparedListener,
SurfaceHolder.Callback {
...
Intent intt = new Intent( "com.android.music.musicservicecommand" );
intt.putExtra( "command", "pause" );
sendBroadcast( intt );
}
...
private MediaPlayer m_MediaPlayer = null;
private SurfaceView m_SurfaceView = null;
private SurfaceHolder m_SurfaceHolder = null;
// VideoView
m_VideoView = (VideoView)findViewById( R.id.VideoView01 );
// SurfaceView
m_SurfaceView = (SurfaceView)findViewById( R.id.SurfaceView01 );
m_SurfaceHolder = m_SurfaceView.getHolder();
m_SurfaceHolder.addCallback( this );
m_SurfaceHolder.setType( SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS );
m_SurfaceView.setClickable( false );
// Visibility
// VideoView
//m_VideoView.setVisibility( 0 );
//m_VideoView.invalidate();
// SurfaceView
m_SurfaceView.setVisibility( 0 );
m_SurfaceView.invalidate();
// Button: Play
Button btnPlay = (Button)findViewById( R.id.Button01 );
View.OnClickListener btnPlayListener = new View.OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
if( m_MediaPlayer == null ) {
Log.d( "PLAY", "OK, First time" );
PlayVideo();
}
else {
PlayVideo();
}
}
};
btnPlay.setOnClickListener( btnPlayListener );
public void PlayVideo() {
if( m_MediaPlayer != null )
m_MediaPlayer.release();
m_MediaPlayer = null;
m_MediaPlayer = new MediaPlayer();
AssetFileDescriptor afd = getResources().openRawResourceFd( R.raw.__RAW_MEDIA_FILE__ );
if( m_MediaPlayer == null ) {
Log.d( "MediaPlayer", "m_MediaPlayer == NULL" );
return;
}
// Use ViewoView
/*
if( m_VideoView == null ) {
Log.d( "VideoView", "m_VideoView == NULL" );
return;
}
*/
// Use SurfaceView
if( m_SurfaceView == null ) {
Log.d( "SurfaceView", "m_SurfaceView == NULL" );
return;
}
m_MediaPlayer.setAudioStreamType( AudioManager.STREAM_MUSIC );
m_MediaPlayer.setScreenOnWhilePlaying( true );
try {
m_MediaPlayer.setDataSource( afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength() );
// Use VideoView
//m_VideoView.getHolder().addCallback( this );
//m_MediaPlayer.setDisplay( m_VideoView.getHolder() );
// Use Surface
m_MediaPlayer.setDisplay( m_SurfaceHolder );
m_MediaPlayer.prepare();
}
catch( IllegalStateException e ) {
// ...
}
catch( IOException e ) {
// ...
}
if( m_CurrentPosition > 0 )
m_MediaPlayer.seekTo( m_CurrentPosition );
if( !isPause )
m_MediaPlayer.start();
}
}
if( m_MediaPlayer != null ) {
m_MediaPlayer.release();
m_MediaPlayer = null;
}
// ---------------------------------------------
// ---------------------------------------------
// :: Play Video (VideoView)
// ---------------------------------------------
// VideoView
int m_CurrentPosition = 0;
... onSaveInstanceState( ... ) {
m_VideoView.pause();
m_CurrentPosition = m_VideoView.getCurrentPosition();
}
... onRestoreInstanceState( ... ) {
m_VideoView.seekTo( m_CurrentPosition );
m_VideoView.start();
}
if( m_MediaController == null )
m_MediaController = new MediaController( this );
Uri uriVideo = Uri.parse( "android.resource://com.test.TESTAPP/" + R.raw.xxx );
m_VideoView.setVideoURI( uriVideo );
m_MediaController.setSaveEnabled( true );
m_VideoView.setMediaController( m_MediaController );
m_MediaController.show();
m_VideoView.requestFocus();
m_VIdeoView.start();
// ---------------------------------------------
// ---------------------------------------------
// :: Media Scan (SD card)
// ---------------------------------------------
sendBroadcast( new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://" + Environment.getExternalStorageDirectory())) );
// ---------------------------------------------
// ---------------------------------------------
// :: Restrict characters length (Korean/Japanese)
// - EditText 에서 한글/일본어 입력 시 byte 수 제한하기.
// - 간단한 테스트는 Emulator 에서 일본어 입력기로 해보면 된다.
// ---------------------------------------------
m_Editbox = (EditText)findViewById( R.id.EditText01 );
m_Editbox.addTextChangedListener( new TextWatcher() {
public void onTextChanged(CharSequence s, int start, int before, int count) {
// TODO Auto-generated method stub
//Log.d("LOG", s.toString() );
}
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// TODO Auto-generated method stub
//Log.d("LOG", s.toString() );
}
// byte to int, bytes to hex 는 internet 에서 그냥 찾아서 썼다.
// NOT my code (^^) --------------------
public int getInt(byte[] bytes) {
int newValue = 0;
newValue |= (((int) bytes[0]) << 24) & 0xFF000000;
newValue |= (((int) bytes[1]) << 16) & 0xFF0000;
newValue |= (((int) bytes[2]) << 8) & 0xFF00;
newValue |= (((int) bytes[3])) & 0xFF;
return newValue;
}
public String byteArrayToHex(byte[] ba) {
if (ba == null || ba.length == 0) {
return null;
}
StringBuffer sb = new StringBuffer(ba.length * 2);
String hexNumber;
for (int x = 0; x < ba.length; x++) {
hexNumber = "0" + Integer.toHexString(0xff & ba[x]);
sb.append(hexNumber.substring(hexNumber.length() - 2));
}
return sb.toString();
}
// NOT my code (^^) --------------------
public void afterTextChanged(Editable s) {
// TODO Auto-generated method stub
//Toast.makeText( myTest1App.this, m_Editbox.getText().toString(), Toast.LENGTH_LONG ).show();
// 여기에선 8 bytes 를 제한한다.
// 주의할 점은 한글/일본어는 2 bytes 가 아닌 3 bytes 로 된다.
// 아래 log 에서 해당 문자와 hex code 를 보면 안다.
int max_len = 8; // restrict 8 bytes. (Korean/Japanese may has 3 bytes. NOT 2 bytes.)
if( s.length() > 0 ) {
int c = s.charAt( s.length()-1 );
String str = Character.toString( s.charAt(s.length()-1) );
int cLen = str.length();
Log.d( "LOG", "s len = " + s.toString().getBytes().length + ", s str = " + s.toString() + ", s hex = " + byteArrayToHex(s.toString().getBytes()) );
//Log.d( "LOG", "byte = " + s.toString().getBytes() + ", len = " + cLen + ", ascii = " + s.charAt(0) + ", dec = " + c + ", hex = " + byteArrayToHex(s.toString().getBytes()) );
Log.d( "LOG", "s.charAt(" + (s.length()-1) + ") -> " + ", = " + str + ", len = " + cLen + ", dec = " + c + ", bytes = " + str.getBytes() + ", len = " + str.getBytes().length + ", hex = " + byteArrayToHex(str.getBytes()) );
if( s.toString().getBytes().length > max_len ) {
s.delete( s.length()-1, s.length() );
m_TextView.setText( s.toString() );
}
}
}
}
);
// ---------------------------------------------
// ---------------------------------------------
// :: Indicator: Notification
// ---------------------------------------------
// http://developer.android.com/guide/topics/ui/notifiers/notifications.html
// http://osdir.com/ml/Android-Beginners/2010-07/msg00649.html
// Path: /android-sdk-windows/platforms/android-4/samples/ApiDemos/src/com/example/android/apis/app
// Source: RemoteService.java
// - AndroidManifest.xml
// - < activity ... android:launchMode="singleTask">
//
// Show a notification while this service is running.
private NotificationManager mNM = null;
private void showNotification() {
// Indicator: Notification
if( mNM != null ) {
mNM.cancel( R.string.app_name );
// Use custom view
//mNM.cancel( R.layout.local_service_controller );
}
mNM = (NotificationManager)getSystemService( NOTIFICATION_SERVICE );
// In this sample, we'll use the same text for the ticker and the expanded notification
CharSequence text = getText( R.string.remote_service_started );
// Set the icon, scrolling text and timestamp
//Notification notification = new Notification(R.drawable.stat_sample, text, System.currentTimeMillis() );
Notification notification = new Notification( -1, text, System.currentTimeMillis() );
Intent intent = new Intent( this, testMyActivity.class );
intent.setFlags( Intent.FLAG_ACTIVITY_SINGLE_TOP );
// The PendingIntent to launch our activity if the user selects this notification
PendingIntent contentIntent = PendingIntent.getActivity( this, 0, intent, 0 );
// Set the info for the views that show in the notification panel.
//notification.setLatestEventInfo(this, getText(R.string.local_service_label),
notification.setLatestEventInfo( this, getText(R.string.Info), text, contentIntent );
/*
// Set custom view
* DELETE notification.setLatestEventInfo(...)
RemoteViews contentView = new RemoteViews( getPackageName(), R.layout.local_service_controller );
////contentView.setImageViewResource( R.id.image, R.drawable.notification_image );
////contentView.setTextViewText( R.id.text, "Hello, this message is in a custom expanded view" );
//contentView.setImageViewResource( R.id.image, R.drawable.imagefile );
contentView.setTextViewText( R.id.TextViewIndicator, getText(R.string.app_name) );
notification.contentView = contentView;
// Use custom view
notification.contentIntent = contentIntent;
*/
// Send the notification.
// We use a string id because it is a unique number. We use it later to cancel.
mNM.notify( R.string.remote_service_started, notification );
// Use custom view
//mNM.notify( R.layout.local_service_controller, notification );
}
// Use custom view (ImageView, TextView)
// local_service_controller.xml
// Change (, ) to <, >
(LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:padding="4dip"
android:id="@+id/LinearLayoutIndicator"
android:layout_width="fill_parent" android:layout_height="fill_parent")
(RelativeLayout android:orientation="horizontal"
android:layout_width="fill_parent" android:layout_height="fill_parent")
(TextView
android:id="@+id/TextViewIndicator"
android:layout_width="fill_parent" android:layout_height="wrap_content"
android:layout_weight="0"
android:paddingBottom="4dip"
android:text="local_service_controller")
(/TextView)
(Button android:id="@+id/start"
android:layout_below="@+id/TextViewIndicator"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:text="start_service")
(/Button)
(Button android:id="@+id/stop"
android:layout_below="@+id/TextViewIndicator"
android:layout_toRightOf="@+id/start"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:text="stop_service")
(/Button)
(/RelativeLayout)
(/LinearLayout)
// ---------------------------------------------
-----
Cheers,
June
피드 구독하기:
글 (Atom)