Related
I have developed an application for barcode decoding in android using Google vision Library for GS1 data matrix and Zbar Library for GS1 128 barcode Unable to read FNC1 character at the first position of a GS1 128 Barcode using Zbar library.
The Zbar library is unable to display any sign of FNC1 character at the start of the Barcode!
Any Solutions. . . .
Instant Help is appreciable . . .
Below is my ZBar Scanner Activity
#SuppressWarnings("deprecation")
public class ZBarFirstScannerActivity extends AppCompatActivity{
//TextView tv;
ImageView iv;
LinearLayout ll;
private Camera mCamera;
private CameraPreview mPreview;
private Handler autoFocusHandler;
private ImageScanner scanner;
private boolean barcodeScanned = false;
private boolean previewing = true;
TextView tv;
static {
System.loadLibrary("iconv");
}
static {
System.loadLibrary("zbarjni");
}
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.barcode_capture1d);
tv = (TextView) findViewById(R.id.textVertical);
tv.setRotation(90);
initToolbar();
autoFocusHandler = new Handler();
mCamera = getCameraInstance();
// Instance barcode scanner
scanner = new ImageScanner();
scanner.setConfig(0, Config.X_DENSITY, 1);
scanner.setConfig(0, Config.Y_DENSITY, 1);
scanner.setConfig(Symbol.CODE128, Config.ENABLE,1);
scanner.setConfig(Symbol.EAN13, Config.ENABLE,1);
mPreview = new CameraPreview(this, mCamera, previewCb, autoFocusCB);
FrameLayout preview = (FrameLayout)findViewById(R.id.cameraPreview);
preview.addView(mPreview);
}
private void initToolbar() {
final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
final ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setHomeButtonEnabled(true);
actionBar.setHomeAsUpIndicator(ContextCompat.getDrawable(this, R.drawable.abc_ic_ab_back_mtrl_am_alpha));
actionBar.setDisplayHomeAsUpEnabled(true);
}
}
/** A safe way to get an instance of the Camera object. */
public static Camera getCameraInstance()
{
Camera c = null;
try
{
c = Camera.open();
} catch (Exception e)
{
//nada
}
return c;
}
private void releaseCamera()
{
if (mCamera != null)
{
previewing = false;
mCamera.setPreviewCallback(null);
mCamera.release();
mCamera = null;
}
}
PreviewCallback previewCb = new PreviewCallback()
{
public void onPreviewFrame(byte[] data, Camera camera)
{
Camera.Parameters parameters = camera.getParameters();
Size size = parameters.getPreviewSize();
Image barcode = new Image(size.width, size.height, "Y800");
barcode.setData(data);
int result = scanner.scanImage(barcode);
if (result != 0)
{
previewing = false;
mCamera.setPreviewCallback(null);
mCamera.stopPreview();
SymbolSet syms = scanner.getResults();
for (Symbol sym : syms)
{
barcodeScanned = true;
Intent returnIntent = new Intent();
returnIntent.putExtra("BARCODE", sym.getData());
setResult(MainActivity.BAR_CODE_TYPE_128,returnIntent);
releaseCamera();
finish();
break;
}
}
}
};
// Mimic continuous auto-focusing
AutoFocusCallback autoFocusCB = new AutoFocusCallback()
{
public void onAutoFocus(boolean success, Camera camera)
{
autoFocusHandler.postDelayed(doAutoFocus, 3000);
}
};
private Runnable doAutoFocus = new Runnable()
{
public void run()
{
if (previewing)
mCamera.autoFocus(autoFocusCB);
}
};
public void onPause() {
super.onPause();
releaseCamera();
}
public void onResume(){
super.onResume();
new ZBarFirstScannerActivity();
}
#Override
public void onBackPressed() {
releaseCamera();
finish();
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == android.R.id.home) {
onBackPressed();
return true;
}
return super.onOptionsItemSelected(item);
}
}
Below is my Google Scanner Activity
public final class GoogleScannerActivity extends AppCompatActivity {
private static final String TAG = "Barcode-reader";
// intent request code to handle updating play services if needed.
private static final int RC_HANDLE_GMS = 9001;
// permission request codes need to be < 256
private static final int RC_HANDLE_CAMERA_PERM = 2;
// constants used to pass extra data in the intent
public static final String AutoFocus = "AutoFocus";
public static final String UseFlash = "UseFlash";
public static final String BarcodeObject = "Barcode";
Bitmap bmp;
FileOutputStream fos = null;
private Camera c;
Switch aSwitch;
private CameraSource mCameraSource;
private CameraSourcePreview mPreview;
private GraphicOverlay<BarcodeGraphic> mGraphicOverlay;
// helper objects for detecting taps and pinches.
private ScaleGestureDetector scaleGestureDetector;
private GestureDetector gestureDetector;
/**
* Initializes the UI and creates the detector pipeline.
*/
#Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.barcode_capture2d);
initToolbar();
ActivitySource.caller = this;
mPreview = (CameraSourcePreview) findViewById(R.id.preview);
mGraphicOverlay = (GraphicOverlay<BarcodeGraphic>) findViewById(R.id.graphicOverlay);
boolean autoFocus = true;
boolean useFlash = false;
// Check for the camera permission before accessing the camera. If the
// permission is not granted yet, request permission.
int rc = ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA);
if (rc == PackageManager.PERMISSION_GRANTED) {
createCameraSource(autoFocus, useFlash);
} else {
requestCameraPermission();
}
gestureDetector = new GestureDetector(this, new CaptureGestureListener());
scaleGestureDetector = new ScaleGestureDetector(this, new ScaleListener());
/*Snackbar.make(mGraphicOverlay, "Tap to capture. Pinch/Stretch to zoom",
Snackbar.LENGTH_LONG)
.show();*/
}
private void initToolbar() {
final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
final ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setHomeButtonEnabled(true);
actionBar.setHomeAsUpIndicator(ContextCompat.getDrawable(this, R.drawable.abc_ic_ab_back_mtrl_am_alpha));
actionBar.setDisplayHomeAsUpEnabled(true);
}
}
private Camera.Size getBestPreviewSize(int width, int height, Camera.Parameters parameters){
Camera.Size bestSize = null;
List<Camera.Size> sizeList = parameters.getSupportedPreviewSizes();
bestSize = sizeList.get(0);
for(int i = 1; i < sizeList.size(); i++){
if((sizeList.get(i).width * sizeList.get(i).height) >
(bestSize.width * bestSize.height)){
bestSize = sizeList.get(i);
}
}
return bestSize;
}
/**
* Handles the requesting of the camera permission. This includes
* showing a "Snackbar" message of why the permission is needed then
* sending the request.
*/
private void requestCameraPermission() {
Log.w(TAG, "Camera permission is not granted. Requesting permission");
final String[] permissions = new String[]{Manifest.permission.CAMERA};
if (!ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.CAMERA)) {
ActivityCompat.requestPermissions(this, permissions, RC_HANDLE_CAMERA_PERM);
return;
}
final Activity thisActivity = this;
View.OnClickListener listener = new View.OnClickListener() {
#Override
public void onClick(View view) {
ActivityCompat.requestPermissions(thisActivity, permissions,
RC_HANDLE_CAMERA_PERM);
}
};
Snackbar.make(mGraphicOverlay, R.string.permission_camera_rationale,
Snackbar.LENGTH_INDEFINITE)
.setAction(R.string.ok, listener)
.show();
}
#Override
public boolean onTouchEvent(MotionEvent e) {
boolean b = scaleGestureDetector.onTouchEvent(e);
boolean c = gestureDetector.onTouchEvent(e);
return b || c || super.onTouchEvent(e);
}
/**
* Creates and starts the camera. Note that this uses a higher resolution in comparison
* to other detection examples to enable the barcode detector to detect small barcodes
* at long distances.
*
* Suppressing InlinedApi since there is a check that the minimum version is met before using
* the constant.
*/
#SuppressLint("InlinedApi")
private void createCameraSource(boolean autoFocus, boolean useFlash) {
Context context = getApplicationContext();
// A barcode detector is created to track barcodes. An associated multi-processor instance
// is set to receive the barcode detection results, track the barcodes, and maintain
// graphics for each barcode on screen. The factory is used by the multi-processor to
// create a separate tracker instance for each barcode.
BarcodeDetector barcodeDetector = new BarcodeDetector.Builder(context).setBarcodeFormats(Barcode.CODE_128 | Barcode.DATA_MATRIX | Barcode.QR_CODE).build();
BarcodeTrackerFactory barcodeFactory = new BarcodeTrackerFactory(mGraphicOverlay);
barcodeDetector.setProcessor(
new MultiProcessor.Builder<>(barcodeFactory).build());
if (!barcodeDetector.isOperational()) {
// Note: The first time that an app using the barcode or face API is installed on a
// device, GMS will download a native libraries to the device in order to do detection.
// Usually this completes before the app is run for the first time. But if that
// download has not yet completed, then the above call will not detect any barcodes
// and/or faces.
//
// isOperational() can be used to check if the required native libraries are currently
// available. The detectors will automatically become operational once the library
// downloads complete on device.
Log.w(TAG, "Detector dependencies are not yet available.");
// Check for low storage. If there is low storage, the native library will not be
// downloaded, so detection will not become operational.
IntentFilter lowstorageFilter = new IntentFilter(Intent.ACTION_DEVICE_STORAGE_LOW);
boolean hasLowStorage = registerReceiver(null, lowstorageFilter) != null;
if (hasLowStorage) {
Toast.makeText(this, R.string.low_storage_error, Toast.LENGTH_LONG).show();
Log.w(TAG, getString(R.string.low_storage_error));
}
}
// Creates and starts the camera. Note that this uses a higher resolution in comparison
// to other detection examples to enable the barcode detector to detect small barcodes
// at long distances.
CameraSource.Builder builder = new CameraSource.Builder(getApplicationContext(), barcodeDetector)
.setFacing(CameraSource.CAMERA_FACING_BACK)
.setRequestedPreviewSize(1100, 844)
.setRequestedFps(15.0f);
// make sure that auto focus is an available option
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
builder = builder.setFocusMode(
autoFocus ? Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE : null);
}
mCameraSource = builder
.setFlashMode(useFlash ? Camera.Parameters.FLASH_MODE_TORCH : null)
.build();
}
/**
* Restarts the camera.
*/
#Override
protected void onResume() {
super.onResume();
startCameraSource();
}
/**
* Stops the camera.
*/
#Override
protected void onPause() {
super.onPause();
if (mPreview != null) {
mPreview.stop();
}
}
/**
* Releases the resources associated with the camera source, the associated detectors, and the
* rest of the processing pipeline.
*/
#Override
protected void onDestroy() {
super.onDestroy();
if (mPreview != null) {
mPreview.release();
}
}
#Override
public void onRequestPermissionsResult(int requestCode,
#NonNull String[] permissions,
#NonNull int[] grantResults) {
if (requestCode != RC_HANDLE_CAMERA_PERM) {
Log.d(TAG, "Got unexpected permission result: " + requestCode);
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
return;
}
if (grantResults.length != 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Log.d(TAG, "Camera permission granted - initialize the camera source");
// we have permission, so create the camerasource
boolean autoFocus = getIntent().getBooleanExtra(AutoFocus,false);
boolean useFlash = getIntent().getBooleanExtra(UseFlash, false);
createCameraSource(autoFocus, useFlash);
return;
}
Log.e(TAG, "Permission not granted: results len = " + grantResults.length +
" Result code = " + (grantResults.length > 0 ? grantResults[0] : "(empty)"));
DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
finish();
}
};
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Multitracker sample")
.setMessage(R.string.no_camera_permission)
.setPositiveButton(R.string.ok, listener)
.show();
}
/**
* Starts or restarts the camera source, if it exists. If the camera source doesn't exist yet
* (e.g., because onResume was called before the camera source was created), this will be called
* again when the camera source is created.
*/
private void startCameraSource() throws SecurityException {
// check that the device has play services available.
int code = GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(
getApplicationContext());
if (code != ConnectionResult.SUCCESS) {
Dialog dlg =
GoogleApiAvailability.getInstance().getErrorDialog(this, code, RC_HANDLE_GMS);
dlg.show();
}
if (mCameraSource != null) {
try {
mPreview.start(mCameraSource, mGraphicOverlay);
} catch (IOException e) {
Log.e(TAG, "Unable to start camera source.", e);
mCameraSource.release();
mCameraSource = null;
}
}
}
/**
* onTap is called to capture the oldest barcode currently detected and
* return it to the caller.
*
* #param rawX - the raw position of the tap
* #param rawY - the raw position of the tap.
* #return true if the activity is ending.
*/
private boolean onTap(float rawX, float rawY) {
//TODO: use the tap position to select the barcode.
BarcodeGraphic graphic = mGraphicOverlay.getFirstGraphic();
Barcode barcode = null;
if (graphic != null) {
barcode = graphic.getBarcode();
if (barcode != null) {
Intent data = new Intent();
data.putExtra(BarcodeObject, barcode);
setResult(CommonStatusCodes.SUCCESS, data);
finish();
}
else {
Log.d(TAG, "barcode data is null");
}
}
else {
Log.d(TAG,"no barcode detected");
}
return barcode != null;
}
private class CaptureGestureListener extends GestureDetector.SimpleOnGestureListener {
#Override
public boolean onSingleTapConfirmed(MotionEvent e) {
return onTap(e.getRawX(), e.getRawY()) || super.onSingleTapConfirmed(e);
}
}
private class ScaleListener implements ScaleGestureDetector.OnScaleGestureListener {
/**
* Responds to scaling events for a gesture in progress.
* Reported by pointer motion.
*
* #param detector The detector reporting the event - use this to
* retrieve extended info about event state.
* #return Whether or not the detector should consider this event
* as handled. If an event was not handled, the detector
* will continue to accumulate movement until an event is
* handled. This can be useful if an application, for example,
* only wants to update scaling factors if the change is
* greater than 0.01.
*/
#Override
public boolean onScale(ScaleGestureDetector detector) {
return false;
}
/**
* Responds to the beginning of a scaling gesture. Reported by
* new pointers going down.
*
* #param detector The detector reporting the event - use this to
* retrieve extended info about event state.
* #return Whether or not the detector should continue recognizing
* this gesture. For example, if a gesture is beginning
* with a focal point outside of a region where it makes
* sense, onScaleBegin() may return false to ignore the
* rest of the gesture.
*/
#Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
return true;
}
/**
* Responds to the end of a scale gesture. Reported by existing
* pointers going up.
* <p/>
* Once a scale has ended, {#link ScaleGestureDetector#getFocusX()}
* and {#link ScaleGestureDetector#getFocusY()} will return focal point
* of the pointers remaining on the screen.
*
* #param detector The detector reporting the event - use this to
* retrieve extended info about event state.
*/
#Override
public void onScaleEnd(ScaleGestureDetector detector) {
mCameraSource.doZoom(detector.getScaleFactor());
}
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == android.R.id.home) {
onBackPressed();
return true;
}
return super.onOptionsItemSelected(item);
}
}
When scanning a GS1-128 symbol the FNC1 in first position acts as a flag character to indicate the presence of GS1 Application Identifier standard format data and is intentionally omitted from the scanned data, whilst any inter-field FNC1 formatting character is transmitted at GS (ASCII 29).
The implicit, leading FNC1 can be inferred if your reader is configured to emit symbology identifiers at the start of the scanned data. In this case your GS1-128 scanned data will begin with ]C1 rather than ]C0 for generic Code 128.
Unfortunately it does not appear as though either the ZBar library or Google Vision Library can be configured to return symbology identifiers which is a disappointing limitation.
Additionally the Google Vision Library erroneously returns a leading GS1 representing the FNC1 in first position.
Reading of GS1 formatted data is described in detail by this answer.
Specifically the ISO/IEC 15417 - Code 128 bar code symbology specification says:
"Any application which utilizes Code
128 symbols with FNC1 in the first or second data position should
require the transmission of symbology identifiers to be enabled. When
FNC1 is used in the first or second position it shall not be
represented in the transmitted message, although its presence is
indicated by the use of modifier values 1 or 2 respectively in the
symbology identifier."
How will we play youtube video with android media player???
Anybody has idea then please explain me.
I have to play the URL:"http://www.youtube.com/embed/bIPcobKMB94?autoplay=1" with android default media player.
When i played this url with android media player, i got MediaPlayer error (1, -2147483648).
I play that url in my android device media player but now i am not able play in tablet. Anybody help me. Why i am not able to play that video in tablet?
rtsp://v6.cache3.c.youtube.com/CiILENy73wIaGQnokCRYfXXPsBMYDSANFEgGUgZ2aWRlb3MM/0/0/0/video.3gp
Thanks
Well, the Android part is quite easy. You just need a raw URI of the YouTube video and trigger an intent with it:
Uri uri = Uri.parse("http://<link-to-RAW-youtube-video>"); // i.e. mp4 version
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(uri, "video/*"); // important! otherwise you just download the video
startActivity(intent); // called directly from an other activity as you see
If the user has multiple video players installed the user also gets a choice which one he wants to use for the playback.
The tricky part here is not Android related it is how to get the raw URI of a YouTube video. Usually they are extracted from the source code of the original YouTube Video page but that's an other topic. I tried the code above with a self extracted URI to a mp4 version of the video and it worked just fine on my Android 4.0 phone.
EDIT:
You really have to use a raw URI to the YouTube Video, for your Video it would be:
http://o-o.preferred.ber01s04.v22.lscache2.c.youtube.com/videoplayback?sparams=cp%2Cid%2Cip%2Cipbits%2Citag%2Cratebypass%2Csource%2Cexpire&fexp=904550%2C919700%2C911614&itag=18&ip=77.0.0.0&signature=C721CE7543081FC0C805C86F5D3C4D9B34D77764.D4288106CF7A3153FF1574F2334161CBD1176535&sver=3&ratebypass=yes&source=youtube&expire=1332001847&key=yt1&ipbits=8&cp=U0hSR1BLT19JUUNOMl9IRVNJOmllRjJJYy1SSG92&id=6c83dca1b28c07de&title=AT%26T%20Samsung%20Captivate%20TV%20Commercial%20-%20Galaxy%20S%20Phone-360p
It's very long but it will work :)
I had a very hard time implementing a player supporting many features and formats. Even VideoView didn't match all of my needs. Finally, I ended up writting my own solution based on SurfaceView and MediaPlayer. Here is the source code. It was validated on 4.0.3 and 4.1.2 for local 3gp, local mp4, http 3gp and youtube rtsp streams.
Remember that, presently, an URI for valid youtube video on android is to be like this: rtsp://v5.cache1.c.youtube.com/CjYLENy73wIaLQnhycnrJQ8qmRMYESARFEIJbXYtZ29vZ2xlSARSBXdhdGNoYPj_hYjnq6uUTQw=/0/0/0/video.3gp. You get them via http://m.youtube.video.
The activity's arguments are set by Intent. There are quite a variety of options. See the last source code provided in my comment. You can remove the code related to Sequencer, Scenario and Test classes. They are specific to my program (automated system for platform testing)
package my.package;
import java.io.IOException;
import java.lang.ref.WeakReference;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Point;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnBufferingUpdateListener;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnPreparedListener;
import android.media.MediaPlayer.OnVideoSizeChangedListener;
import android.net.Uri;
import android.os.Build.VERSION;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.text.format.Time;
import android.view.Display;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import my.package.Log;
import my.package.R;
import my.package.Scenario;
import my.package.Sequencer;
import my.package.Test;
import my.package.TestUtil;
/**
* An activity to display local or remote video or play audio file.
*/
public class MediaPlayerActivity extends Activity implements
OnBufferingUpdateListener, OnCompletionListener, OnPreparedListener,
OnVideoSizeChangedListener, OnErrorListener, SurfaceHolder.Callback {
private static final String LOG_TAG = MediaPlayerActivity.class
.getSimpleName();
// Mandatory creation arguments passed by extras in starting Intent
public static final String SEQUENCER = "sequencer"; //$NON-NLS-1$
public static final String SCENARIO = "scenario"; //$NON-NLS-1$
public static final String TEST = "test"; //$NON-NLS-1$
public static final String SOURCE_URI = "uri"; //$NON-NLS-1$
// Optional creation arguments passed by extras in starting Intent
public static final String PAUSE_ON_BACKGROUND = "auto_pause"; //$NON-NLS-1$
public static final String TIMEOUT = "timeout"; //$NON-NLS-1$
public static final String LOOP = "loop"; //$NON-NLS-1$
public static final String SCREEN_ON_WHILE_PLAYING = "screen_on_while_playing"; //$NON-NLS-1$
// data arguments returned by Intent on finish
public static final String REASON = "cause"; //$NON-NLS-1$
public static final String EXCEPTION = "exception"; //$NON-NLS-1$
// additional state bundle arguments.
private static final String START_POSITION = "start"; //$NON-NLS-1$
private static final String VIDEO_WIDTH = "video_width"; //$NON-NLS-1$
private static final String VIDEO_HEIGHT = "video_height"; //$NON-NLS-1$
private WeakReference<Sequencer> mSequencer = new WeakReference<Sequencer> (null);
private WeakReference<Test> mTest = new WeakReference<Test> (null);
/**
* URI of the video/audio source.
*
* This player supports a variety of videos and audio sources, either local
* or remote.
* <p>
* An HTTP live streaming URI would be:
* {#code httplive://xboodangx.api.channel.livestream.com/3.0/playlist.m3u8}
* </p>
* <p>
* A local video file URI would be {#code file:///sdcard/spiderman.mp4}
* </p>
* <p>
* A remote 3GPP format video URI would be
* {#code http://commonsware.com/misc/test2.3gp}
* </p>
* <p>
* And finally an RTP or RTSP video source URI would be
* {#code rtsp://v4.cache1.c.youtube.com/CjYLENy73wIaLQk4RDShYkdS1BMYDSANFEIJbXYtZ29vZ2xlSARSBXdhdGNoYK-Cn8qh8J6-Tgw=/0/0/0/video.3gp}
* </p>
*/
private Uri mMediaURI;
/**
* Input: this flag is set to true if the video must be paused when the
* activity is not visible any more. The video will resume when the activity
* is visible again.
*/
private boolean mPauseOnBackground;
/**
* Input: number of milliseconds until automatic shutdown, or -1 if no
* timeout.
*/
private long mTimeout;
/**
* Input: flag set to true to loop back to the beginning of the video when
* reaching its end
*/
private boolean mLoop;
/**
* The width of the video, obtained by
* {#link #onVideoSizeChanged(MediaPlayer, int, int)}
*/
private int mVideoWidth;
/**
* The height of the video, obtained by
* {#link #onVideoSizeChanged(MediaPlayer, int, int)}
*/
private int mVideoHeight;
private MediaPlayer mMediaPlayer;
private SurfaceView mPreview;
private boolean mIsVideoSizeKnown = false;
private boolean mMediaPrepared = false;
/**
* This member is set to position the video should start. It is set when
* pausing the video and used when restoring the instance.
*/
private int mStartPosition;
private boolean mTimeoutSet;
private boolean mScreenOnWhilePlaying;
private SurfaceHolder mHolder;
private static class ShutdownHandler extends Handler {
WeakReference<MediaPlayerActivity> mActivity;
public ShutdownHandler(MediaPlayerActivity activity) {
mActivity = new WeakReference<MediaPlayerActivity>(activity);
}
#Override
public void handleMessage(Message msg) {
MediaPlayerActivity activity = mActivity.get();
if (activity != null) {
activity.finishTest(Activity.RESULT_OK, null);
} else {
//Log.w(LOG_TAG, "no activity for shutdown");
}
}
}
public MediaPlayerActivity() {
super();
// These members are initialized in onCreate(Bundle) by the
// starting Intent, the first time the activity is created, and restored
// in the same method with the arguments in the saved instance bundle.
mSequencer = new WeakReference<Sequencer> (null);
mTest = new WeakReference<Test> (null);
setSourceURI(null);
setPauseOnBackground(false);
setPlayTimeout(-1);
setLooping(false);
setScreenOnWhilePlaying(true);
// Initialize internals.
mIsVideoSizeKnown = false;
mVideoWidth = mVideoHeight = 0; // unknown
mMediaPrepared = false;
mMediaPlayer = null;
mPreview = null; // set in onCreate(Bundle)
setStartPosition(0); // beginning of the video
mTimeoutSet = false;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.video_player);
Intent intent = getIntent();
if (savedInstanceState != null) {
onRestoreInstanceState(savedInstanceState);
} else if (intent != null) {
Log.d(LOG_TAG, "Loading starting Intent extras...");
// read starting Intent extras.
_updateForeignReferences(intent);
setSourceURI((Uri) intent.getParcelableExtra(SOURCE_URI));
setPlayTimeout(intent.getLongExtra(TIMEOUT, -1L));
setPauseOnBackground(intent.getBooleanExtra(PAUSE_ON_BACKGROUND,
false));
setLooping(intent.getBooleanExtra(LOOP, false));
setScreenOnWhilePlaying(intent.getBooleanExtra(SCREEN_ON_WHILE_PLAYING, true));
}
mTimeoutSet = false;
_updateWidgets();
}
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
Log.d(LOG_TAG, "Restoring instance state...");
// restore saved references
_updateSavedForeignReferences(savedInstanceState);
// restore saved inputs
setSourceURI(Uri.parse(savedInstanceState.getString(SOURCE_URI)));
setPlayTimeout(savedInstanceState.getLong(TIMEOUT));
setPauseOnBackground(savedInstanceState.getBoolean(PAUSE_ON_BACKGROUND));
setLooping(savedInstanceState.getBoolean(LOOP));
setScreenOnWhilePlaying(savedInstanceState.getBoolean(SCREEN_ON_WHILE_PLAYING));
// restore internals
setStartPosition(savedInstanceState.getInt(START_POSITION, 0));
mVideoWidth = savedInstanceState.getInt(VIDEO_WIDTH);
mVideoHeight = savedInstanceState.getInt(VIDEO_HEIGHT); // unknown
mIsVideoSizeKnown = (mVideoWidth > 0) && (mVideoHeight > 0);
}
#Override
protected void onResume() {
super.onResume();
if (mMediaPlayer == null) {
try {
_playMedia();
} catch (Exception e) {
_fail(e);
}
}
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Log.d(LOG_TAG, "Saving instance state");
Sequencer sequencer = mSequencer.get();
if (sequencer != null) {
outState.putInt(SEQUENCER, sequencer.getPosition());
Scenario scenario = sequencer.getScenario();
if (scenario != null) {
outState.putInt(SCENARIO, scenario.getScenarioId());
}
}
Test test = mTest.get();
if (test != null) {
outState.putString(TEST, TestUtil.getTestPath(test, TestUtil.Path.Static));
}
if (getSourceURI() != null) {
outState.putString(SOURCE_URI, getSourceURI().toString());
}
outState.putBoolean(LOOP, isLooping());
outState.putBoolean(PAUSE_ON_BACKGROUND, isPausingOnBackground());
outState.putLong(TIMEOUT, getPlayTimeout());
outState.putBoolean(SCREEN_ON_WHILE_PLAYING, isScreenOnWhilePlaying());
outState.putInt(START_POSITION, getStartPosition());
}
#Override
protected void onPause() {
super.onPause();
if (isPausingOnBackground()) {
_pausePlayback();
}
}
#Override
protected void onStop() {
super.onStop();
Log.d(LOG_TAG, "onStop");
if (isPausingOnBackground()) {
_releaseMediaPlayer();
}
}
#Override
protected void onDestroy() {
super.onDestroy();
Log.d(LOG_TAG, "onDestroy");
// TODO: It would be fine to fail the test if the activity was destroyed
// if we didn't finished the test yet but there are far too many cases
// and I failed to implement one working with all of them!
/* if (!mInstanceSaved) {
finishTest(Activity.RESULT_FIRST_USER, new Intent().putExtra(REASON,
"Activity destroyed. Something certainly goes wrong there."));
}
*/
_releaseMediaPlayer();
}
// Restore sequencer, scenario and test references from saved state.
private void _updateSavedForeignReferences(Bundle savedInstanceState) {
int sequencer = savedInstanceState.getInt(SEQUENCER, -1);
int scenarioId = savedInstanceState.getInt(SCENARIO, -1);
mSequencer = new WeakReference<Sequencer>(null);
mTest = new WeakReference<Test>(null);
if (scenarioId >= 0 && sequencer >= 0) {
Scenario scenario = Controller.controller.getData().scenarios()
.getScenario(scenarioId);
mSequencer = new WeakReference<Sequencer>(Controller.controller
.engine().getSequencerAt(sequencer));
String testPath = savedInstanceState.getString(TEST);
if (!TextUtils.isEmpty(testPath)) {
mTest = new WeakReference<Test>(TestUtil.fromPath(
scenario.getRootTest(), testPath));
}
}
}
// Update sequencer, scenario and test references from starting Intent
protected void _updateForeignReferences(Intent intent) {
int scenarioId = intent.getIntExtra(MediaPlayerActivity.SCENARIO, -1);
Scenario scenario = Controller.controller.getData().scenarios()
.getScenario(scenarioId);
int sequencer = intent.getIntExtra(MediaPlayerActivity.SEQUENCER, -1);
mSequencer = new WeakReference<Sequencer>(null);
mTest = new WeakReference<Test>(null);
if (scenarioId >= 0 && sequencer >= 0) {
mSequencer = new WeakReference<Sequencer>(Controller.controller
.engine().getSequencerAt(sequencer));
String testPath = intent.getStringExtra(MediaPlayerActivity.TEST);
if (!TextUtils.isEmpty(testPath)) {
mTest = new WeakReference<Test>(TestUtil.fromPath(
scenario.getRootTest(), testPath));
}
}
}
/**
* Terminate the test case and finish the activity at the same time.
* <p>
* The result code and data are passed to both the parent activity and the
* {#link Test#terminate(int, Sequencer, Object)} method.
* </p>
*
* #param resultCode
* the result code. May be on of the Activity result code but
* also any other one having a meaning for the test and caller
* activity.
* #param data
* extra result data. Can be null.
*/
public void finishTest(int resultCode, Intent data) {
Test test = mTest.get();
Sequencer sequencer = mSequencer.get();
if ((test != null) && (sequencer != null)) {
test.terminate(resultCode, sequencer, data);
// prevent any further call to finishTest.
mTest = new WeakReference<Test> (null);
}
if (!isFinishing()) {
setResult(Activity.RESULT_OK, data);
finish();
}
}
#SuppressWarnings("deprecation")
private void _updateWidgets() {
SurfaceView surface = (SurfaceView) findViewById(R.id.surface);
mPreview = surface;
SurfaceHolder holder = surface.getHolder();
holder.addCallback(this);
if (VERSION.SDK_INT < android.os.Build.VERSION_CODES.HONEYCOMB) {
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
}
public void onBufferingUpdate(MediaPlayer arg0, int percent) {
Log.d(LOG_TAG, "onBufferingUpdate percent:" + percent);
if (percent >= 100) {
mMediaPlayer.setOnBufferingUpdateListener(null);
}
// no display so don't bother.
}
public void onCompletion(MediaPlayer player) {
_releaseMediaPlayer();
finishTest(Activity.RESULT_OK, null);
}
private void _rearmPlayer() {
mVideoWidth = 0;
mVideoHeight = 0;
mMediaPrepared = false;
mIsVideoSizeKnown = false;
}
public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
if (mIsVideoSizeKnown) return; // further notifications are completely wrong!!
Log.i(LOG_TAG, "Video size: " + width + "x" + height);
mIsVideoSizeKnown = true;
mVideoWidth = width;
mVideoHeight = height;
if (width > 0 && height > 0) {
_fitSurfaceForVideo();
} else {
// audio only or video size unknown.
}
if (mMediaPrepared) {
_startPlayback();
}
}
#SuppressWarnings("deprecation")
#SuppressLint("NewApi")
private void _fitSurfaceForVideo() {
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
if (VERSION.SDK_INT >= 13) {
display.getSize(size);
} else {
size.x = display.getWidth();
size.y = display.getHeight();
}
double ratioVideo = (double)mVideoWidth / mVideoHeight;
double ratioScreen = (double)size.x / size.y;
if (ratioScreen > ratioVideo) {
// fit in height and scale the width to match the video ratio
mVideoHeight = size.y;
mVideoWidth = (int) (size.y / ratioVideo);
} else {
// fit in width and scale height to keep the video ratio
mVideoWidth = size.x;
mVideoHeight = (int) (size.x / ratioVideo);
}
}
public void onPrepared(MediaPlayer mediaplayer) {
mMediaPrepared = true;
if (mIsVideoSizeKnown) {
_startPlayback();
}
}
private void _startPlayback() {
SurfaceHolder holder = mPreview.getHolder();
if (mVideoWidth > 0 && mVideoHeight > 0) {
holder.setFixedSize(mVideoWidth, mVideoHeight);
}
if (mStartPosition > 0) {
Log.i(LOG_TAG, String.format("Resume at %f seconds", mStartPosition / 1000.f));
mMediaPlayer.seekTo(mStartPosition);
} else {
Log.i(LOG_TAG, "Start video");
}
if (!mTimeoutSet && (getPlayTimeout() > 0)) {
// this is a constant time reference: deduce the time already played.
long remaining = getPlayTimeout() - mStartPosition;
Time time = new Time();
time.setToNow();
time.second += remaining / 1000;
time.normalize(false);
Log.i(LOG_TAG, "Will end the video on " + time.format2445());
new ShutdownHandler(this).sendEmptyMessageDelayed(0, remaining);
mTimeoutSet = true;
}
mMediaPlayer.start();
}
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
Log.d(LOG_TAG, String.format(
"surfaceChanged called: format=%d, width=%d, height=%d",
format, width, height));
}
public void surfaceDestroyed(SurfaceHolder surfaceholder) {
Log.d(LOG_TAG, "surfaceDestroyed called");
mHolder = null;
if (mMediaPlayer != null) {
mMediaPlayer.setDisplay(null);
}
}
public void surfaceCreated(SurfaceHolder holder) {
Log.d(LOG_TAG, "surfaceCreated called");
mHolder = holder;
if (mMediaPlayer != null) {
// surface created after the media player
try {
mMediaPlayer.setDisplay(holder);
mMediaPlayer.setScreenOnWhilePlaying(isScreenOnWhilePlaying());
mMediaPlayer.setOnCompletionListener(this);
if (!mMediaPrepared) {
mMediaPlayer.setDataSource(this, mMediaURI);
mMediaPlayer.prepareAsync();
}
} catch (IllegalStateException e) {
_fail(e);
} catch (IllegalArgumentException e) {
_fail(e);
} catch (SecurityException e) {
_fail(e);
} catch (IOException e) {
_fail(e);
}
}
}
private void _playMedia() throws IllegalArgumentException,
SecurityException, IllegalStateException, IOException {
Log.d(LOG_TAG, "_playMedia()");
_rearmPlayer();
/*
* The video should be in a streamable mp4 or 3gpp format. The URI
* scheme may be Http. Mediaplayer can only play
* "progressive streamable contents" which basically means: 1. the movie
* atom has to precede all the media data atoms. 2. The clip has to be
* reasonably interleaved.
*/
if (mMediaURI != null) {
Log.i(LOG_TAG, "Source: " + mMediaURI);
// Create a new media player and set the listeners
if (mMediaPlayer != null) {
mMediaPlayer.reset();
} else {
mMediaPlayer = new MediaPlayer();
}
// mMediaPlayer.setDataSource(this, mMediaURI);
mMediaPlayer.setOnBufferingUpdateListener(this);
mMediaPlayer.setOnPreparedListener(this);
mMediaPlayer.setLooping(isLooping());
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mMediaPlayer.setOnVideoSizeChangedListener(this);
if (mHolder != null) {
// surface created before the media player
mMediaPlayer.setDisplay(mHolder);
mMediaPlayer.setScreenOnWhilePlaying(isScreenOnWhilePlaying());
mMediaPlayer.setOnCompletionListener(this);
mMediaPlayer.setDataSource(this, mMediaURI);
mMediaPlayer.prepareAsync();
}
} else {
_fail("No video source defined");
}
}
// fail due to exception
private void _fail(Exception e) {
Log.e(LOG_TAG, e);
Intent data = new Intent();
data.putExtra(EXCEPTION, e);
finishTest(Activity.RESULT_FIRST_USER, data);
}
// fail due to generic error
private void _fail(String text) {
Log.e(LOG_TAG, text);
Intent data = new Intent();
data.putExtra(REASON, text);
finishTest(Activity.RESULT_FIRST_USER, data);
}
private void _pausePlayback() {
if (mMediaPlayer != null && mMediaPlayer.isPlaying()) {
Log.i(LOG_TAG, "Pause playback");
mMediaPlayer.pause();
// retain position for use by onSaveInstanceState(Bundle)
setStartPosition(mMediaPlayer.getCurrentPosition());
}
}
#Override
public void onBackPressed() {
super.onBackPressed();
Intent data = new Intent();
data.putExtra(REASON, "canceled by user");
finishTest(Activity.RESULT_CANCELED, data);
}
private void _releaseMediaPlayer() {
_stopPlayback();
if (mMediaPlayer != null) {
mMediaPlayer.release();
mMediaPlayer = null;
}
_rearmPlayer();
}
private void _stopPlayback() {
if (mMediaPlayer != null && mMediaPlayer.isPlaying()) {
_pausePlayback();
Log.i(LOG_TAG, "stop video");
mMediaPlayer.stop();
}
}
public boolean isPausingOnBackground() {
return mPauseOnBackground;
}
public void setPauseOnBackground(boolean pause) {
Log.d(LOG_TAG, "Pausing on background: " + pause);
this.mPauseOnBackground = pause;
}
public Uri getSourceURI() {
return mMediaURI;
}
public void setSourceURI(Uri uri) {
Log.d(LOG_TAG, "Media source: " + uri);
this.mMediaURI = uri;
}
public long getPlayTimeout() {
return mTimeout;
}
public void setPlayTimeout(long timeout) {
Log.d(LOG_TAG, "Play length (ms): " + timeout);
this.mTimeout = timeout;
}
public boolean isLooping() {
return mLoop;
}
public void setLooping(boolean loop) {
Log.d(LOG_TAG, "Is looping: " + loop);
this.mLoop = loop;
}
public int getStartPosition() {
int position = 0;
if (mMediaPlayer != null) {
position = mMediaPlayer.getCurrentPosition();
}
return position;
}
public void setStartPosition(int position) {
Log.d(LOG_TAG, String.format("Start at %fs", position / 1000.));
this.mStartPosition = position;
}
public boolean isScreenOnWhilePlaying() {
return mScreenOnWhilePlaying;
}
public void setScreenOnWhilePlaying(boolean screenOnWhilePlaying) {
Log.d(LOG_TAG, "Screen ON while playing: " + screenOnWhilePlaying);
this.mScreenOnWhilePlaying = screenOnWhilePlaying;
}
#Override
public boolean onError(MediaPlayer mp, int what, int extra) {
_fail(String.format("Media player error: what=%d, extra=%d", what, extra));
return true;
}
}
The resource for the layout containing the SurfaceView:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<SurfaceView
android:id="#+id/surface"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</FrameLayout>
An example of use of the activity:
Intent intent = new Intent(parent, MediaPlayerActivity.class);
intent.putExtra(MediaPlayerActivity.SOURCE_URI, this.getSourceURI());
intent.putExtra(MediaPlayerActivity.PAUSE_ON_BACKGROUND,
this.getPauseOnBackground());
Scenario scenario = sequencer.getScenario();
intent.putExtra(MediaPlayerActivity.SCENARIO, scenario.getScenarioId());
intent.putExtra(MediaPlayerActivity.SEQUENCER, sequencer.getPosition());
intent.putExtra(MediaPlayerActivity.TEST, TestUtil.getTestPath(
scenario.getCurrentTest(), TestUtil.Path.Static));
// timeout option
TimeSpan timeout = this.getTimeout();
if (!timeout.isNull()) {
timeout.renew();
intent.putExtra(MediaPlayerActivity.TIMEOUT, timeout.value());
}
intent.putExtra(MediaPlayerActivity.LOOP, this.isLooping());
startActivity(intent);
#Sock have you thought about using the YouTube API for Android. They have a great playerview which gives you lots of control and event-listening ability on the video. I recently posted a tutorial on using the API if it might fit your needs, check it out here
I have an image view , i had written swiping , at that time of swiping,the images are downloading from Internet, so i thought i have to download the images in the background before swiping , for that which i need to use asynctask or Service or IntentService, all these will help in downloading and storing in data/data/mypackages , but still swiping gets slow in my case any idea, also convey me which one is best one, is it i'm calling in a right way
1. asynctask
2. services
3. Intent Service as shown below,
i m confused which one is right method because still my problem not solved
Here's asynctask code sample snippet
public class Demo extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
new FirstTask().execute(); // calling Asynctask here
}
}
Async Task code
private class FirstTask extends AsyncTask<Void, Void, Void> {
private final ProgressDialog dialog = new ProgressDialog(Catalogue.this);
int temp = 0;
// can use UI thread here
protected void onPreExecute() {
this.dialog.setMessage("Loading...");
this.dialog.setCancelable(false);
//this.dialog.show();
System.gc();
Toast.makeText(Catalogue.this, "My Async Created",
Toast.LENGTH_LONG).show();
}
#Override
protected Void doInBackground(Void... params) {
Looper.prepare();
try {
myddownloadmethod();// calling my download method
} catch (Exception e) {
Util.trace("Error in Async"+e.getMessage());
}
Looper.loop();
return null;
}
protected void onPostExecute(Void result) {
if (this.dialog.isShowing()) {
Toast.makeText(Catalogue.this, "My Async destroyed",
Toast.LENGTH_LONG).show();
Toast.makeText(Catalogue.this, "count" + temp,
Toast.LENGTH_LONG).show();
this.dialog.dismiss();
}
}
}
Here's My Service sinppet
public class MyService extends Service implements Runnable
{ #Override
public void onCreate() {
super.onCreate();
Thread mythread = new Thread(this);
mythread.start();
}
public void run() {
Looper.prepare();
try {
myddownloadmethod();// calling my download method
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
Looper.loop();
}
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
}
Invoking Service
public class ServicesDemo extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
startService(new Intent(this, MyService.class));
}
}
Here's IntentService Code
public class Downloader extends IntentService {
public Downloader() {
super("Downloader");
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public void onDestroy() {
super.onDestroy();
}
#Override
public void onHandleIntent(Intent i) {
try {
myddownloadmethod();// calling my download method
} catch (Exception e1) {
// TODO Auto-generated catch block
Log.d("Error",e1.getMessage());
}
}
}
Calling IntentService from MyActivity
public class ServicesDemo extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Intent i1=new Intent(this, Downloader.class);
startService(i1);
}
}
The best way to download it using the service like i have done to download the file from server and put in SD card also use the notification for it.
It is quite long code but i think the perfect one,if did not understand any thing then please go to android developer blog for services.
public class DownloadService extends Service{
SharedPreferences preferences;
private static final String DOCUMENT_VIEW_STATE_PREFERENCES = "DjvuDocumentViewState";
private Looper mServiceLooper;
private ServiceHandler mServiceHandler;
private NotificationManager mNM;
String downloadUrl;
public static boolean serviceState=false;
// Handler that receives messages from the thread
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
#Override
public void handleMessage(Message msg) {
downloadFile();
showNotification(getResources().getString(R.string.notification_catalog_downloaded),"VVS");
stopSelf(msg.arg1);
}
}
#Override
public void onCreate() {
serviceState=true;
mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
HandlerThread thread = new HandlerThread("ServiceStartArguments",1);
thread.start();
// Get the HandlerThread's Looper and use it for our Handler
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("SERVICE-ONCOMMAND","onStartCommand");
Bundle extra = intent.getExtras();
if(extra != null){
String downloadUrl = extra.getString("downloadUrl");
Log.d("URL",downloadUrl);
this.downloadUrl=downloadUrl;
}
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
mServiceHandler.sendMessage(msg);
// If we get killed, after returning from here, restart
return START_STICKY;
}
#Override
public void onDestroy() {
Log.d("SERVICE-DESTROY","DESTORY");
serviceState=false;
//Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show();
}
#Override
public IBinder onBind(Intent intent) {
// We don't provide binding, so return null
return null;
}
public void downloadFile(){
downloadFile(this.downloadUrl,fileName);
}
void showNotification(String message,String title) {
// In this sample, we'll use the same text for the ticker and the expanded notification
CharSequence text = message;
// Set the icon, scrolling text and timestamp
Notification notification = new Notification(R.drawable.icon, "vvs",
System.currentTimeMillis());
notification.flags |= Notification.FLAG_AUTO_CANCEL;
Intent intent = new Intent(this, HomeScreenActivity.class);
intent.setFlags (Intent.FLAG_ACTIVITY_CLEAR_TOP);
//The PendingIntent to launch our activity if the user selects this notification
PendingIntent contentIntent = PendingIntent.getActivity(this.getBaseContext(), 0,
intent, PendingIntent.FLAG_CANCEL_CURRENT);
// Set the info for the views that show in the notification panel.
notification.setLatestEventInfo(this, title,
text, contentIntent);
// Send the notification.
// We use a layout id because it is a unique number. We use it later to cancel.
mNM.notify(R.string.app_name, notification);
}
public void downloadFile(String fileURL, String fileName) {
StatFs stat_fs = new StatFs(Environment.getExternalStorageDirectory().getPath());
double avail_sd_space = (double)stat_fs.getAvailableBlocks() *(double)stat_fs.getBlockSize();
//double GB_Available = (avail_sd_space / 1073741824);
double MB_Available = (avail_sd_space / 10485783);
//System.out.println("Available MB : " + MB_Available);
Log.d("MB",""+MB_Available);
try {
File root =new File(Environment.getExternalStorageDirectory()+"/vvveksperten");
if(root.exists() && root.isDirectory()) {
}else{
root.mkdir();
}
Log.d("CURRENT PATH",root.getPath());
URL u = new URL(fileURL);
HttpURLConnection c = (HttpURLConnection) u.openConnection();
c.setRequestMethod("GET");
c.setDoOutput(true);
c.connect();
int fileSize = c.getContentLength()/1048576;
Log.d("FILESIZE",""+fileSize);
if(MB_Available <= fileSize ){
this.showNotification(getResources().getString(R.string.notification_no_memory),getResources().getString(R.string.notification_error));
c.disconnect();
return;
}
FileOutputStream f = new FileOutputStream(new File(root.getPath(), fileName));
InputStream in = c.getInputStream();
byte[] buffer = new byte[1024];
int len1 = 0;
while ((len1 = in.read(buffer)) > 0) {
f.write(buffer, 0, len1);
}
f.close();
File file = new File(root.getAbsolutePath() + "/" + "some.pdf");
if(file.exists()){
file.delete();
Log.d("FILE-DELETE","YES");
}else{
Log.d("FILE-DELETE","NO");
}
File from =new File(root.getAbsolutePath() + "/" + fileName);
File to = new File(root.getAbsolutePath() + "/" + "some.pdf");
} catch (Exception e) {
Log.d("Downloader", e.getMessage());
}
For anyone running into this question later, take a look at the async download mechanism used in the android sample code for the project com.example.android.bitmapfun.ui.ImageGridActivity. It downloads images asynchronously and also caches them for offline display in an ImageView. Folks have wrapped their code around this one and made image loading libraries of their own. These libraries use an AsyncTask instead of a service. Async tasks are expected to wrap up their work within a couple of seconds.
If you are looking to download something larger, I'd recommend the DownloadManager that is available since API 9 instead of using services. There is a lot of code in there that adds resilience to the download.
The download manager is a system service that handles long-running HTTP downloads. Clients may request that a URI be downloaded to a particular destination file. The download manager will conduct the download in the background, taking care of HTTP interactions and retrying downloads after failures or across connectivity changes and system reboots. Instances of this class should be obtained through getSystemService(String) by passing DOWNLOAD_SERVICE. Apps that request downloads through this API should register a broadcast receiver for ACTION_NOTIFICATION_CLICKED to appropriately handle when the user clicks on a running download in a notification or from the downloads UI. Note that the application must have the INTERNET permission to use this class.
You are probably over engineering this. I have implemented swiping with dynamically loading images and I just a use a simple utility class that does it all for me via static method call.
Try this class:
package com.beget.consumer.util;
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you 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.
*/
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.WeakReference;
import java.net.MalformedURLException;
import java.util.HashMap;
import java.util.Map;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.ImageView;
public class DrawableLoader {
private final Map<String, Drawable> drawableMap;
private WeakReference<ImageView> imageViewReference;
public DrawableLoader() {
drawableMap = new HashMap<String, Drawable>();
}
public Drawable fetchDrawable(String urlString) {
if (drawableMap.containsKey(urlString)) {
return drawableMap.get(urlString);
}
Log.d(this.getClass().getSimpleName(), "image url:" + urlString);
try {
InputStream is = fetch(urlString);
Drawable drawable = Drawable.createFromStream(is, "src");
drawableMap.put(urlString, drawable);
Log.d(this.getClass().getSimpleName(), "got a thumbnail drawable: " + drawable.getBounds() + ", "
+ drawable.getIntrinsicHeight() + "," + drawable.getIntrinsicWidth() + ", "
+ drawable.getMinimumHeight() + "," + drawable.getMinimumWidth());
return drawable;
} catch (MalformedURLException e) {
Log.e(this.getClass().getSimpleName(), "fetchDrawable failed", e);
return null;
} catch (IOException e) {
Log.e(this.getClass().getSimpleName(), "fetchDrawable failed", e);
return null;
}
}
public void fetchDrawableOnThread(final String urlString, final ImageView imageView) {
imageViewReference = new WeakReference<ImageView>(imageView);
if (drawableMap.containsKey(urlString)) {
imageViewReference.get().setImageDrawable(drawableMap.get(urlString));
}
final Handler handler = new Handler() {
#Override
public void handleMessage(Message message) {
imageViewReference.get().setImageDrawable((Drawable) message.obj);
}
};
Thread thread = new Thread() {
#Override
public void run() {
//TODO : set imageView to a "pending" image
Drawable drawable = fetchDrawable(urlString);
Message message = handler.obtainMessage(1, drawable);
handler.sendMessage(message);
}
};
thread.start();
}
private InputStream fetch(String urlString) throws MalformedURLException, IOException {
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpGet request = new HttpGet(urlString);
HttpResponse response = httpClient.execute(request);
return response.getEntity().getContent();
}
}
This is all you need. Then when you need to load an image, you call:
fetchDrawableOnThread("http://path/to/your/image.jpg", yourImageViewReference);
That's it.
If you have an URL from a JSON object, parse the URL into your string so:
String url = jsonObj.getString("url");
Then call fetchDrawableOnThread(url, yourImageViewReference);
Use volley.
Using volley network image view you can do this
we use latest architecure components here.We make some observers with live data for some flag that represents download status.In service we download the image and completing we update the live data so that the observers method automatically called
I have an image view , i had written swiping , at that time of swiping,the images are downloading from Internet, so i thought i have to download the images in the background before swiping , for that which i need to use asynctask or Service or IntentService, all these will help in downloading and storing in data/data/mypackages , but still swiping gets slow in my case any idea, also convey me which one is best one, is it i'm calling in a right way
1. asynctask
2. services
3. Intent Service as shown below,
i m confused which one is right method because still my problem not solved
Here's asynctask code sample snippet
public class Demo extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
new FirstTask().execute(); // calling Asynctask here
}
}
Async Task code
private class FirstTask extends AsyncTask<Void, Void, Void> {
private final ProgressDialog dialog = new ProgressDialog(Catalogue.this);
int temp = 0;
// can use UI thread here
protected void onPreExecute() {
this.dialog.setMessage("Loading...");
this.dialog.setCancelable(false);
//this.dialog.show();
System.gc();
Toast.makeText(Catalogue.this, "My Async Created",
Toast.LENGTH_LONG).show();
}
#Override
protected Void doInBackground(Void... params) {
Looper.prepare();
try {
myddownloadmethod();// calling my download method
} catch (Exception e) {
Util.trace("Error in Async"+e.getMessage());
}
Looper.loop();
return null;
}
protected void onPostExecute(Void result) {
if (this.dialog.isShowing()) {
Toast.makeText(Catalogue.this, "My Async destroyed",
Toast.LENGTH_LONG).show();
Toast.makeText(Catalogue.this, "count" + temp,
Toast.LENGTH_LONG).show();
this.dialog.dismiss();
}
}
}
Here's My Service sinppet
public class MyService extends Service implements Runnable
{ #Override
public void onCreate() {
super.onCreate();
Thread mythread = new Thread(this);
mythread.start();
}
public void run() {
Looper.prepare();
try {
myddownloadmethod();// calling my download method
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
Looper.loop();
}
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
}
Invoking Service
public class ServicesDemo extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
startService(new Intent(this, MyService.class));
}
}
Here's IntentService Code
public class Downloader extends IntentService {
public Downloader() {
super("Downloader");
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public void onDestroy() {
super.onDestroy();
}
#Override
public void onHandleIntent(Intent i) {
try {
myddownloadmethod();// calling my download method
} catch (Exception e1) {
// TODO Auto-generated catch block
Log.d("Error",e1.getMessage());
}
}
}
Calling IntentService from MyActivity
public class ServicesDemo extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Intent i1=new Intent(this, Downloader.class);
startService(i1);
}
}
The best way to download it using the service like i have done to download the file from server and put in SD card also use the notification for it.
It is quite long code but i think the perfect one,if did not understand any thing then please go to android developer blog for services.
public class DownloadService extends Service{
SharedPreferences preferences;
private static final String DOCUMENT_VIEW_STATE_PREFERENCES = "DjvuDocumentViewState";
private Looper mServiceLooper;
private ServiceHandler mServiceHandler;
private NotificationManager mNM;
String downloadUrl;
public static boolean serviceState=false;
// Handler that receives messages from the thread
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
#Override
public void handleMessage(Message msg) {
downloadFile();
showNotification(getResources().getString(R.string.notification_catalog_downloaded),"VVS");
stopSelf(msg.arg1);
}
}
#Override
public void onCreate() {
serviceState=true;
mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
HandlerThread thread = new HandlerThread("ServiceStartArguments",1);
thread.start();
// Get the HandlerThread's Looper and use it for our Handler
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("SERVICE-ONCOMMAND","onStartCommand");
Bundle extra = intent.getExtras();
if(extra != null){
String downloadUrl = extra.getString("downloadUrl");
Log.d("URL",downloadUrl);
this.downloadUrl=downloadUrl;
}
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
mServiceHandler.sendMessage(msg);
// If we get killed, after returning from here, restart
return START_STICKY;
}
#Override
public void onDestroy() {
Log.d("SERVICE-DESTROY","DESTORY");
serviceState=false;
//Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show();
}
#Override
public IBinder onBind(Intent intent) {
// We don't provide binding, so return null
return null;
}
public void downloadFile(){
downloadFile(this.downloadUrl,fileName);
}
void showNotification(String message,String title) {
// In this sample, we'll use the same text for the ticker and the expanded notification
CharSequence text = message;
// Set the icon, scrolling text and timestamp
Notification notification = new Notification(R.drawable.icon, "vvs",
System.currentTimeMillis());
notification.flags |= Notification.FLAG_AUTO_CANCEL;
Intent intent = new Intent(this, HomeScreenActivity.class);
intent.setFlags (Intent.FLAG_ACTIVITY_CLEAR_TOP);
//The PendingIntent to launch our activity if the user selects this notification
PendingIntent contentIntent = PendingIntent.getActivity(this.getBaseContext(), 0,
intent, PendingIntent.FLAG_CANCEL_CURRENT);
// Set the info for the views that show in the notification panel.
notification.setLatestEventInfo(this, title,
text, contentIntent);
// Send the notification.
// We use a layout id because it is a unique number. We use it later to cancel.
mNM.notify(R.string.app_name, notification);
}
public void downloadFile(String fileURL, String fileName) {
StatFs stat_fs = new StatFs(Environment.getExternalStorageDirectory().getPath());
double avail_sd_space = (double)stat_fs.getAvailableBlocks() *(double)stat_fs.getBlockSize();
//double GB_Available = (avail_sd_space / 1073741824);
double MB_Available = (avail_sd_space / 10485783);
//System.out.println("Available MB : " + MB_Available);
Log.d("MB",""+MB_Available);
try {
File root =new File(Environment.getExternalStorageDirectory()+"/vvveksperten");
if(root.exists() && root.isDirectory()) {
}else{
root.mkdir();
}
Log.d("CURRENT PATH",root.getPath());
URL u = new URL(fileURL);
HttpURLConnection c = (HttpURLConnection) u.openConnection();
c.setRequestMethod("GET");
c.setDoOutput(true);
c.connect();
int fileSize = c.getContentLength()/1048576;
Log.d("FILESIZE",""+fileSize);
if(MB_Available <= fileSize ){
this.showNotification(getResources().getString(R.string.notification_no_memory),getResources().getString(R.string.notification_error));
c.disconnect();
return;
}
FileOutputStream f = new FileOutputStream(new File(root.getPath(), fileName));
InputStream in = c.getInputStream();
byte[] buffer = new byte[1024];
int len1 = 0;
while ((len1 = in.read(buffer)) > 0) {
f.write(buffer, 0, len1);
}
f.close();
File file = new File(root.getAbsolutePath() + "/" + "some.pdf");
if(file.exists()){
file.delete();
Log.d("FILE-DELETE","YES");
}else{
Log.d("FILE-DELETE","NO");
}
File from =new File(root.getAbsolutePath() + "/" + fileName);
File to = new File(root.getAbsolutePath() + "/" + "some.pdf");
} catch (Exception e) {
Log.d("Downloader", e.getMessage());
}
For anyone running into this question later, take a look at the async download mechanism used in the android sample code for the project com.example.android.bitmapfun.ui.ImageGridActivity. It downloads images asynchronously and also caches them for offline display in an ImageView. Folks have wrapped their code around this one and made image loading libraries of their own. These libraries use an AsyncTask instead of a service. Async tasks are expected to wrap up their work within a couple of seconds.
If you are looking to download something larger, I'd recommend the DownloadManager that is available since API 9 instead of using services. There is a lot of code in there that adds resilience to the download.
The download manager is a system service that handles long-running HTTP downloads. Clients may request that a URI be downloaded to a particular destination file. The download manager will conduct the download in the background, taking care of HTTP interactions and retrying downloads after failures or across connectivity changes and system reboots. Instances of this class should be obtained through getSystemService(String) by passing DOWNLOAD_SERVICE. Apps that request downloads through this API should register a broadcast receiver for ACTION_NOTIFICATION_CLICKED to appropriately handle when the user clicks on a running download in a notification or from the downloads UI. Note that the application must have the INTERNET permission to use this class.
You are probably over engineering this. I have implemented swiping with dynamically loading images and I just a use a simple utility class that does it all for me via static method call.
Try this class:
package com.beget.consumer.util;
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you 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.
*/
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.WeakReference;
import java.net.MalformedURLException;
import java.util.HashMap;
import java.util.Map;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.ImageView;
public class DrawableLoader {
private final Map<String, Drawable> drawableMap;
private WeakReference<ImageView> imageViewReference;
public DrawableLoader() {
drawableMap = new HashMap<String, Drawable>();
}
public Drawable fetchDrawable(String urlString) {
if (drawableMap.containsKey(urlString)) {
return drawableMap.get(urlString);
}
Log.d(this.getClass().getSimpleName(), "image url:" + urlString);
try {
InputStream is = fetch(urlString);
Drawable drawable = Drawable.createFromStream(is, "src");
drawableMap.put(urlString, drawable);
Log.d(this.getClass().getSimpleName(), "got a thumbnail drawable: " + drawable.getBounds() + ", "
+ drawable.getIntrinsicHeight() + "," + drawable.getIntrinsicWidth() + ", "
+ drawable.getMinimumHeight() + "," + drawable.getMinimumWidth());
return drawable;
} catch (MalformedURLException e) {
Log.e(this.getClass().getSimpleName(), "fetchDrawable failed", e);
return null;
} catch (IOException e) {
Log.e(this.getClass().getSimpleName(), "fetchDrawable failed", e);
return null;
}
}
public void fetchDrawableOnThread(final String urlString, final ImageView imageView) {
imageViewReference = new WeakReference<ImageView>(imageView);
if (drawableMap.containsKey(urlString)) {
imageViewReference.get().setImageDrawable(drawableMap.get(urlString));
}
final Handler handler = new Handler() {
#Override
public void handleMessage(Message message) {
imageViewReference.get().setImageDrawable((Drawable) message.obj);
}
};
Thread thread = new Thread() {
#Override
public void run() {
//TODO : set imageView to a "pending" image
Drawable drawable = fetchDrawable(urlString);
Message message = handler.obtainMessage(1, drawable);
handler.sendMessage(message);
}
};
thread.start();
}
private InputStream fetch(String urlString) throws MalformedURLException, IOException {
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpGet request = new HttpGet(urlString);
HttpResponse response = httpClient.execute(request);
return response.getEntity().getContent();
}
}
This is all you need. Then when you need to load an image, you call:
fetchDrawableOnThread("http://path/to/your/image.jpg", yourImageViewReference);
That's it.
If you have an URL from a JSON object, parse the URL into your string so:
String url = jsonObj.getString("url");
Then call fetchDrawableOnThread(url, yourImageViewReference);
Use volley.
Using volley network image view you can do this
we use latest architecure components here.We make some observers with live data for some flag that represents download status.In service we download the image and completing we update the live data so that the observers method automatically called
I'm stuck with a memory leak that I cannot fix. I identified where it occurs, using the MemoryAnalizer but I vainly struggle to get rid of it. Here is the code:
public class MyActivity extends Activity implements SurfaceHolder.Callback {
...
Camera.PictureCallback mPictureCallbackJpeg = new Camera.PictureCallback() {
public void onPictureTaken(byte[] data, Camera c) {
try {
// log the action
Log.e(getClass().getSimpleName(), "PICTURE CALLBACK JPEG: data.length = " + data);
// Show the ProgressDialog on this thread
pd = ProgressDialog.show(MyActivity.this, "", "Préparation", true, false);
// Start a new thread that will manage the capture
new ManageCaptureTask().execute(data, c);
}
catch(Exception e){
AlertDialog.Builder dialog = new AlertDialog.Builder(MyActivity.this);
...
dialog.create().show();
}
}
class ManageCaptureTask extends AsyncTask<Object, Void, Boolean> {
protected Boolean doInBackground(Object... args) {
Boolean isSuccess = false;
// initialize the bitmap before the capture
((myApp) getApplication()).setBitmapX(null);
try{
// Check if it is a real device or an emulator
TelephonyManager telmgr = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
String deviceID = telmgr.getDeviceId();
boolean isEmulator = "000000000000000".equalsIgnoreCase(deviceID);
// get the bitmap
if (isEmulator) {
((myApp) getApplication()).setBitmapX(BitmapFactory.decodeFile(imageFileName));
} else {
((myApp) getApplication()).setBitmapX(BitmapFactory.decodeByteArray((byte[]) args[0], 0, ((byte[])args[0]).length));
}
((myApp) getApplication()).setImageForDB(ImageTools.resizeBmp(((myApp) getApplication()).getBmp()));
// convert the bitmap into a grayscale image and display it in the preview
((myApp) getApplication()).setImage(makeGrayScale());
isSuccess = true;
}
catch (Exception connEx){
errorMessageFromBkgndThread = getString(R.string.errcapture);
}
return isSuccess;
}
protected void onPostExecute(Boolean result) {
// Pass the result data back to the main activity
if (MyActivity.this.pd != null) {
MyActivity.this.pd.dismiss();
}
if (result){
((ImageView) findViewById(R.id.apercu)).setImageBitmap(((myApp) getApplication()).getBmp());
((myApp) getApplication()).setBitmapX(null);
}
else{
// there was an error
ErrAlert();
}
}
}
};
private void ErrAlert(){
// notify the user about the error
AlertDialog.Builder dialog = new AlertDialog.Builder(this);
...
dialog.create().show();
}
}
The activity is terminated on a button click, like this:
Button use = (Button) findViewById(R.id.use);
use.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(MyActivity.this, NextActivity.class);
intent.putExtra("dbID", "-1");
intent.putExtra("category", category);
((myApp) getApplication()).setBitmapX(null);
MyActivity.this.startActivity(intent);
MyActivity.this.finish();
}
});
MemoryAnalyzer indicated the memory leak at:
((myApp) getApplication()).setBitmapX(BitmapFactory.decodeByteArray((byte[]) args[0], 0, ((byte[])args[0]).length));
I am grateful for any suggestion, thank you in advance.
Is your thread garbage collected after onPostExecute is called or is it still in the memory?
A Async Task will not be canceled or destroyed at the moment the activity is dismissed. If your thread is more or less lightweight and finishes after a small time, just keep it running and add a MyActivity.this.isFinishing() clause in the onPostExecute() method.
Your Task stores a implicit reference to your Activity MyActivity.this because it is a private class inside the activity. This means that your Activity will not be garbage collected until the task exits.
You can try below code snippet
protected void onPostExecute(Boolean result) {
if(YourActivity.this.isFinished()){
//to smomething here
}
}