I'm trying to build a custom launcher app. I'm stuck at restoring widgets when activity is restarted.
After picking a widget the widgetID is stored to shared prefs and in onCreate I'm trying to restore the previous set widgets. I was following this tutorial.
AppWidgetManager mAppWidgetManager;
AppWidgetHost mAppWidgetHost;
ViewGroup hostView;
int numWidgets = 0;
/**
* Called on the creation of the activity.
*/
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dashboard);
hostView = (ViewGroup) findViewById(R.id.LAYOUT_DASHBOARD);
hostView.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View view) {
if(numWidgets < 4) {
selectWidget();
}else {
removeAllWidgets();
numWidgets = 0;
}
return false;
}
});
mAppWidgetManager = AppWidgetManager.getInstance(this);
mAppWidgetHost = new AppWidgetHost(this, R.id.APPWIDGET_HOST_ID);
restoreWidgets();
}
/**
* Launches the menu to select the widget. The selected widget will be on
* the result of the activity.
*/
void selectWidget() {
int appWidgetId = this.mAppWidgetHost.allocateAppWidgetId();
Intent pickIntent = new Intent(AppWidgetManager.ACTION_APPWIDGET_PICK);
pickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
addEmptyData(pickIntent);
startActivityForResult(pickIntent, R.id.REQUEST_PICK_APPWIDGET);
}
/**
* This avoids a bug in the com.android.settings.AppWidgetPickActivity,
* which is used to select widgets. This just adds empty extras to the
* intent, avoiding the bug.
*
* See more: http://code.google.com/p/android/issues/detail?id=4272
*/
void addEmptyData(Intent pickIntent) {
ArrayList<AppWidgetProviderInfo> customInfo = new ArrayList<AppWidgetProviderInfo>();
pickIntent.putParcelableArrayListExtra(AppWidgetManager.EXTRA_CUSTOM_INFO, customInfo);
ArrayList<Bundle> customExtras = new ArrayList<Bundle>();
pickIntent.putParcelableArrayListExtra(AppWidgetManager.EXTRA_CUSTOM_EXTRAS, customExtras);
}
/**
* If the user has selected an widget, the result will be in the 'data' when
* this function is called.
*/
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
if (requestCode == R.id.REQUEST_PICK_APPWIDGET) {
configureWidget(data);
} else if (requestCode == R.id.REQUEST_CREATE_APPWIDGET) {
createWidget(data);
}
} else if (resultCode == RESULT_CANCELED && data != null) {
int appWidgetId = data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);
if (appWidgetId != -1) {
mAppWidgetHost.deleteAppWidgetId(appWidgetId);
}
}
}
/**
* Checks if the widget needs any configuration. If it needs, launches the
* configuration activity.
*/
private void configureWidget(Intent data) {
Bundle extras = data.getExtras();
int appWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);
AppWidgetProviderInfo appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(appWidgetId);
if (appWidgetInfo.configure != null) {
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE);
intent.setComponent(appWidgetInfo.configure);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
startActivityForResult(intent, R.id.REQUEST_CREATE_APPWIDGET);
} else {
createWidget(data);
}
}
/**
* Creates the widget and adds to our view layout.
*/
public void createWidget(Intent data) {
if(numWidgets<4) {
Bundle extras = data.getExtras();
int appWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);
AppWidgetProviderInfo appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(appWidgetId);
AppWidgetHostView widHostView = mAppWidgetHost.createView(this, appWidgetId, appWidgetInfo);
widHostView.setAppWidget(appWidgetId, appWidgetInfo);
SharedPreferences sharedPref = this.getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putInt("ID"+numWidgets, appWidgetId);
editor.commit();
attachWidget(widHostView);
}
}
/**
* Attaches a new widget at the right position on hostView
* #param widHostView widget to attach
*/
public void attachWidget(AppWidgetHostView widHostView){
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(hostView.getWidth() / 2, hostView.getHeight() / 2);
if (numWidgets < 2) {
lp.leftMargin = numWidgets * (hostView.getWidth() / 2);
lp.topMargin = 0;
} else {
lp.leftMargin = (numWidgets - 2) * (hostView.getWidth() / 2);
lp.topMargin = hostView.getHeight() / 2;
}
this.hostView.addView(widHostView, lp);
numWidgets++;
}
/**
* Restores all widgets from shared preferences
*/
public void restoreWidgets()
{
SharedPreferences sharedPref = this.getPreferences(Context.MODE_PRIVATE);
restoreWidget(sharedPref.getInt("ID0", -1));
restoreWidget(sharedPref.getInt("ID1", -1));
restoreWidget(sharedPref.getInt("ID2", -1));
restoreWidget(sharedPref.getInt("ID3", -1));
}
/**
* Restores a single widget
*/
public void restoreWidget(int _widgetId){
if(_widgetId < 0){
return;
}
AppWidgetProviderInfo appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(_widgetId);
AppWidgetHostView hostView = mAppWidgetHost.createView(this, _widgetId, appWidgetInfo);
hostView.setAppWidget(_widgetId, appWidgetInfo);
attachWidget(hostView);
}
/**
* Registers the AppWidgetHost to listen for updates to any widgets this app
* has.
*/
#Override
protected void onStart() {
super.onStart();
mAppWidgetHost.startListening();
}
/**
* Stop listen for updates for our widgets (saving battery).
*/
#Override
protected void onStop() {
super.onStop();
mAppWidgetHost.stopListening();
}
/**
* Removes the widget displayed by this AppWidgetHostView.
*/
public void removeWidget(AppWidgetHostView hostView) {
mAppWidgetHost.deleteAppWidgetId(hostView.getAppWidgetId());
this.hostView.removeView(hostView);
}
/**
* Removes all widgets displayed on screen.
*/
public void removeAllWidgets(){
boolean stop = false;
do{
int childCount = hostView.getChildCount();
if (childCount >= 1) {
View view = hostView.getChildAt(childCount - 1);
if (view instanceof AppWidgetHostView) {
removeWidget((AppWidgetHostView) view);
}
}else{
stop = true;
}
}while (!stop);
}
}
I did some debugging for this and realized, that you need to store the appWidgetIds for each widget added. When I stored appWidgetIds and tried to get AppWidgetProviderInfo from them, the width and height was always 0, BUT mAppWidgetHost.createView would return a valid view. So to fix this store the last width and height, the id, and any other data you wish to a WidgetHolder. Then you can store those values into SharedPreferences if you wish.
Here is a working WidgetHolder class I wrote ...
import android.util.Base64;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class WidgetHolder implements Serializable {
// any other data you want
public int id;
public int width, height;
public WidgetHolder() {}
public WidgetHolder(int id, int width, int height) {
this.id = id;
this.width = width;
this.height = height;
}
public static WidgetHolder deserialize( String data ) {
try {
byte [] bites = Base64.decode( data.getBytes(), 0);
ByteArrayInputStream bis = new ByteArrayInputStream( bites );
ObjectInputStream ois = new ObjectInputStream( bis );
WidgetHolder holder = (WidgetHolder) ois.readObject();
ois.close();
return holder;
} catch (IOException e ) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return new WidgetHolder();
}
public String serialize() {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream( baos );
oos.writeObject(this);
oos.flush();
return new String(Base64.encode(baos.toByteArray(), 0));
} catch( IOException e ) {
return "";
}
}
}
Then whenever you add a new AppWidget to your AppWidgetHost you store the WidgetHolder data to SharedPreferences or a cached file.
private void handleAddNewAppWidget( int appWidgetId, AppWidgetProviderInfo info ) {
// use application context, for issues with support v7 libs causing AppCompatImage exceptions
AppWidgetHostView hostView = mAppWidgetHost
.createView(context.getApplicationContext(), appWidgetId, info);
hostView.setAppWidget(appWidgetId, info);
// calculate width and height for hostView from info.minHeight and info.minWidth
RelativeLayout.LayoutParams rlp = new RelativeLayout.LayoutParams( width, height );
hostView.setLayoutParams(rlp);
// add hostView to widgetContainer (RelativeLayout)
widgetContainer.addView(hostView);
// create widgetHolder
WidgetHolder holder = new WidgetHolder( appWidgetId, width, height );
String serialized = holder.serialize();
// storage is a wrapper for SharedPreferences, the key is the appWidgetId, and the value is the serialized content
storage.store(appWidgetId + "", serialized);
}
private void handleRestoreWidgets(ArrayList<String> widgets) {
// Retrieve all saved widgets from Storage
for( int i = 0; i < widgets.size(); i++ ) {
String widgetString = widgets.get(i);
WidgetHolder holder = WidgetHolder.deserialize(widgetString);
AppWidgetProviderInfo info = AppWidgetManager
.getInstance(getContext().getApplicationContext() )
.getAppWidgetInfo(holder.id);
AppWidgetHostView hostView = mAppWidgetHost
.createView(context.getApplicationContext(), holder.id, info);
hostView.setAppWidget(holder.id, info);
RelativeLayout.LayoutParams rlp = new RelativeLayout.LayoutParams( holder.width,
holder.height );
hostView.setLayoutParams(rlp);
// restore app widget from holder
widgetContainer.addView(hostView);
}
}
The Storage class was not included for brevity as this post is already long. However, to get all key-value pairs from SharedPreferences is easy.
A small example ...
Map<String, String> allKeyValues = getContext().getSharedPreferences("WidgetHolders", Context.MODE_PRIVATE).getAll();
// then to get all stored String do
ArrayList<String> serializedWidgetHolders = new ArrayList<String>( allKeyValues.values() );
Related
I'm using sharedElementTransition in my app and i've used a custom class for sharedElementCallback to update the views at run time. It was causing OutOfMemory errors at sometimes, so i searched about it and from this solution i used code of LeakFreeSupportSharedElementCallback to avoid crashes but i still get following crash logs very often.
Fatal Exception: java.lang.OutOfMemoryError: Failed to allocate a 8357052 byte allocation with 953048 free bytes and 930KB until OOM
at dalvik.system.VMRuntime.newNonMovableArray(VMRuntime.java)
at android.graphics.Bitmap.nativeCopy(Bitmap.java)
at android.graphics.Bitmap.copy(Bitmap.java:684)
at com.fayvo.ui.main.home.post.PostDetailSharedElementCallback.onCreateSnapshotView(PostDetailSharedElementCallback.java:279)
at android.support.v4.app.ActivityCompat$SharedElementCallback21Impl.onCreateSnapshotView(ActivityCompat.java:609)
at android.app.ActivityTransitionCoordinator.createSnapshots(ActivityTransitionCoordinator.java:666)
at android.app.EnterTransitionCoordinator.startSharedElementTransition(EnterTransitionCoordinator.java:400)
at android.app.EnterTransitionCoordinator.-wrap4(EnterTransitionCoordinator.java)
at android.app.EnterTransitionCoordinator$5$1$1.run(EnterTransitionCoordinator.java:475)
at android.app.ActivityTransitionCoordinator.startTransition(ActivityTransitionCoordinator.java:836)
at android.app.EnterTransitionCoordinator$5$1.onPreDraw(EnterTransitionCoordinator.java:472)
at android.view.ViewTreeObserver.dispatchOnPreDraw(ViewTreeObserver.java:1013)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2513)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1522)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7098)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:927)
at android.view.Choreographer.doCallbacks(Choreographer.java:702)
at android.view.Choreographer.doFrame(Choreographer.java:638)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:913)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6682)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1520)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1410)
CustomCallback class:
public class CustomSharedElementCallback extends SharedElementCallback {
static final String BUNDLE_SNAPSHOT_BITMAP = "BUNDLE_SNAPSHOT_BITMAP";
static final String BUNDLE_SNAPSHOT_IMAGE_SCALETYPE = "BUNDLE_SNAPSHOT_IMAGE_SCALETYPE";
static final String BUNDLE_SNAPSHOT_IMAGE_MATRIX = "BUNDLE_SNAPSHOT_IMAGE_MATRIX";
static final String BUNDLE_SNAPSHOT_TYPE = "BUNDLE_SNAPSHOT_TYPE";
static final String BUNDLE_SNAPSHOT_TYPE_IMAGE_VIEW = "BUNDLE_SNAPSHOT_TYPE";
private static int MAX_IMAGE_SIZE = (1024 * 1024);
private List<View> mSharedElements;
private int currentPosition = 0;
private boolean enableChangeImageTransform;
private SparseArray<Matrix> tempMatrixes;
public PostDetailSharedElementCallback() {
mSharedElements = new ArrayList<>();
tempMatrixes = new SparseArray<>();
}
#Override
public void onSharedElementStart(List<String> sharedElementNames,
List<View> sharedElements,
List<View> sharedElementSnapshots) {
/*AppLogger.d("usm_shared_callback_0.1", "onSharedElementStart: " + sharedElementNames.get(0)
+ " ,enableChangeImageTransform= " + enableChangeImageTransform
);*/
boolean allowTransform = enableChangeImageTransform && sharedElements != null && sharedElements.size() > 0;
if (allowTransform && sharedElements.get(0) instanceof CustomPhotoView) {
((CustomPhotoView) sharedElements.get(0)).setScaleType(ImageView.ScaleType.CENTER_CROP);
} else if (allowTransform && sharedElements.get(0) instanceof ImageView) {
((ImageView) sharedElements.get(0)).setScaleType(ImageView.ScaleType.FIT_CENTER);
}
}
#Override
public void onSharedElementEnd(List<String> sharedElementNames, List<View> sharedElements, List<View> sharedElementSnapshots) {
/*AppLogger.d("usm_shared_callback_0.2", "onSharedElementEnd: " + sharedElementNames.get(0)
+ " ,enableChangeImageTransform= " + enableChangeImageTransform
);*/
boolean allowTransform = enableChangeImageTransform && sharedElements != null && sharedElements.size() > 0;
if (allowTransform && sharedElements.get(0) instanceof CustomPhotoView) {
((CustomPhotoView) sharedElements.get(0)).setScaleType(ImageView.ScaleType.FIT_CENTER);
// updateCloudChipBoxTagsView(sharedElementNames, sharedElements);
updateBoxIconView(sharedElementNames, sharedElements);
updateUserNameView(sharedElementNames, sharedElements);
} else if (allowTransform && sharedElements.get(0) instanceof ImageView) {
((ImageView) sharedElements.get(0)).setScaleType(ImageView.ScaleType.CENTER_CROP);
}
}
private void updateCloudChipBoxTagsView(List<String> sharedElementNames, List<View> sharedElements) {
int i = 0;
for (String sharedName : sharedElementNames) {
if (sharedName.contains(PostTags.TRANSITION_NAME_TAGS)) {
if (sharedElements.get(i) instanceof ChipCloud) {
ChipCloud chipCloud = ((ChipCloud) sharedElements.get(i));
int textColor = ContextCompat.getColor(chipCloud.getContext(), R.color.fayvo_color);
// adding modifyChips method to make animation transition experience a bit better
chipCloud.modifyChips(chipCloud.getContext().getResources().getDimension(R.dimen.hint_text_size), textColor);
break;
}
}
i++;
}
}
private void updateBoxIconView(List<String> sharedElementNames, List<View> sharedElements) {
int i = 0;
for (String sharedName : sharedElementNames) {
if (sharedName.contains(PostTags.TRANSITION_NAME_BOX_ICON)) {
if (sharedElements.get(i) instanceof ImageView) {
ImageView ivBoxIcon = (ImageView) sharedElements.get(i);
int color = ContextCompat.getColor(ivBoxIcon.getContext(), R.color.fayvo_color);
ivBoxIcon.setColorFilter(color);
break;
}
}
i++;
}
}
private void updateUserNameView(List<String> sharedElementNames, List<View> sharedElements) {
int i = 0;
for (String sharedName : sharedElementNames) {
if (sharedName.contains(PostTags.TRANSITION_NAME_USERNAME)) {
if (sharedElements.get(i) instanceof TextView) {
TextView textView = (TextView) sharedElements.get(i);
int color = ContextCompat.getColor(textView.getContext(), R.color.black);
float textSizePx = textView.getContext().getResources().getDimension(R.dimen.et_text_size);
textView.setTextColor(color);
textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSizePx);
break;
}
}
i++;
}
}
#Override
public void onMapSharedElements(List<String> names, Map<String, View> sharedElements) {
removeObsoleteElements(names, sharedElements, mapObsoleteElements(names));
// update transition names
setTransitionNames();
for (int i = 0; i < mSharedElements.size(); i++)
mapSharedElement(names, sharedElements, mSharedElements.get(i));
}
public int getCurrentPosition() {
return currentPosition;
}
public void setCurrentPosition(int position) {
// AppLogger.d("usm_shared_callback_1", "currentPosition= " + position);
this.currentPosition = position;
}
public void setEnableChangeImageTransform(boolean enableTransform) {
this.enableChangeImageTransform = enableTransform;
}
/**
* This method is used to set Transition name of shared views.
* Note: Keep the sequence exactly same in which the views are
* passed for transition.
*/
public void setTransitionNames() {
// AppLogger.d("usm_shared_callback_2", "Setting transition names: " + currentPosition);
if (mSharedElements.size() > 0)
ViewCompat.setTransitionName(mSharedElements.get(0), PostTags.TRANSITION_NAME_POST_BODY + currentPosition);
if (mSharedElements.size() > 1)
ViewCompat.setTransitionName(mSharedElements.get(1), PostTags.TRANSITION_NAME_USER_PIC + currentPosition);
if (mSharedElements.size() > 2)
ViewCompat.setTransitionName(mSharedElements.get(2), PostTags.TRANSITION_NAME_USERNAME + currentPosition);
if (mSharedElements.size() > 3)
ViewCompat.setTransitionName(mSharedElements.get(3), PostTags.TRANSITION_NAME_TAGS + currentPosition);
if (mSharedElements.size() > 4)
ViewCompat.setTransitionName(mSharedElements.get(4), PostTags.TRANSITION_NAME_BOX_ICON + currentPosition);
}
public List<View> getSharedViews() {
// AppLogger.d("usm_shared_callback_4", "setSharedViews is called");
if (mSharedElements != null)
return mSharedElements;
return null;
}
public void setSharedViews(#NonNull View... sharedViews) {
// AppLogger.d("usm_shared_callback_4", "setSharedViews is called");
clearSharedViews();
for (View view : sharedViews) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
mSharedElements.add(view);
}
}
}
public void clearSharedViews() {
mSharedElements.clear();
tempMatrixes.clear();
}
/**
* Maps all views that don't start with "android" namespace.
*
* #param names All shared element names.
* #return The obsolete shared element names.
*/
#NonNull
private List<String> mapObsoleteElements(List<String> names) {
List<String> elementsToRemove = new ArrayList<>(names.size());
for (String name : names) {
if (name.startsWith("android")) continue;
elementsToRemove.add(name);
}
return elementsToRemove;
}
/**
* Removes obsolete elements from names and shared elements.
*
* #param names Shared element names.
* #param sharedElements Shared elements.
* #param elementsToRemove The elements that should be removed.
*/
private void removeObsoleteElements(List<String> names,
Map<String, View> sharedElements,
List<String> elementsToRemove) {
if (elementsToRemove.size() > 0) {
names.removeAll(elementsToRemove);
for (String elementToRemove : elementsToRemove) {
sharedElements.remove(elementToRemove);
}
}
}
/**
* Puts a shared element to transitions and names.
*
* #param names The names for this transition.
* #param sharedElements The elements for this transition.
* #param view The view to add.
*/
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void mapSharedElement(List<String> names, Map<String, View> sharedElements, View view) {
String transitionName = view.getTransitionName();
names.add(transitionName);
sharedElements.put(transitionName, view);
}
/**
* This method is overridden to avoid memory leaks
* #param context
* #param snapshot
* #return
*/
#Override
public View onCreateSnapshotView(Context context, Parcelable snapshot) {
// AppLogger.d("usm_shared_element_call_back", "onCreateSnapshotView: mSharedElements= " + mSharedElements.size());
View view = null;
if (snapshot instanceof Bundle) {
Bundle bundle = (Bundle) snapshot;
Bitmap bitmap = bundle.getParcelable(BUNDLE_SNAPSHOT_BITMAP);
if (bitmap == null) {
bundle.clear();
return null;
}
// Curiously, this is required to have the bitmap be GCed almost immediately after transition ends
// otherwise, garbage-collectable mem will still build up quickly
bitmap = bitmap.copy(Bitmap.Config.ARGB_8888, false);
if (bitmap == null) {
return null;
}
if (BUNDLE_SNAPSHOT_TYPE_IMAGE_VIEW.equals(((Bundle) snapshot).getString(BUNDLE_SNAPSHOT_TYPE))) {
ImageView imageView = new ImageView(context);
view = imageView;
imageView.setImageBitmap(bitmap);
imageView.setScaleType(
ImageView.ScaleType.valueOf(bundle.getString(BUNDLE_SNAPSHOT_IMAGE_SCALETYPE)));
if (imageView.getScaleType() == ImageView.ScaleType.MATRIX) {
float[] values = bundle.getFloatArray(BUNDLE_SNAPSHOT_IMAGE_MATRIX);
Matrix matrix = new Matrix();
matrix.setValues(values);
imageView.setImageMatrix(matrix);
}
} else {
view = new View(context);
Resources resources = context.getResources();
view.setBackground(new BitmapDrawable(resources, bitmap));
}
bundle.clear();
}
return view;
// return super.onCreateSnapshotView(context, snapshot);
}
/**
* This method is overridden to avoid memory leaks
* #param sharedElement
* #param viewToGlobalMatrix
* #param screenBounds
* #return
*/
#Override
public Parcelable onCaptureSharedElementSnapshot(View sharedElement, Matrix viewToGlobalMatrix, RectF screenBounds) {
//AppLogger.d("usm_shared_element_call_back", "onCaptureSharedElementSnapshot: mSharedElements= " + mSharedElements.size()
// + " ,sharedElement name= " + sharedElement.getTransitionName() + " ,id= " + sharedElement.getId());
if (sharedElement instanceof ImageView) {
ImageView imageView = ((ImageView) sharedElement);
Drawable d = imageView.getDrawable();
Drawable bg = imageView.getBackground();
if (d != null && (bg == null || bg.getAlpha() == 0)) {
Bitmap bitmap = TransitionUtils.createDrawableBitmap(d);
if (bitmap != null) {
Bundle bundle = new Bundle();
bundle.putParcelable(BUNDLE_SNAPSHOT_BITMAP, bitmap);
bundle.putString(BUNDLE_SNAPSHOT_IMAGE_SCALETYPE,
imageView.getScaleType().toString());
if (imageView.getScaleType() == ImageView.ScaleType.MATRIX) {
Matrix matrix = imageView.getImageMatrix();
float[] values = new float[9];
matrix.getValues(values);
bundle.putFloatArray(BUNDLE_SNAPSHOT_IMAGE_MATRIX, values);
}
bundle.putString(BUNDLE_SNAPSHOT_TYPE, BUNDLE_SNAPSHOT_TYPE_IMAGE_VIEW);
return bundle;
}
}
}
if (tempMatrixes.get(sharedElement.getId(), null) == null) {
tempMatrixes.put(sharedElement.getId(), new Matrix(viewToGlobalMatrix));
} else {
tempMatrixes.get(sharedElement.getId()).set(viewToGlobalMatrix);
}
Bundle bundle = new Bundle();
Bitmap bitmap = TransitionUtils.createViewBitmap(sharedElement, tempMatrixes.get(sharedElement.getId()), screenBounds);
bundle.putParcelable(BUNDLE_SNAPSHOT_BITMAP, bitmap);
return bundle;
// return super.onCaptureSharedElementSnapshot(sharedElement, viewToGlobalMatrix, screenBounds);
}
}
In your manifest file under application tag add the following line
<application
android:largeHeap="true"
>
That is not a very good approach but this will resolve your issue or you have to find a way to manage your memory allocation. But these days devices are coming with large memories. So this will not affect noticeable performance. You are good to go with this.
For further information regarding memory allocation do visit this link:
performance and memory
I am trying to use camera and save image. Followed the steps as commonsware suggested. Constantly I am getting error -
2018-11-12 02:10:54.588 3145-3173/com.bisw.weac E/DatabaseUtils: Writing exception to parcel
java.lang.SecurityException: Permission Denial: writing android.support.v4.content.FileProvider uri content://com.bisw.weac.provider/external_files/Android/data/com.bisw.weac/files/wallpaper/theme.jpg from pid=5566, uid=10071 requires the provider be exported, or grantUriPermission()
at android.content.ContentProvider.enforceWritePermissionInner(ContentProvider.java:713)
at android.content.ContentProvider$Transport.enforceWritePermission(ContentProvider.java:519)
at android.content.ContentProvider$Transport.enforceFilePermission(ContentProvider.java:491)
at android.content.ContentProvider$Transport.openAssetFile(ContentProvider.java:389)
at android.content.ContentProviderNative.onTransact(ContentProviderNative.java:251)
at android.os.Binder.execTransact(Binder.java:682)
I have tried almost everything like - intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); but nothing helps. I am croping the image from camera.
Activity code
public class LocalAlbumActivity extends BaseActivity implements View.OnClickListener {
private static final int REQUEST_IMAGE_CAPTURE_THEME = 1;
private static final int REQUEST_IMAGE_CAPTURE_QRCODE_LOGO = 4;
private static final int REQUEST_IMAGE_CROP_THEME = 2;
private static final int REQUEST_IMAGE_CROP_QRCODE_LOGO = 5;
private static final int REQUEST_ALBUM_DETAIL = 3;
public static final String ALBUM_PATH = "album_path";
public static final String ALBUM_NAME = "album_name";
private LocalAlbumAdapter mLocalAlbumAdapter;
private List<ImageBucket> mLocalAlbumList;
private AsyncTask<Void, Void, List<ImageBucket>> mBucketLoadTask;
private ListView mLocalAlbumListView;
/**
* 访问本地相册类型:0,主题;1,扫码;2,造码
*/
private int mRequestType;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
OttoAppConfig.getInstance().register(this);
setContentView(R.layout.activity_local_album);
ViewGroup backGround = (ViewGroup) findViewById(R.id.background);
MyUtil.setBackgroundBlur(backGround, this);
initAdapter();
assignViews();
}
private void initAdapter() {
mLocalAlbumList = new ArrayList<>();
mLocalAlbumAdapter = new LocalAlbumAdapter(this, mLocalAlbumList);
//trying permission
mBucketLoadTask = new AsyncTask<Void, Void, List<ImageBucket>>() {
#Override
protected void onPreExecute() {
super.onPreExecute();
// showLoading();
}
#Override
protected List<ImageBucket> doInBackground(Void... params) {
return LocalAlbumImagePickerHelper.getInstance(LocalAlbumActivity.this)
.getImagesBucketList();
}
#Override
protected void onPostExecute(List<ImageBucket> list) {
dismissLoadingDialog();
TextView emptyView = (TextView) findViewById(R.id.local_album_lv_empty);
mLocalAlbumListView.setEmptyView(emptyView);
mLocalAlbumList.addAll(list);
mLocalAlbumAdapter.notifyDataSetChanged();
}
};
mBucketLoadTask.execute();
}
private void dismissLoadingDialog() {
ViewGroup progressBarLlyt = (ViewGroup) findViewById(R.id.progress_bar_llyt);
progressBarLlyt.setVisibility(View.GONE);
}
private void assignViews() {
TextView loadingMsg = (TextView) findViewById(R.id.loading_msg);
loadingMsg.setText(R.string.scanning);
ImageView backBtn = (ImageView) findViewById(R.id.action_back);
TextView captureBtn = (TextView) findViewById(R.id.action_capture);
backBtn.setOnClickListener(this);
mRequestType = getIntent().getIntExtra(WeacConstants.REQUEST_LOCAL_ALBUM_TYPE, 0);
switch (mRequestType) {
// 主题
case 0:
// 造码
case 2:
captureBtn.setOnClickListener(this);
break;
// 扫码
case 1:
// 隐藏拍照按钮
captureBtn.setVisibility(View.GONE);
break;
}
mLocalAlbumListView = (ListView) findViewById(R.id.local_album_lv);
mLocalAlbumListView.setAdapter(mLocalAlbumAdapter);
mLocalAlbumListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (MyUtil.isFastDoubleClick()) {
return;
}
Intent intent = new Intent(LocalAlbumActivity.this, LocalAlbumDetailActivity.class);
intent.putParcelableArrayListExtra(ALBUM_PATH,
mLocalAlbumAdapter.getItem(position).bucketList);
intent.putExtra(ALBUM_NAME, mLocalAlbumAdapter.getItem(position).bucketName);
intent.putExtra(WeacConstants.REQUEST_LOCAL_ALBUM_TYPE, mRequestType);
startActivityForResult(intent, REQUEST_ALBUM_DETAIL);
}
});
// OverScrollDecoratorHelper.setUpOverScroll(mLocalAlbumListView);
}
private Uri mImageUri;
#Override
public void onClick(View v) {
switch (v.getId()) {
// 返回
case R.id.action_back:
myFinish();
break;
// 拍照
case R.id.action_capture:
PackageManager pm = getPackageManager();
// FEATURE_CAMERA - 后置相机
// FEATURE_CAMERA_FRONT - 前置相机
if (pm.hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY)) {
// 访问相机类型
int requestType;
// 截取主题壁纸
if (mRequestType != 2) {
requestType = REQUEST_IMAGE_CAPTURE_THEME;
} else { // 截取二维码logo
requestType = REQUEST_IMAGE_CAPTURE_QRCODE_LOGO;
}
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
//mImageUri = Uri.fromFile(MyUtil.getFileDirectory(this, "/Android/data/" +
// getPackageName() + "/capture/temporary.jpg"));
mImageUri = FileProvider.getUriForFile(this,BuildConfig.APPLICATION_ID+".provider",MyUtil.getFileDirectory(this, "/Android/data/" +
getPackageName() + "/capture/temporary.jpg"));
this.grantUriPermission(getPackageName(),mImageUri,Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.putExtra(MediaStore.EXTRA_OUTPUT, mImageUri);
startActivityForResult(intent, requestType);
overridePendingTransition(0, R.anim.zoomin);
} else { // 没有可用相机
Intent intent = new Intent(this, MyDialogActivitySingle.class);
intent.putExtra(WeacConstants.TITLE, getString(R.string.prompt));
intent.putExtra(WeacConstants.DETAIL, getString(R.string.camera_error));
startActivity(intent);
}
break;
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode != RESULT_OK) {
// 截图/相机返回
overridePendingTransition(0, R.anim.zoomout);
return;
}
// 扫描二维码相册详细取消
if (data != null) {
boolean isFinishMe = data.getBooleanExtra(LocalAlbumDetailActivity.FINISH_ACTIVITY, false);
if (isFinishMe && !isFinishing()) {
myFinish2();
return;
}
}
switch (requestCode) {
// 拍照(截取主题壁纸)
case REQUEST_IMAGE_CAPTURE_THEME:
cropImage(0, REQUEST_IMAGE_CROP_THEME, WeacConstants.DIY_WALLPAPER_PATH);
break;
// 拍照(截取二维码logo)
case REQUEST_IMAGE_CAPTURE_QRCODE_LOGO:
cropImage(1, REQUEST_IMAGE_CROP_QRCODE_LOGO, WeacConstants.DIY_QRCODE_LOGO_PATH);
break;
// 截图(截取主题壁纸)
case REQUEST_IMAGE_CROP_THEME:
String filePath = MyUtil.getFilePath(this, WeacConstants.DIY_WALLPAPER_PATH);
// 更新壁纸信息
MyUtil.saveWallpaper(this, WeacConstants.WALLPAPER_PATH, filePath);
// 发送壁纸更新事件
OttoAppConfig.getInstance().post(new WallpaperEvent());
myFinish();
break;
// 截图(截取二维码logo)
case REQUEST_IMAGE_CROP_QRCODE_LOGO:
String logoPath = MyUtil.getFilePath(this, WeacConstants.DIY_QRCODE_LOGO_PATH);
// 保存自定义二维码logo地址
MyUtil.saveQRcodeLogoPath(this, logoPath);
// 发送自定义二维码logo截取地址事件
OttoAppConfig.getInstance().post(new QRcodeLogoEvent(logoPath));
myFinish();
break;
// 相册详细图片
case REQUEST_ALBUM_DETAIL:
assert data != null;
String url = data.getStringExtra(WeacConstants.IMAGE_URL);
OttoAppConfig.getInstance().post(new ScanCodeEvent(url));
myFinish2();
break;
}
}
private void cropImage(int type, int requestType, String path) {
ToastUtil.showLongToast(this, "path:"+path);
Intent intent = MyUtil.getCropImageOptions(this, mImageUri, path, type);
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
if (intent.resolveActivity(getPackageManager()) != null) {
startActivityForResult(intent, requestType);
overridePendingTransition(0, 0);
} else {
// 不可以复制其他应用的内部文件
// TODO: 全屏裁剪&自定义裁剪功能
ToastUtil.showLongToast(this, getString(R.string.no_crop_action));
}
}
#Subscribe
public void finishMeEvent(FinishLocalAlbumActivityEvent event) {
myFinish2();
}
#Override
public void onBackPressed() {
myFinish();
}
private void myFinish() {
finish();
if (mRequestType != 2) {
overridePendingTransition(0, R.anim.zoomout);
} else {
overridePendingTransition(0, R.anim.move_out_bottom);
}
}
private void myFinish2() {
finish();
overridePendingTransition(0, 0);
}
#Override
protected void onDestroy() {
super.onDestroy();
OttoAppConfig.getInstance().unregister(this);
if (null != mBucketLoadTask && mBucketLoadTask.getStatus() == AsyncTask.Status.RUNNING) {
mBucketLoadTask.cancel(true);
}
}
}
Helper Methods
/**
* Returns specified directory(/mnt/sdcard/...).
* directory will be created on SD card by defined path if card
* is mounted. Else - Android defines files directory on device's
* files(/data/data/<application package>/files) system.
*
* #param context context
* #param path file path (e.g.: "/AppDir/a.mp3", "/AppDir/files/images/a.jp")
* #return File {#link File directory}
*/
public static File getFileDirectory(Context context, String path) {
File file = null;
if (isHasSDCard()) {
file = new File(Environment.getExternalStorageDirectory(), path);
if (!file.getParentFile().exists()) {
if (!file.getParentFile().mkdirs()) {
file = null;
}
}
}
if (file == null) {
// 使用内部缓存[MediaStore.EXTRA_OUTPUT ("output")]是无法正确写入裁切后的图片的。
// 系统是用全局的ContentResolver来做这个过程的文件io操作,app内部的存储被忽略。(猜测)
file = new File(context.getFilesDir(), path);
}
return file;
}
/**
* Returns specified directory(/mnt/sdcard/Android/data/<application package>/files/...).
* directory will be created on SD card by defined path if card
* is mounted. Else - Android defines files directory on device's
* files(/data/data/<application package>/files) system.
*
* #param context context
* #param path file path (e.g.: "/music/a.mp3", "/pictures/a.jpg")
* #return File {#link File directory}
*/
public static File getExternalFileDirectory(Context context, String path) {
File file = null;
if (isHasSDCard()) {
file = new File(context.getExternalFilesDir(null), path);
if (!file.getParentFile().exists()) {
if (!file.getParentFile().mkdirs()) {
file = null;
}
}
}
if (file == null) {
// 使用内部缓存[MediaStore.EXTRA_OUTPUT ("output")]是无法正确写入裁切后的图片的。
// 系统是用全局的ContentResolver来做这个过程的文件io操作,app内部的存储被忽略。(猜测)
file = new File(context.getFilesDir(), path);
}
return file;
}
public static boolean isHasSDCard() {
return Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState());
}
/**
* Returns directory absolutePath.
*
* #param context context
* #param path file path (e.g.: "/AppDir/a.mp3", "/AppDir/files/images/a.jpg")
* #return /mnt/sdcard/Android/data/<application package>/files/....
*/
public static String getFilePath(Context context, String path) {
return getExternalFileDirectory(context, path).getAbsolutePath();
}
/**
* set intent options
*
* #param context context
* #param uri image path uri
* #param filePath save path (e.g.: "/AppDir/a.mp3", "/AppDir/files/images/a.jpg")
* #param type 0,截取壁纸/拍照;1,截取Logo
* #return Intent
*/
public static Intent getCropImageOptions(Context context, Uri uri, String filePath, int type) {
int width;
int height;
// 截取壁纸/拍照
if (type == 0) {
width = context.getResources().getDisplayMetrics().widthPixels;
height = context.getResources().getDisplayMetrics().heightPixels;
} else { // 截取logo
width = height = dip2px(context, 30);
}
//filePath="/Internal storage/Download/a.jpg";
LogUtil.e(LOG_TAG, " filePath:" + filePath );
Intent intent = new Intent();
intent.setAction("com.android.camera.action.CROP");
intent.setDataAndType(uri, "image/*");
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.putExtra("crop", "true");
// 裁剪框比例
intent.putExtra("aspectX", width);
intent.putExtra("aspectY", height);
// 保存路径
//#ToDO: Uri.fromFile change to FileProvider.getUriForFile
Uri mImageUri;
//mImageUri=Uri.fromFile(getExternalFileDirectory(context, filePath));
intent.putExtra(MediaStore.EXTRA_OUTPUT, FileProvider.getUriForFile(context,BuildConfig.APPLICATION_ID+".provider",getExternalFileDirectory(context, filePath)));
// 是否去除面部检测
intent.putExtra("noFaceDetection", true);
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
// 是否保留比例
intent.putExtra("scale", true);
intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
// 裁剪区的宽高
intent.putExtra("outputX", width);
intent.putExtra("outputY", height);
// 是否将数据保留在Bitmap中返回
intent.putExtra("return-data", false);
return intent;
}
You need to add the following in provider declaration in your manifest file
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="<application-id>.fileprovider" // com.abc.def
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/provider_paths" />
</provider>
How can I save my current ImageView when I press onClick?
Im currently having the problem that the image that is next in line is being saved instead of the current actual image..
My Code for saving onLike
public class MainActivity extends Activity implements SwipeView.OnCardSwipedListener {
// Declaring variables
private final static int CARDS_MAX_ELEMENTS = 5;
private FrameLayout contentLayout;
private SwipeView mSwipeView;
private View addCardc41;
private Firebase mRef;
public ImageView imageLogo;
public ImageView imageview;
private static final String TAG = "MyActivity";
// Creating array of meals, getting them from the drawable folder
private int[] meals = {
R.drawable.a,
R.drawable.b,
R.drawable.c,
R.drawable.d,
R.drawable.e,
R.drawable.f,
R.drawable.g,
R.drawable.h,
R.drawable.i,
R.drawable.j
};
// Declaring a counter for the next method
private int count = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_swipe_view_demo);
contentLayout = (FrameLayout) findViewById(R.id.contentLayout);
imageLogo = (ImageView) findViewById(R.id.imageView3);
imageview = (ImageView) findViewById(R.id.imageView);
// Add the swipe view
mSwipeView = new SwipeView(this, R.id.imgSwipeLike, R.id.imgSwipeNope,
this);
contentLayout.addView(mSwipeView);
// Adding the cards initially with the maximum limits of cards.
for (int i = 0; i < CARDS_MAX_ELEMENTS; i++) {
addCard(i);
}
}
/**
* On clicked view.
*
* #param clickedView
* the clicked view
*/
public void onClickedView(View clickedView) {
switch (clickedView.getId()) {
case R.id.imgDisLike: {
mSwipeView.dislikeCard();
break;
}
case R.id.imgLike: {
mSwipeView.likeCard();
break;
}
}
}
#Override
public void onLikes() {
imageview.setDrawingCacheEnabled(true); //Add this line.
imageview.buildDrawingCache();
Bitmap bm=imageview.getDrawingCache();
OutputStream fOut = null;
Uri outputFileUri;
try {
File root = new File(Environment.getExternalStorageDirectory()
+ File.separator + "folder_name" + File.separator);
root.mkdirs();
File sdImageMainDirectory = new File(root, "myPicName.jpg");
outputFileUri = Uri.fromFile(sdImageMainDirectory);
fOut = new FileOutputStream(sdImageMainDirectory);
MediaScannerConnection.scanFile(this, new String[] { sdImageMainDirectory.getAbsolutePath() }, null, null);
} catch (Exception e) {
Toast.makeText(this, "Error occured. Please try again later.",
Toast.LENGTH_SHORT).show();
}
try {
bm.compress(Bitmap.CompressFormat.PNG, 100, fOut);
fOut.flush();
fOut.close();
} catch (Exception e){}
System.out.println("An Card removed");
// Add a card if you needed after any previous card swiped
addCard(0);
}
#Override
public void onDisLikes() {
System.out.println("An Card removed");
// Add a card if you needed after any previous card swiped
addCard(0);
}
#Override
public void onSingleTap() {
}
/**
* Adds the card to the swipe.
*/
private void addCard(int position) {
final View cardView = LayoutInflater.from(this).inflate(
R.layout.item_swipe_view, null);
final ImageView imgMeal = (ImageView) cardView
.findViewById(R.id.imgMeals);
imgMeal.setImageResource(meals[count]);
count++;
if (count == meals.length) {
count = 0;
}
// Add a card to the swipe view..
mSwipeView.addCard(cardView, position);
// Create OnClickListener for the CookBookActivity
// Declare Button for the Cookbook
Button btn = (Button) findViewById(R.id.button3);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startActivity(new Intent(MainActivity.this, CookbookActivity.class));
}
});
// Check Authentication
mRef = new Firebase(Constants.FIREBASE_URL);
if (mRef.getAuth() == null) {
loadLoginView();
}
}
private void loadLoginView() {
Intent intent = new Intent(this, LoginActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
}
}
The Library that i'm using for the swiping
//
// credits to IntelliJ IDEA
// (powered by Fernflower decompiler)
package com.rk.lib.view;
import android.content.Context;
import android.os.Handler;
import android.os.Build.VERSION;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.View.OnTouchListener;
import android.view.animation.AlphaAnimation;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.FrameLayout.LayoutParams;
public class SwipeView extends FrameLayout {
private View mFocusedView;
private View mFocusedViewLike;
private View mFocusedViewNope;
private int mFocusedViewWidth;
private float mPreviousAlpha = 0.0F;
private Integer mLikeResource = Integer.valueOf(0);
private Integer mNopeResource = Integer.valueOf(0);
private static final int MAX_ELEMENTS = 3;
private static final long DELAY_SCROLL_RUNNABLE = 1L;
private static final int SCROLL_LENGTH = 5;
private int mScrolledPixelsX;
private int mScrolledPixelsY;
private int mNeedToScrollX;
private int mNeedToScrollY;
private int mTotalScrolledX;
private int mTotalScrolledY;
private int mScrollLengthX = 5;
private int mScrollLengthY = 5;
private boolean enableTouchSwipe = true;
private Context mContext;
private SwipeView.ScrollMode mScrollModeX;
private SwipeView.ScrollMode mScrollModeY;
private SwipeView.ScrollDirection mScrollDirection;
private int[] paddingX;
private int[] paddingYTop;
private int[] paddingYBottom;
private SwipeView.OnCardSwipedListener mOnCardSwipedListener;
private Handler mScrollHandler;
private Runnable mScrollRunnable;
private final SimpleOnGestureListener simpleOnGestureListener;
public SwipeView(Context context, Integer likeResource, Integer nopeResource, SwipeView.OnCardSwipedListener cardSwipeListener) {
super(context);
this.mScrollModeX = SwipeView.ScrollMode.NONE;
this.mScrollModeY = SwipeView.ScrollMode.NONE;
this.mScrollDirection = SwipeView.ScrollDirection.NONE;
this.paddingX = new int[]{0, 10, 20};
this.paddingYTop = new int[]{0, 10, 20};
this.paddingYBottom = new int[]{20, 10, 0};
this.mScrollHandler = new Handler();
this.mScrollRunnable = new Runnable() {
public void run() {
boolean scrollX;
boolean scrollY;
int scrollX1;
int scrollY1;
if(SwipeView.this.mScrollDirection == SwipeView.ScrollDirection.OUT) {
if(SwipeView.this.mNeedToScrollX <= 0 && SwipeView.this.mNeedToScrollY <= 0) {
SwipeView.this.mScrollHandler.removeCallbacks(SwipeView.this.mScrollRunnable);
SwipeView.this.removeView(SwipeView.this.mFocusedView);
if(SwipeView.this.mScrollModeX == SwipeView.ScrollMode.LEFT) {
SwipeView.this.mOnCardSwipedListener.onLikes();
} else if(SwipeView.this.mScrollModeX == SwipeView.ScrollMode.RIGHT) {
SwipeView.this.mOnCardSwipedListener.onDisLikes();
}
SwipeView.this.alignCardsPadding();
} else {
if(SwipeView.this.mNeedToScrollX < SwipeView.this.mScrollLengthX) {
SwipeView.this.mScrollLengthX = SwipeView.this.mNeedToScrollX;
SwipeView.this.mNeedToScrollX = 0;
} else {
SwipeView.this.mNeedToScrollX = SwipeView.this.mNeedToScrollX - SwipeView.this.mScrollLengthX;
}
if(SwipeView.this.mNeedToScrollY < SwipeView.this.mScrollLengthY) {
SwipeView.this.mScrollLengthY = SwipeView.this.mNeedToScrollY;
SwipeView.this.mNeedToScrollY = 0;
} else {
SwipeView.this.mNeedToScrollY = SwipeView.this.mNeedToScrollY - SwipeView.this.mScrollLengthY;
}
scrollX = false;
scrollY = false;
if(SwipeView.this.mScrollModeX == SwipeView.ScrollMode.LEFT) {
scrollX1 = -SwipeView.this.mScrollLengthX;
} else {
scrollX1 = SwipeView.this.mScrollLengthX;
}
if(SwipeView.this.mScrollModeY == SwipeView.ScrollMode.TOP) {
scrollY1 = -SwipeView.this.mScrollLengthY;
} else {
scrollY1 = SwipeView.this.mScrollLengthY;
}
SwipeView.this.mFocusedView.scrollBy(scrollX1, scrollY1);
SwipeView.this.mScrollHandler.postDelayed(SwipeView.this.mScrollRunnable, 1L);
}
} else if(SwipeView.this.mScrollDirection == SwipeView.ScrollDirection.IN) {
if(SwipeView.this.mTotalScrolledX <= 0 && SwipeView.this.mTotalScrolledY <= 0) {
SwipeView.this.mScrollHandler.removeCallbacks(SwipeView.this.mScrollRunnable);
SwipeView.this.mScrollDirection = SwipeView.ScrollDirection.NONE;
} else {
if(SwipeView.this.mTotalScrolledX < SwipeView.this.mScrollLengthX) {
SwipeView.this.mScrollLengthX = SwipeView.this.mTotalScrolledX;
SwipeView.this.mTotalScrolledX = 0;
} else {
SwipeView.this.mTotalScrolledX = SwipeView.this.mTotalScrolledX - SwipeView.this.mScrollLengthX;
}
if(SwipeView.this.mTotalScrolledY < SwipeView.this.mScrollLengthY) {
SwipeView.this.mScrollLengthY = SwipeView.this.mTotalScrolledY;
SwipeView.this.mTotalScrolledY = 0;
} else {
SwipeView.this.mTotalScrolledY = SwipeView.this.mTotalScrolledY - SwipeView.this.mScrollLengthY;
}
scrollX = false;
scrollY = false;
if(SwipeView.this.mScrollModeX == SwipeView.ScrollMode.LEFT) {
scrollX1 = SwipeView.this.mScrollLengthX;
} else {
scrollX1 = -SwipeView.this.mScrollLengthX;
}
if(SwipeView.this.mScrollModeY == SwipeView.ScrollMode.TOP) {
scrollY1 = -SwipeView.this.mScrollLengthY;
} else {
scrollY1 = SwipeView.this.mScrollLengthY;
}
SwipeView.this.mFocusedView.scrollBy(scrollX1, scrollY1);
SwipeView.this.mScrollHandler.postDelayed(SwipeView.this.mScrollRunnable, 1L);
}
}
}
};
this.simpleOnGestureListener = new SimpleOnGestureListener() {
public boolean onSingleTapConfirmed(MotionEvent e) {
SwipeView.this.mOnCardSwipedListener.onSingleTap();
return super.onSingleTapConfirmed(e);
}
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
if(SwipeView.this.mFocusedView != null) {
SwipeView.this.mScrolledPixelsX = SwipeView.this.mScrolledPixelsX + (int)distanceX;
SwipeView.this.mScrolledPixelsY = SwipeView.this.mScrolledPixelsY + (int)distanceY;
SwipeView.this.mFocusedView.scrollBy((int)distanceX, (int)distanceY);
float alpha = (float)SwipeView.this.mScrolledPixelsX / (float)SwipeView.this.mFocusedViewWidth;
if(alpha > 0.0F) {
SwipeView.this.mFocusedViewNope.setVisibility(0);
SwipeView.this.mFocusedViewLike.setVisibility(8);
SwipeView.setAlpha(SwipeView.this.mFocusedViewNope, SwipeView.this.mPreviousAlpha, alpha);
SwipeView.this.mPreviousAlpha = alpha;
} else {
SwipeView.this.mFocusedViewNope.setVisibility(8);
SwipeView.this.mFocusedViewLike.setVisibility(0);
SwipeView.setAlpha(SwipeView.this.mFocusedViewLike, SwipeView.this.mPreviousAlpha, -alpha);
SwipeView.this.mPreviousAlpha = -alpha;
}
}
return true;
}
};
this.mContext = context;
this.mLikeResource = likeResource;
this.mNopeResource = nopeResource;
this.mOnCardSwipedListener = cardSwipeListener;
float density = this.getResources().getDisplayMetrics().density;
for(int gestureDetector = 0; gestureDetector < this.paddingX.length; ++gestureDetector) {
this.paddingX[gestureDetector] = (int)((float)this.paddingX[gestureDetector] * density);
this.paddingYTop[gestureDetector] = (int)((float)this.paddingYTop[gestureDetector] * density);
this.paddingYBottom[gestureDetector] = (int)((float)this.paddingYBottom[gestureDetector] * density);
}
final GestureDetector var7 = new GestureDetector(this.mContext, this.simpleOnGestureListener);
this.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
if(SwipeView.this.getChildCount() > 0) {
if(SwipeView.this.mScrollDirection != SwipeView.ScrollDirection.NONE) {
return false;
} else if(!SwipeView.this.enableTouchSwipe) {
return false;
} else {
var7.onTouchEvent(event);
switch(event.getAction()) {
case 0:
if(SwipeView.this.getChildCount() > 0) {
SwipeView.this.mFocusedView = SwipeView.this.getChildAt(SwipeView.this.getChildCount() - 1);
SwipeView.this.mFocusedViewLike = SwipeView.this.mFocusedView.findViewById(SwipeView.this.mLikeResource.intValue());
SwipeView.this.mFocusedViewNope = SwipeView.this.mFocusedView.findViewById(SwipeView.this.mNopeResource.intValue());
SwipeView.this.mFocusedViewWidth = SwipeView.this.mFocusedView.getWidth();
SwipeView.this.mFocusedView.setPadding(SwipeView.this.paddingX[0], 0, SwipeView.this.paddingX[0], 0);
}
SwipeView.this.resetScrollingValues();
break;
case 1:
SwipeView.this.alignCardsPadding();
if(SwipeView.this.mScrolledPixelsX < 0) {
SwipeView.this.mScrollModeX = SwipeView.ScrollMode.LEFT;
SwipeView.this.mTotalScrolledX = -SwipeView.this.mScrolledPixelsX;
} else {
SwipeView.this.mScrollModeX = SwipeView.ScrollMode.RIGHT;
SwipeView.this.mTotalScrolledX = SwipeView.this.mScrolledPixelsX;
}
if(SwipeView.this.mScrolledPixelsY < 0) {
SwipeView.this.mScrollModeY = SwipeView.ScrollMode.BOTTOM;
SwipeView.this.mTotalScrolledY = -SwipeView.this.mScrolledPixelsY;
} else {
SwipeView.this.mScrollModeY = SwipeView.ScrollMode.TOP;
SwipeView.this.mTotalScrolledY = SwipeView.this.mScrolledPixelsY;
}
SwipeView.this.detectSwipe();
}
return true;
}
} else {
return false;
}
}
});
}
public void addCard(View view, int position) {
if(this.getChildCount() <= 3 && position < 3) {
LinearLayout viewLayout = new LinearLayout(this.mContext);
viewLayout.setLayoutParams(new LayoutParams(-1, -1));
view.setLayoutParams(new LayoutParams(-1, -1));
viewLayout.addView(view);
viewLayout.setPadding(this.paddingX[position], this.paddingYTop[position], this.paddingX[position], this.paddingYBottom[position]);
this.addView(viewLayout, 0);
}
}
public void removeFocusedCard() {
this.removeView(this.mFocusedView);
this.alignCardsPadding();
}
private void alignCardsPadding() {
int i = 0;
for(int j = this.getChildCount() - 1; j >= 0; --j) {
this.getChildAt(j).setPadding(this.paddingX[i], this.paddingYTop[i], this.paddingX[i], this.paddingYBottom[i]);
++i;
}
this.mScrollDirection = SwipeView.ScrollDirection.NONE;
}
private void resetScrollingValues() {
this.mPreviousAlpha = 0.0F;
this.mNeedToScrollX = 0;
this.mScrolledPixelsX = 0;
this.mTotalScrolledX = 0;
this.mNeedToScrollY = 0;
this.mScrolledPixelsY = 0;
this.mTotalScrolledY = 0;
this.mScrollLengthX = 5;
this.mScrollLengthY = 5;
this.mScrollModeX = SwipeView.ScrollMode.NONE;
this.mScrollModeY = SwipeView.ScrollMode.NONE;
}
public void resetFocuedView() {
if(this.getChildCount() > 0) {
View mFocusedView = this.getChildAt(this.getChildCount() - 1);
View mFocusedViewLike = mFocusedView.findViewById(this.mLikeResource.intValue());
View mFocusedViewNope = mFocusedView.findViewById(this.mNopeResource.intValue());
setAlpha(mFocusedViewLike, 0.0F, 0.0F);
setAlpha(mFocusedViewNope, 0.0F, 0.0F);
mFocusedView.scrollTo(0, 0);
}
}
private void detectSwipe() {
int imageHalf = this.mFocusedView.getWidth() / 2;
this.mNeedToScrollX = this.mFocusedView.getWidth() - this.mTotalScrolledX;
if(this.mScrollDirection == SwipeView.ScrollDirection.NONE) {
if(this.mNeedToScrollX < imageHalf) {
this.mScrollDirection = SwipeView.ScrollDirection.OUT;
} else {
this.mScrollDirection = SwipeView.ScrollDirection.IN;
setAlpha(this.mFocusedViewLike, 0.0F, 0.0F);
setAlpha(this.mFocusedViewNope, 0.0F, 0.0F);
}
}
this.mScrollHandler.post(this.mScrollRunnable);
}
public void likeCard() {
if(this.getChildCount() > 0) {
this.mFocusedView = this.getChildAt(this.getChildCount() - 1);
this.mFocusedViewLike = this.mFocusedView.findViewById(this.mLikeResource.intValue());
this.mFocusedViewNope = this.mFocusedView.findViewById(this.mNopeResource.intValue());
if(this.mScrollDirection != SwipeView.ScrollDirection.NONE) {
return;
}
this.resetScrollingValues();
this.mScrollDirection = SwipeView.ScrollDirection.OUT;
this.mScrollModeX = SwipeView.ScrollMode.LEFT;
this.mFocusedViewLike.setVisibility(0);
setAlpha(this.mFocusedViewLike, 0.0F, 1.0F);
this.detectSwipe();
}
}
public void dislikeCard() {
if(this.getChildCount() > 0) {
this.mFocusedView = this.getChildAt(this.getChildCount() - 1);
this.mFocusedViewLike = this.mFocusedView.findViewById(this.mLikeResource.intValue());
this.mFocusedViewNope = this.mFocusedView.findViewById(this.mNopeResource.intValue());
if(this.mScrollDirection != SwipeView.ScrollDirection.NONE) {
return;
}
this.resetScrollingValues();
this.mScrollDirection = SwipeView.ScrollDirection.OUT;
this.mScrollModeX = SwipeView.ScrollMode.RIGHT;
this.mFocusedViewNope.setVisibility(0);
setAlpha(this.mFocusedViewNope, 0.0F, 1.0F);
this.detectSwipe();
}
}
public void setTouchable(boolean touchable) {
this.enableTouchSwipe = touchable;
}
public static void setAlpha(View view, float fromAlpha, float toAlpha) {
if(VERSION.SDK_INT < 11) {
AlphaAnimation alphaAnimation = new AlphaAnimation(fromAlpha, toAlpha);
alphaAnimation.setDuration(0L);
alphaAnimation.setFillAfter(true);
view.startAnimation(alphaAnimation);
} else {
view.setAlpha(toAlpha);
}
}
public interface OnCardSwipedListener {
void onLikes();
void onDisLikes();
void onSingleTap();
}
private static enum ScrollDirection {
IN,
OUT,
NONE;
private ScrollDirection() {
}
}
private static enum ScrollMode {
LEFT,
RIGHT,
TOP,
BOTTOM,
NONE;
private ScrollMode() {
}
}
}
ATTEMPT #3
This is the code that i've tried but I keep getting the same result (read comment below what I have done:
FrameLayout view = (FrameLayout)findViewById(R.id.contentLayout);
view.setDrawingCacheEnabled(true);
view.buildDrawingCache();
Bitmap bitmap = view.getDrawingCache();
I believe the image you are trying to save is getting removed during the onSwipe due to the library code. I think you need to move your code to before the onLike is called.
You're also attempting to get a bitmap from the cache of the entire layout, rather than the wanted ImageView here:
bm=contentLayout.getDrawingCache();
You'll want to get your current card view as a View, then, from my understanding of your code, the ID of your actual ImageView containing the expected bitmap is R.id.imgMeals, so I the suggest replacing the line:
bm=contentLayout.getDrawingCache();
with the following:
ImageView imageView = (ImageView) cardView.findViewById(R.id.imgMeals);
BitmapDrawable drawable = (BitmapDrawable) imageView.getDrawable();
Bitmap bm = drawable.getBitmap();
Move all of the below code from where you have it, to where I have marked //HERE!! in the following part of your code (or better, move it to a new method and call the method here).
// If the imageview of like is clicked
case R.id.imgLike: {
// HERE!!
// The imageview in the contentlayout will be swiped to the right
mSwipeView.likeCard();
break;
}
This is the code to me moved including the change I mention above:
View cardView = mSwipeView.getChildAt(mSwipeView.getChildCount() - 1);
ImageView imageView = (ImageView) cardView.findViewById(R.id.imgMeals);
BitmapDrawable drawable = (BitmapDrawable) imageView.getDrawable();
Bitmap bm = drawable.getBitmap();
OutputStream fOut = null;
try {
// Save on my sd card
File root = new File(Environment.getExternalStorageDirectory()
// Making a folder name Food Inspiration
+ File.separator + "Food Inspiration" + File.separator);
root.mkdirs();
File sdImageMainDirectory = null;
// Loop for having a different name for every image
int i = 0;
do {
sdImageMainDirectory = new File(root, "pic-" + i + ".png");
i++;
} while (sdImageMainDirectory.exists());
fOut = new FileOutputStream(sdImageMainDirectory);
// Updates the gallery of your phone with the folder and the "liked" images in it
MediaScannerConnection.scanFile(this, new String[] { sdImageMainDirectory.getAbsolutePath() }, null, null);
// If something goes wrong
} catch (Exception e) {
Toast.makeText(this, "Error occured. Please try again later.",
Toast.LENGTH_SHORT).show();
}
// Compresses the actual bitmap image
try {
bm.compress(Bitmap.CompressFormat.PNG, 100, fOut);
fOut.flush();
fOut.close();
} catch (Exception e){}
i have integrated zxing library in my app, i used to call zxing via intent :
Intent intent = new Intent("com.google.zxing.client.android.SCAN");
intent.putExtra("SCAN_MODE", "ONE_D_MODE");
intent.putExtra("SCAN_FORMATS", "CODE_39,CODE_93,CODE_128,DATA_MATRIX,ITF,CODABAR,EAN_13,EAN_8,UPC_A,QR_CODE");
startActivityForResult(intent, 1);
But com.google.zxing.client.android.SCAN allows user to choose scan app if he has another barcode scanners, and i want that if user starts scan from my app than will stats my zxing CaptureActivity.class , i call it via intent
Intent intent = new Intent(this, CaptuureActivity.class);
intent.putExtra("SCAN_MODE", "ONE_D_MODE");
intent.putExtra("SCAN_FORMATS", "CODE_39,CODE_93,CODE_128,DATA_MATRIX,ITF,CODABAR,EAN_13,EAN_8,UPC_A,QR_CODE");
startActivityForResult(intent, 1);
But when Capture Activity detect barcode nothing happend, it didnt comes back to previous activity .
Here is CaptureACtivity :
public final class CaptureActivity extends Activity implements SurfaceHolder.Callback {
private static final String TAG = CaptureActivity.class.getSimpleName();
private static final long DEFAULT_INTENT_RESULT_DURATION_MS = 1500L;
private static final long BULK_MODE_SCAN_DELAY_MS = 1000L;
private static final String[] ZXING_URLS = { "http://zxing.appspot.com/scan", "zxing://scan/" };
public static final int HISTORY_REQUEST_CODE = 0x0000bacc;
private static final Collection<ResultMetadataType> DISPLAYABLE_METADATA_TYPES =
EnumSet.of(ResultMetadataType.ISSUE_NUMBER,
ResultMetadataType.SUGGESTED_PRICE,
ResultMetadataType.ERROR_CORRECTION_LEVEL,
ResultMetadataType.POSSIBLE_COUNTRY);
private CameraManager cameraManager;
private CaptureActivityHandler handler;
private Result savedResultToShow;
private ViewfinderView viewfinderView;
private TextView statusView;
private View resultView;
private Result lastResult;
private boolean hasSurface;
private boolean copyToClipboard;
private IntentSource source;
private String sourceUrl;
private ScanFromWebPageManager scanFromWebPageManager;
private Collection<BarcodeFormat> decodeFormats;
private Map<DecodeHintType,?> decodeHints;
private String characterSet;
private HistoryManager historyManager;
private InactivityTimer inactivityTimer;
private BeepManager beepManager;
private AmbientLightManager ambientLightManager;
ViewfinderView getViewfinderView() {
return viewfinderView;
}
public Handler getHandler() {
return handler;
}
CameraManager getCameraManager() {
return cameraManager;
}
#Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
Window window = getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setContentView(R.layout.capture);
hasSurface = false;
historyManager = new HistoryManager(this);
historyManager.trimHistory();
inactivityTimer = new InactivityTimer(this);
beepManager = new BeepManager(this);
ambientLightManager = new AmbientLightManager(this);
PreferenceManager.setDefaultValues(this, R.xml.preferences, false);
}
#Override
protected void onResume() {
super.onResume();
// CameraManager must be initialized here, not in onCreate(). This is necessary because we don't
// want to open the camera driver and measure the screen size if we're going to show the help on
// first launch. That led to bugs where the scanning rectangle was the wrong size and partially
// off screen.
cameraManager = new CameraManager(getApplication());
viewfinderView = (ViewfinderView) findViewById(R.id.viewfinder_view);
viewfinderView.setCameraManager(cameraManager);
resultView = findViewById(R.id.result_view);
statusView = (TextView) findViewById(R.id.status_view);
handler = null;
lastResult = null;
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
// if (prefs.getBoolean(PreferencesActivity.KEY_DISABLE_AUTO_ORIENTATION, true)) {
// setRequestedOrientation(getCurrentOrientation());
// } else {
// setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
// }
resetStatusView();
SurfaceView surfaceView = (SurfaceView) findViewById(R.id.preview_view);
SurfaceHolder surfaceHolder = surfaceView.getHolder();
if (hasSurface) {
// The activity was paused but not stopped, so the surface still exists. Therefore
// surfaceCreated() won't be called, so init the camera here.
initCamera(surfaceHolder);
} else {
// Install the callback and wait for surfaceCreated() to init the camera.
surfaceHolder.addCallback(this);
}
beepManager.updatePrefs();
ambientLightManager.start(cameraManager);
inactivityTimer.onResume();
Intent intent = getIntent();
copyToClipboard = prefs.getBoolean(PreferencesActivity.KEY_COPY_TO_CLIPBOARD, true)
&& (intent == null || intent.getBooleanExtra(Intents.Scan.SAVE_HISTORY, true));
source = IntentSource.NONE;
decodeFormats = null;
characterSet = null;
if (intent != null) {
String action = intent.getAction();
String dataString = intent.getDataString();
if (Intents.Scan.ACTION.equals(action)) {
to the calling activity.
source = IntentSource.NATIVE_APP_INTENT;
decodeFormats = DecodeFormatManager.parseDecodeFormats(intent);
decodeHints = DecodeHintManager.parseDecodeHints(intent);
if (intent.hasExtra(Intents.Scan.WIDTH) && intent.hasExtra(Intents.Scan.HEIGHT)) {
int width = intent.getIntExtra(Intents.Scan.WIDTH, 0);
int height = intent.getIntExtra(Intents.Scan.HEIGHT, 0);
if (width > 0 && height > 0) {
cameraManager.setManualFramingRect(width, height);
}
}
String customPromptMessage = intent.getStringExtra(Intents.Scan.PROMPT_MESSAGE);
if (customPromptMessage != null) {
statusView.setText(customPromptMessage);
}
} else if (dataString != null &&
dataString.contains("http://www.google") &&
dataString.contains("/m/products/scan")) {
// Scan only products and send the result to mobile Product Search.
source = IntentSource.PRODUCT_SEARCH_LINK;
sourceUrl = dataString;
decodeFormats = DecodeFormatManager.PRODUCT_FORMATS;
} else if (isZXingURL(dataString)) {
// Scan formats requested in query string (all formats if none specified).
// If a return URL is specified, send the results there. Otherwise, handle it ourselves.
source = IntentSource.ZXING_LINK;
sourceUrl = dataString;
Uri inputUri = Uri.parse(dataString);
scanFromWebPageManager = new ScanFromWebPageManager(inputUri);
decodeFormats = DecodeFormatManager.parseDecodeFormats(inputUri);
// Allow a sub-set of the hints to be specified by the caller.
decodeHints = DecodeHintManager.parseDecodeHints(inputUri);
}
characterSet = intent.getStringExtra(Intents.Scan.CHARACTER_SET);
}
}
private int getCurrentOrientation() {
int rotation = getWindowManager().getDefaultDisplay().getRotation();
switch (rotation) {
case Surface.ROTATION_0:
case Surface.ROTATION_90:
return ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
default:
return ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
}
}
private static boolean isZXingURL(String dataString) {
if (dataString == null) {
return false;
}
for (String url : ZXING_URLS) {
if (dataString.startsWith(url)) {
return true;
}
}
return false;
}
#Override
protected void onPause() {
if (handler != null) {
handler.quitSynchronously();
handler = null;
}
inactivityTimer.onPause();
ambientLightManager.stop();
cameraManager.closeDriver();
if (!hasSurface) {
/* SurfaceView surfaceView = (SurfaceView) findViewById(R.id.preview_view);
SurfaceHolder surfaceHolder = surfaceView.getHolder();
surfaceHolder.removeCallback(this);*/
}
super.onPause();
}
#Override
protected void onDestroy() {
inactivityTimer.shutdown();
super.onDestroy();
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_BACK:
if (source == IntentSource.NATIVE_APP_INTENT) {
setResult(RESULT_CANCELED);
finish();
return true;
}
if ((source == IntentSource.NONE || source == IntentSource.ZXING_LINK) && lastResult != null) {
restartPreviewAfterDelay(0L);
return true;
}
break;
case KeyEvent.KEYCODE_FOCUS:
case KeyEvent.KEYCODE_CAMERA:
// Handle these events so they don't launch the Camera app
return true;
// Use volume up/down to turn on light
case KeyEvent.KEYCODE_VOLUME_DOWN:
cameraManager.setTorch(false);
return true;
case KeyEvent.KEYCODE_VOLUME_UP:
cameraManager.setTorch(true);
return true;
}
return super.onKeyDown(keyCode, event);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater menuInflater = getMenuInflater();
menuInflater.inflate(R.menu.capture, menu);
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
switch (item.getItemId()) {
case R.id.menu_share:
intent.setClassName(this, ShareActivity.class.getName());
startActivity(intent);
break;
case R.id.menu_history:
intent.setClassName(this, HistoryActivity.class.getName());
startActivityForResult(intent, HISTORY_REQUEST_CODE);
break;
case R.id.menu_settings:
intent.setClassName(this, PreferencesActivity.class.getName());
startActivity(intent);
break;
case R.id.menu_help:
intent.setClassName(this, HelpActivity.class.getName());
startActivity(intent);
break;
default:
return super.onOptionsItemSelected(item);
}
return true;
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
if (resultCode == RESULT_OK) {
if (requestCode == HISTORY_REQUEST_CODE) {
int itemNumber = intent.getIntExtra(Intents.History.ITEM_NUMBER, -1);
if (itemNumber >= 0) {
HistoryItem historyItem = historyManager.buildHistoryItem(itemNumber);
decodeOrStoreSavedBitmap(null, historyItem.getResult());
}
}
}
}
private void decodeOrStoreSavedBitmap(Bitmap bitmap, Result result) {
// Bitmap isn't used yet -- will be used soon
if (handler == null) {
savedResultToShow = result;
} else {
if (result != null) {
savedResultToShow = result;
}
if (savedResultToShow != null) {
Message message = Message.obtain(handler, R.id.decode_succeeded, savedResultToShow);
handler.sendMessage(message);
}
savedResultToShow = null;
}
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
if (holder == null) {
Log.e(TAG, "*** WARNING *** surfaceCreated() gave us a null surface!");
}
if (!hasSurface) {
hasSurface = true;
initCamera(holder);
}
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
hasSurface = false;
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
/**
* A valid barcode has been found, so give an indication of success and show the results.
*
* #param rawResult The contents of the barcode.
* #param scaleFactor amount by which thumbnail was scaled
* #param barcode A greyscale bitmap of the camera data which was decoded.
*/
public void handleDecode(Result rawResult, Bitmap barcode, float scaleFactor) {
inactivityTimer.onActivity();
lastResult = rawResult;
ResultHandler resultHandler = ResultHandlerFactory.makeResultHandler(this, rawResult);
boolean fromLiveScan = barcode != null;
if (fromLiveScan) {
historyManager.addHistoryItem(rawResult, resultHandler);
// Then not from history, so beep/vibrate and we have an image to draw on
beepManager.playBeepSoundAndVibrate();
//drawResultPoints(barcode, scaleFactor, rawResult);
}
switch (source) {
case NATIVE_APP_INTENT:
handleDecodeExternally(rawResult, resultHandler, barcode);
break;
case PRODUCT_SEARCH_LINK:
handleDecodeExternally(rawResult, resultHandler, barcode);
break;
case ZXING_LINK:
if (scanFromWebPageManager == null || !scanFromWebPageManager.isScanFromWebPage()) {
handleDecodeInternally(rawResult, resultHandler, barcode);
} else {
handleDecodeExternally(rawResult, resultHandler, barcode);
}
break;
case NONE:
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
if (fromLiveScan && prefs.getBoolean(PreferencesActivity.KEY_BULK_MODE, false)) {
Toast.makeText(getApplicationContext(),
getResources().getString(R.string.msg_bulk_mode_scanned) + " (" + rawResult.getText() + ')',
Toast.LENGTH_SHORT).show();
// Wait a moment or else it will scan the same barcode continuously about 3 times
// restartPreviewAfterDelay(BULK_MODE_SCAN_DELAY_MS);
} else {
handleDecodeInternally(rawResult, resultHandler, barcode);
}
break;
}
}
/**
* Superimpose a line for 1D or dots for 2D to highlight the key features of the barcode.
*
* #param barcode A bitmap of the captured image.
* #param scaleFactor amount by which thumbnail was scaled
* #param rawResult The decoded results which contains the points to draw.
*/
private void drawResultPoints(Bitmap barcode, float scaleFactor, Result rawResult) {
ResultPoint[] points = rawResult.getResultPoints();
if (points != null && points.length > 0) {
Canvas canvas = new Canvas(barcode);
Paint paint = new Paint();
paint.setColor(getResources().getColor(R.color.result_points));
if (points.length == 2) {
paint.setStrokeWidth(4.0f);
drawLine(canvas, paint, points[0], points[1], scaleFactor);
} else if (points.length == 4 &&
(rawResult.getBarcodeFormat() == BarcodeFormat.UPC_A ||
rawResult.getBarcodeFormat() == BarcodeFormat.EAN_13)) {
// Hacky special case -- draw two lines, for the barcode and metadata
drawLine(canvas, paint, points[0], points[1], scaleFactor);
drawLine(canvas, paint, points[2], points[3], scaleFactor);
} else {
paint.setStrokeWidth(10.0f);
for (ResultPoint point : points) {
if (point != null) {
canvas.drawPoint(scaleFactor * point.getX(), scaleFactor * point.getY(), paint);
}
}
}
}
}
private static void drawLine(Canvas canvas, Paint paint, ResultPoint a, ResultPoint b, float scaleFactor) {
if (a != null && b != null) {
canvas.drawLine(scaleFactor * a.getX(),
scaleFactor * a.getY(),
scaleFactor * b.getX(),
scaleFactor * b.getY(),
paint);
}
}
// Put up our own UI for how to handle the decoded contents.
private void handleDecodeInternally(Result rawResult, ResultHandler resultHandler, Bitmap barcode) {
CharSequence displayContents = resultHandler.getDisplayContents();
if (copyToClipboard && !resultHandler.areContentsSecure()) {
ClipboardInterface.setText(displayContents, this);
}
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
if (resultHandler.getDefaultButtonID() != null && prefs.getBoolean(PreferencesActivity.KEY_AUTO_OPEN_WEB, false)) {
resultHandler.handleButtonPress(resultHandler.getDefaultButtonID());
return;
}
statusView.setVisibility(View.VISIBLE);
viewfinderView.setVisibility(View.VISIBLE);
resultView.setVisibility(View.VISIBLE);
/*ImageView barcodeImageView = (ImageView) findViewById(R.id.barcode_image_view);
if (barcode == null) {
barcodeImageView.setImageBitmap(BitmapFactory.decodeResource(getResources(),
R.drawable.launcher_icon));
} else {
barcodeImageView.setImageBitmap(barcode);
})*/
TextView formatTextView = (TextView) findViewById(R.id.format_text_view);
formatTextView.setText(rawResult.getBarcodeFormat().toString());
TextView typeTextView = (TextView) findViewById(R.id.type_text_view);
typeTextView.setText(resultHandler.getType().toString());
DateFormat formatter = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT);
TextView timeTextView = (TextView) findViewById(R.id.time_text_view);
timeTextView.setText(formatter.format(new Date(rawResult.getTimestamp())));
TextView metaTextView = (TextView) findViewById(R.id.meta_text_view);
View metaTextViewLabel = findViewById(R.id.meta_text_view_label);
metaTextView.setVisibility(View.GONE);
metaTextViewLabel.setVisibility(View.GONE);
Map<ResultMetadataType,Object> metadata = rawResult.getResultMetadata();
if (metadata != null) {
StringBuilder metadataText = new StringBuilder(20);
for (Map.Entry<ResultMetadataType,Object> entry : metadata.entrySet()) {
if (DISPLAYABLE_METADATA_TYPES.contains(entry.getKey())) {
metadataText.append(entry.getValue()).append('\n');
}
}
if (metadataText.length() > 0) {
metadataText.setLength(metadataText.length() - 1);
metaTextView.setText(metadataText);
metaTextView.setVisibility(View.VISIBLE);
metaTextViewLabel.setVisibility(View.VISIBLE);
}
}
TextView contentsTextView = (TextView) findViewById(R.id.contents_text_view);
contentsTextView.setText(displayContents);
int scaledSize = Math.max(22, 32 - displayContents.length() / 4);
contentsTextView.setTextSize(TypedValue.COMPLEX_UNIT_SP, scaledSize);
TextView supplementTextView = (TextView) findViewById(R.id.contents_supplement_text_view);
supplementTextView.setText("");
supplementTextView.setOnClickListener(null);
if (PreferenceManager.getDefaultSharedPreferences(this).getBoolean(
PreferencesActivity.KEY_SUPPLEMENTAL, true)) {
SupplementalInfoRetriever.maybeInvokeRetrieval(supplementTextView,
resultHandler.getResult(),
historyManager,
this);
}
int buttonCount = resultHandler.getButtonCount();
ViewGroup buttonView = (ViewGroup) findViewById(R.id.result_button_view);
buttonView.requestFocus();
for (int x = 0; x < ResultHandler.MAX_BUTTON_COUNT; x++) {
TextView button = (TextView) buttonView.getChildAt(x);
if (x < buttonCount) {
button.setVisibility(View.VISIBLE);
button.setText(resultHandler.getButtonText(x));
button.setOnClickListener(new ResultButtonListener(resultHandler, x));
} else {
button.setVisibility(View.GONE);
}
}
}
// Briefly show the contents of the barcode, then handle the result outside Barcode Scanner.
private void handleDecodeExternally(Result rawResult, ResultHandler resultHandler, Bitmap barcode) {
if (barcode != null) {
viewfinderView.drawResultBitmap(barcode);
}
long resultDurationMS;
if (getIntent() == null) {
resultDurationMS = 0;
} else {
resultDurationMS = getIntent().getLongExtra(Intents.Scan.RESULT_DISPLAY_DURATION_MS,
0);
}
if (resultDurationMS > 0) {
String rawResultString = String.valueOf(rawResult);
if (rawResultString.length() > 32) {
rawResultString = rawResultString.substring(0, 32) + " ...";
}
statusView.setText(getString(resultHandler.getDisplayTitle()) + " : " + rawResultString);
}
if (copyToClipboard && !resultHandler.areContentsSecure()) {
CharSequence text = resultHandler.getDisplayContents();
ClipboardInterface.setText(text, this);
}
if (source == IntentSource.NATIVE_APP_INTENT) {
// Hand back whatever action they requested - this can be changed to Intents.Scan.ACTION when
// the deprecated intent is retired.
Intent intent = new Intent(getIntent().getAction());
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
intent.putExtra(Intents.Scan.RESULT, rawResult.toString());
intent.putExtra(Intents.Scan.RESULT_FORMAT, rawResult.getBarcodeFormat().toString());
setResult(Activity.RESULT_OK,intent);
byte[] rawBytes = rawResult.getRawBytes();
if (rawBytes != null && rawBytes.length > 0) {
intent.putExtra(Intents.Scan.RESULT_BYTES, rawBytes);
}
Map<ResultMetadataType,?> metadata = rawResult.getResultMetadata();
if (metadata != null) {
if (metadata.containsKey(ResultMetadataType.UPC_EAN_EXTENSION)) {
intent.putExtra(Intents.Scan.RESULT_UPC_EAN_EXTENSION,
metadata.get(ResultMetadataType.UPC_EAN_EXTENSION).toString());
}
Number orientation = (Number) metadata.get(ResultMetadataType.ORIENTATION);
if (orientation != null) {
intent.putExtra(Intents.Scan.RESULT_ORIENTATION, orientation.intValue());
}
String ecLevel = (String) metadata.get(ResultMetadataType.ERROR_CORRECTION_LEVEL);
if (ecLevel != null) {
intent.putExtra(Intents.Scan.RESULT_ERROR_CORRECTION_LEVEL, ecLevel);
}
#SuppressWarnings("unchecked")
Iterable<byte[]> byteSegments = (Iterable<byte[]>) metadata.get(ResultMetadataType.BYTE_SEGMENTS);
if (byteSegments != null) {
int i = 0;
for (byte[] byteSegment : byteSegments) {
intent.putExtra(Intents.Scan.RESULT_BYTE_SEGMENTS_PREFIX + i, byteSegment);
i++;
}
}
}
sendReplyMessage(R.id.return_scan_result, intent, 0);
} else if (source == IntentSource.PRODUCT_SEARCH_LINK) {
// Reformulate the URL which triggered us into a query, so that the request goes to the same
// TLD as the scan URL.
int end = sourceUrl.lastIndexOf("/scan");
String replyURL = sourceUrl.substring(0, end) + "?q=" + resultHandler.getDisplayContents() + "&source=zxing";
sendReplyMessage(R.id.launch_product_query, replyURL, 0);
} else if (source == IntentSource.ZXING_LINK) {
if (scanFromWebPageManager != null && scanFromWebPageManager.isScanFromWebPage()) {
String replyURL = scanFromWebPageManager.buildReplyURL(rawResult, resultHandler);
sendReplyMessage(R.id.launch_product_query, replyURL, 0);
}
}
}
private void sendReplyMessage(int id, Object arg, long delayMS) {
if (handler != null) {
Message message = Message.obtain(handler, id, arg);
if (delayMS > 0L) {
handler.sendMessageDelayed(message, delayMS);
} else {
handler.sendMessage(message);
}
}
}
private void initCamera(SurfaceHolder surfaceHolder) {
if (surfaceHolder == null) {
throw new IllegalStateException("No SurfaceHolder provided");
}
if (cameraManager.isOpen()) {
Log.w(TAG, "initCamera() while already open -- late SurfaceView callback?");
return;
}
try {
cameraManager.openDriver(surfaceHolder);
// Creating the handler starts the preview, which can also throw a RuntimeException.
if (handler == null) {
handler = new CaptureActivityHandler(this, decodeFormats, decodeHints, characterSet, cameraManager);
}
decodeOrStoreSavedBitmap(null, null);
} catch (IOException ioe) {
Log.w(TAG, ioe);
displayFrameworkBugMessageAndExit();
} catch (RuntimeException e) {
// Barcode Scanner has seen crashes in the wild of this variety:
// java.?lang.?RuntimeException: Fail to connect to camera service
Log.w(TAG, "Unexpected error initializing camera", e);
displayFrameworkBugMessageAndExit();
}
}
private void displayFrameworkBugMessageAndExit() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(getString(R.string.app_name));
builder.setMessage(getString(R.string.msg_camera_framework_bug));
builder.setPositiveButton(R.string.button_ok, new FinishListener(this));
builder.setOnCancelListener(new FinishListener(this));
builder.show();
}
public void restartPreviewAfterDelay(long delayMS) {
if (handler != null) {
handler.sendEmptyMessageDelayed(R.id.restart_preview, delayMS);
}
resetStatusView();
}
private void resetStatusView() {
resultView.setVisibility(View.GONE);
statusView.setText(R.string.msg_default_status);
statusView.setVisibility(View.VISIBLE);
viewfinderView.setVisibility(View.VISIBLE);
lastResult = null;
}
public void drawViewfinder() {
viewfinderView.drawViewfinder();
}
}
I set RESULT_OK in
if (source == IntentSource.NATIVE_APP_INTENT) {
Intent intent = new Intent(getIntent().getAction());
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
intent.putExtra(Intents.Scan.RESULT, rawResult.toString());
intent.putExtra(Intents.Scan.RESULT_FORMAT, rawResult.getBarcodeFormat().toString());
setResult(Activity.RESULT_OK,intent)
......
What im doing wrong?
And one more question , when i call scan with com.google.zxing.client.android.SCAN when barcode was captured actvity didnt close immediately, it wait about 500-1000 milliseconds , how to disable this ?
Thanks for answers
Just add the third line here while starting the intent, thats all, no need for any change in Zxing code, these guys Rock
Intent intent = new Intent(getApplicationContext(), CaptureActivity.class);
intent.putExtra("SCAN_FORMATS", "QR_CODE,EAN_13,EAN_8,RSS_14,UPC_A,UPC_E,CODE_39,CODE_93,CODE_128,ITF,CODABAR,DATA_MATRIX");
intent.setAction(Intents.Scan.ACTION);
startActivityForResult(intent, 0);
By the way I'm using Zxing version 3.2.0
Just like to add the code that I used to receive the output from Zxing:
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
if (resultCode == Activity.RESULT_OK) {
String contents = intent.getStringExtra(Intents.Scan.RESULT);
String formatName = intent.getStringExtra(Intents.Scan.RESULT_FORMAT);
tvStatus.setText(formatName);
tvScanResults.setText(contents + "\n\n" + formatName);
} else if (resultCode == Activity.RESULT_CANCELED) {
}
}
I have a webservice and I am using ksoap2 to connect to it and upload some pictures.
The process is:
Open the gallery
Select a few pictures
Share to my app
Start a foreground service
send the basic information to this service, like an array with all the picture's path
handle the intent and take the bundles
and start the foreground notification with the proper flag and with startForeground(id,noty)
The problem:
Everything goes right. Uploading and showing the items uploaded ...until...suddenly the notification just disappear from the bar.
After a while it shows by itself again and continues the upload, I tried to set some stuff to get the last item uploaded and start from there, I don't know if I am doing right and I would like to have an advice about this.
This is the Activity from where I call the Service:
Intent mServiceIntent = new Intent(this, UploadService.class);
Bundle bund = new Bundle();
bund.putStringArray("pathList", pictureList);
bund.putString("tags", tag);
boolean hasGeotag = UserManagerClass.UserLogged.isActiveLocation();
bund.putBoolean("hasGeotag", hasGeotag);
if (hasGeotag) {
GeoTag gtag = UserManagerClass.UserLocation;
bund.putDouble("latitude", gtag.getLatitude());
bund.putDouble("longitude", gtag.getLongitude());
bund.putString("city", gtag.getCity());
bund.putString("country", gtag.getCountry());
bund.putString("address", gtag.getAddress());
}
bund.putInt("idOwner", IDOWNER);
bund.putInt("idUser", UserManagerClass.UserLogged.getID());
bund.putInt("albumindex", albumIndex);
bund.putInt("privacyindex", privacyIndex);
bund.putString("comment", comment);
mServiceIntent.putExtras(bund);
startService(mServiceIntent);
and this is the code of the Service:
public class UploadService extends Service {
private static final int myID = 1433;
private static final String PREF_NAME = "SERVICEUPLOAD";
private static final String UPLOADED_PATH = "UPLOADED_";
private static int position;
private int albumIndex;
private String comment;
private boolean hasGeotag;
private int idOwner;
private int idUser;
private GeoTag location;
private String[] pathList;
private int privacyIndex;
private SoapPost sp;
private String tags;
private NotificationManager nManager;
private PendingIntent pi;
#Override
public void onCreate() {
Log.e("step 1", "entered to create");
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
nManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
}
private void exit() {
Log.e("step 10", "ending...");
deletePosition();
Log.e("step 12", "ended");
this.stopForeground(true);
updateNotification(true);
}
void createNotification() {
Log.e("step 4", "entered to create notification");
// In this sample, we'll use the same text for the ticker and the
// expanded notification
CharSequence text = getText(R.string.upload_waiting);
//
pi = PendingIntent.getActivity(this, 0, new Intent(), Notification.FLAG_FOREGROUND_SERVICE);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setSmallIcon(R.drawable.add_comment_icon);
builder.setTicker(text);
builder.setContentIntent(pi);
builder.setContentText(text);
builder.setContentTitle(text);
startForeground(myID, builder.build());
}
private void updateNotification(boolean completed) {
Log.e("step 8", "updating notification");
String ticker = String.format(getResources().getString(R.string.upload_uploading_tick), position);
String message = String.format(getResources().getString(R.string.upload_uploading_message_progress), position, pathList.length);
String title = String.format(getResources().getString(R.string.upload_uploading_title), position);
String title_completed = getResources().getString(R.string.upload_uploading_title_completed);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setSmallIcon(R.drawable.add_comment_icon);
builder.setContentText(message);
builder.setTicker(ticker);
if (!completed)
builder.setContentTitle(title);
else {
builder.setContentTitle(title_completed);
pi = PendingIntent.getActivity(this, 0, new Intent(), 0);
}
builder.setContentIntent(pi);
if (completed)
nManager.notify(myID, builder.build());
else
startForeground(myID, builder.build());
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e("step 2", "entered to onstart");
handleIntent(intent);
return START_STICKY;
}
void handleIntent(Intent data) {
Log.e("step 3", "entered to handle");
// GETS THE POSITIONS IF THE SERVICE WAS STOPPED BEFORE
// RETURN 0 IF IT WASNT
getPosition();
//
if (data == null)
this.stopForeground(true);
Bundle dt = data.getExtras();
tags = dt.getString("tags");
pathList = dt.getStringArray("pathList");
hasGeotag = dt.getBoolean("hasGeotag");
if (hasGeotag) {
location = new GeoTag();
location.setLatitude(dt.getDouble("latitude"));
location.setLongitude(dt.getDouble("longitude"));
location.setAddress(dt.getString("address"));
location.setCity(dt.getString("city"));
location.setCountry(dt.getString("country"));
}
idOwner = dt.getInt("idOwner");
idUser = dt.getInt("idUser");
albumIndex = dt.getInt("albumindex");
privacyIndex = dt.getInt("privacyindex");
comment = dt.getString("comment");
// isCover = dt.getBoolean("isCover");
sp = new SoapPost();
// CREATES THE NOTFICATION
createNotification();
// FINALLY SEND THE DATA TO THE WEB SERVICE
sendData();
}
private void sendData() {
Log.e("step 4", "entered to send data");
for (String fl : pathList) {
Log.e("step 5", "sending... " + fl);
if (fl != null && !fl.equals(UPLOADED_PATH)) {
try {
String[] dataup = new String[10];
if (hasGeotag) {
dataup = new String[15];
dataup[10] = String.valueOf(location.getLatitude());
dataup[11] = String.valueOf(location.getLongitude());
dataup[12] = location.getAddress();
dataup[13] = location.getCity();
dataup[14] = location.getCountry();
}
if (comment.length() > 0)
dataup[0] = URLEncoder.encode(comment, "UTF-8");
else
dataup[0] = "";
dataup[1] = String.valueOf(idOwner);
dataup[2] = String.valueOf(idUser);
dataup[3] = "2";
dataup[4] = "";
dataup[5] = String.valueOf(albumIndex);
dataup[6] = String.valueOf(privacyIndex);
dataup[7] = "";
dataup[8] = "";
dataup[9] = "";
File file = new File(fl);
// CONTINUE ONLY IF THE FILE EXISTS
if (file.exists()) {
Log.e("step 6", "file exists true");
// SETTING WIDTH AND HEIGHT
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(fl, options);
int wth = options.outWidth;
int hth = options.outHeight;
long lenght = file.length();
// END W AND H
String b64 = null;
b64 = Base64.encodeToString(PictureManagerClass.getBytesFromFile(file), Base64.DEFAULT);
file = null;
// SETTING
// 4 BASE64
// 7 W
// 8 H
// 9 L
dataup[4] = b64;
dataup[7] = String.valueOf(wth);
dataup[8] = String.valueOf(hth);
dataup[9] = String.valueOf(lenght);
Log.e("step 7", "uploading... " + fl);
// SET THE CURRENT ITEM AS UPLOADED
pathList[position] = null;
// SAVE THE ACTUAL POSITION
savePosition();
sp.uploadPicture(dataup, tags, SoapPost.UPLOAD_PICTURE);
position++;
updateNotification(false);
}// END FILE EXISTS
}
catch (Exception ex) {
// SAVE THE ACTUAL POSITION
savePosition();
//
StackTraceElement[] stack = ex.getStackTrace();
String Trace = " ";
for (StackTraceElement line : stack) {
Trace += line.toString();
}
Log.e("SERVICE: ", Trace);
}
}// END FL NULL
}// END FOR
exit();
}
#Override
public void onDestroy() {
// SAVE THE ACTUAL POSITION
savePosition();
super.onDestroy();
}
#Override
public void onLowMemory() {
// SAVE THE ACTUAL POSITION
savePosition();
super.onLowMemory();
}
void savePosition() {
Log.e("step 9", "saving position");
// SET THE VALUES FROM PATHS TO SET TO SAVE IT INTO PREFERENCES
SharedPreferences prefs = getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = prefs.edit();
editor.putInt("position", position);
Set<String> set = new HashSet<String>();
if (pathList != null) {
for (int i = 0; i < position; i++)
pathList[i] = null;
for (int i = position; i < pathList.length; i++)
if (pathList[i] != null)
set.add(pathList[i]);
}
if (pathList != null)
editor.putStringSet("pathList", set);
editor.commit();
}
void getPosition() {
SharedPreferences prefs = getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
position = prefs.getInt("position", 0);
Log.e("step 3.1", position + "");
Set<String> set = new HashSet<String>();
set = prefs.getStringSet("pathList", set);
int pos = 0;
for (String path : set) {
pathList = new String[set.size()];
pathList[pos] = path;
pos++;
}
}
void deletePosition() {
Log.e("step 11", "clear...");
SharedPreferences prefs = getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = prefs.edit();
editor.clear();
editor.commit();
}
/* (non-Javadoc)
* #see android.app.Service#onBind(android.content.Intent)
*/
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
FIXED
i fixed it...this is the new method sendData():
private void sendData() {
new Thread(new Runnable() {
#Override
public void run() {
for (String fl : pathList) {
if (fl != null && !fl.equals(UPLOADED_PATH)) {
try {
String[] dataup = new String[10];
if (hasGeotag) {
dataup = new String[15];
dataup[10] = String.valueOf(location.getLatitude());
dataup[11] = String.valueOf(location.getLongitude());
dataup[12] = location.getAddress();
dataup[13] = location.getCity();
dataup[14] = location.getCountry();
}
if (comment.length() > 0)
dataup[0] = URLEncoder.encode(comment, "UTF-8");
else
dataup[0] = "";
dataup[1] = String.valueOf(idOwner);
dataup[2] = String.valueOf(idUser);
dataup[3] = "2";
dataup[4] = "";
dataup[5] = String.valueOf(albumIndex);
dataup[6] = String.valueOf(privacyIndex);
dataup[7] = "";
dataup[8] = "";
dataup[9] = "";
File file = new File(fl);
// CONTINUE ONLY IF THE FILE EXISTS
if (file.exists()) {
// SETTING WIDTH AND HEIGHT
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(fl, options);
int wth = options.outWidth;
int hth = options.outHeight;
long lenght = file.length();
// END W AND H
byte[] pic = PictureManagerClass.getBytesFromFile(file);
Log.e("picLength", pic.length + "");
file = null;
// SETTING
// 4 BASE64
// 7 W
// 8 H
// 9 L
dataup[4] = "";
dataup[7] = String.valueOf(wth);
dataup[8] = String.valueOf(hth);
dataup[9] = String.valueOf(lenght);
Log.e("step 7", "uploading... " + fl);
// SET THE CURRENT ITEM AS UPLOADED
pathList[position] = null;
// SAVE THE ACTUAL POSITION
savePosition();
String mes = sp.uploadPicture(dataup, tags, SoapPost.UPLOAD_PICTURE, pic);
Log.e("picID", mes);
pic = null;
dataup = null;
position++;
updateNotification(false);
Thread.sleep(1 * 1000);
}// END FILE EXISTS
}
catch (Exception ex) {
// SAVE THE ACTUAL POSITION
savePosition();
//
StackTraceElement[] stack = ex.getStackTrace();
String Trace = " ";
for (StackTraceElement line : stack) {
Trace += line.toString();
}
Log.e("SERVICE: ", Trace);
}
}// END FL NULL
}// END FOR
exit();
}
}).start();;
}
and now the notification doesnt hide until all files were uploaded ... thanks.