The following code give java.lang.OutOfMemoryError : bitmap exceeds VM budget
i'm writing an app to swipe through a series of images , which are all full screen. I know i'm loading all images together thats whats causing the problem , but i dont know how to overcome this issue. Somebody please help .
package akash.gal;
import android.app.Activity;
import android.content.Context;
import android.content.res.TypedArray;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Gallery;
import android.widget.ImageView;
public class GalActivity extends Activity {
/** Called when the activity is first created. */
Integer imageids[]={R.drawable.one,R.drawable.two,R.drawable.three};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Gallery gallery=(Gallery) findViewById(R.id.gallery1);
gallery.setAdapter(new ImageAdapter(this));
}
public class ImageAdapter extends BaseAdapter{
private Context context;
private int itemBackground;
public ImageAdapter(Context c)
{
context=c;
TypedArray a=obtainStyledAttributes(R.styleable.Gallery1);
itemBackground=a.getResourceId(R.styleable.Gallery1_android_galleryItemBackground,0);
a.recycle();
}
public int getCount() {
// TODO Auto-generated method stub
return imageids.length;
}
public Object getItem(int arg0) {
// TODO Auto-generated method stub
return arg0;
}
public long getItemId(int arg0) {
// TODO Auto-generated method stub
return arg0;
}
public View getView(int arg0, View arg1, ViewGroup arg2) {
// TODO Auto-generated method stub
ImageView imageView=new ImageView(context);
imageView.setImageResource(imageids[arg0]);
imageView.setScaleType(ImageView.ScaleType.FIT_XY);
DisplayMetrics dm=new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
imageView.setLayoutParams(new Gallery.LayoutParams(dm.widthPixels,dm.heightPixels));
imageView.setBackgroundResource(itemBackground);
return imageView;
}
}
}
In Main Activity :--
public class Main extends Activity {
String mImagesPath;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mImagesPath = this.getFilesDir().getParent() + "/images/";
createImagesDir(mImagesPath);
copyImagesToStorage();
loadGridView();
}
/**
* Method handles the logic for setting the adapter for the gridview
*/
private void loadGridView(){
GridView lLazyGrid = (GridView) this.findViewById(R.id.gridview);
try {
LazyImageAdapter lLazyAdapter = new LazyImageAdapter(this.getApplicationContext(),
null,
mImagesPath);
lLazyGrid.setAdapter(lLazyAdapter);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Copy images from assets to storage
*/
private void copyImagesToStorage(){
AssetManager lAssetManager = getAssets();
String[] lFiles = null;
String lTag = "copyImageFail";
try {
// get all of the files in the assets directory
lFiles = lAssetManager.list("");
} catch (IOException e) {
Log.e(lTag, e.getMessage());
}
for(int i=0; i<lFiles.length; i++) {
// We have a file to copy
try {
// copy the file
copyFile(lFiles[i], mImagesPath + lFiles[i]);
} catch(Exception e) {
Log.e(lTag, e.getMessage());
}
}
}
/**
* Method copies the contents of one stream to another
* #param aIn stream to copy from
* #param aOut stream to copy to
* #throws IOException
*/
private void copyFile(String aIn, String aOut) throws IOException {
byte[] lBuffer = new byte[1024];
int lRead;
final int lOffset = 0;
// create an in and out stream
InputStream lIn = getAssets().open(aIn);
OutputStream lOut = new FileOutputStream(aOut);
// Copy contents while there is data
while((lRead = lIn.read(lBuffer)) != -1){
lOut.write(lBuffer, lOffset, lRead);
}
// clean up after our streams
lIn.close();
lIn = null;
lOut.flush();
lOut.close();
lOut = null;
}
/**
* Create the directory specified at aPath if it does not exist
* #param aPath directory to check for and create
*/
private void createImagesDir(String aPath){
File lDir = new File(aPath);
if(!lDir.exists()){
lDir.mkdir();
}
}
}
=====================================
In ImageLoader Class :
public class ImageLoader extends Thread {
public interface ImageLoadListener {
void handleImageLoaded(ViewSwitcher aViewSwitcher, ImageView aImageView, Bitmap aBitmap);
}
private static final String TAG = ImageLoader.class.getSimpleName();
ImageLoadListener mListener = null;
private Handler handler;
/**
* Image loader takes an object that extends ImageLoadListener
* #param lListener
*/
ImageLoader(ImageLoadListener lListener){
mListener = lListener;
}
#Override
public void run() {
try {
// preparing a looper on current thread
// the current thread is being detected implicitly
Looper.prepare();
// Looper gets attached to the current thread by default
handler = new Handler();
Looper.loop();
// Thread will start
} catch (Throwable t) {
Log.e(TAG, "ImageLoader halted due to a error: ", t);
}
}
/**
* Method stops the looper and thus the thread
*/
public synchronized void stopThread() {
// Use the handler to schedule a quit on the looper
handler.post(new Runnable() {
public void run() {
// This runs on the ImageLoader thread
Log.i(TAG, "DownloadThread loop quitting by request");
Looper.myLooper().quit();
}
});
}
/**
* Method queues the image at path to load
* Note that the actual loading takes place in the UI thread
* the ImageView and ViewSwitcher are just references for the
* UI thread.
* #param aPath - Path where the bitmap is located to load
* #param aImageView - The ImageView the UI thread will load
* #param aViewSwitcher - The ViewSwitcher that needs to display the imageview
*/
public synchronized void queueImageLoad(
final String aPath,
final ImageView aImageView,
final ViewSwitcher aViewSwitcher) {
// Wrap DownloadTask into another Runnable to track the statistics
handler.post(new Runnable() {
public void run() {
try {
synchronized (aImageView){
// make sure this thread is the only one performing activities on
// this imageview
BitmapFactory.Options lOptions = new BitmapFactory.Options();
lOptions.inSampleSize = 1;
Bitmap lBitmap = BitmapFactory.decodeFile(aPath, lOptions);
//aImage.setImageBitmap(lBitmap);
// Load the image here
signalUI(aViewSwitcher, aImageView, lBitmap);
}
}
catch(Exception e){
e.printStackTrace();
}
}
});
}
/**
* Method is called when the bitmap is loaded. The UI thread adds the bitmap to the imageview.
* #param aViewSwitcher - The ViewSwitcher that needs to display the imageview
* #param aImageView - The ImageView the UI thread will load
* #param aImage - The Bitmap that gets loaded into the ImageView
*/
private void signalUI(
ViewSwitcher aViewSwitcher,
ImageView aImageView,
Bitmap aImage){
if(mListener != null){
// we have an object that implements ImageLoadListener
mListener.handleImageLoaded(aViewSwitcher, aImageView, aImage);
}
}
}
======================================
IN LazyImageAdapter :
public class LazyImageAdapter extends BaseAdapter implements ImageLoadListener {
private static final int PROGRESSBARINDEX = 0;
private static final int IMAGEVIEWINDEX = 1;
private Context mContext = null;
private OnClickListener mItemClickListener;
private Handler mHandler;
private ImageLoader mImageLoader = null;
private File mDirectory;
/**
* Lazy loading image adapter
* #param aContext
* #param lClickListener click listener to attach to each item
* #param lPath the path where the images are located
* #throws Exception when path can't be read from or is not a valid directory
*/
public LazyImageAdapter(
Context aContext,
OnClickListener lClickListener,
String lPath
) throws Exception {
mContext = aContext;
mItemClickListener = lClickListener;
mDirectory = new File(lPath);
// Do some error checking
if(!mDirectory.canRead()){
throw new Exception("Can't read this path");
}
else if(!mDirectory.isDirectory()){
throw new Exception("Path is a not a directory");
}
mImageLoader = new ImageLoader(this);
mImageLoader.start();
mHandler = new Handler();
}
#Override
protected void finalize() throws Throwable {
// TODO Auto-generated method stub
super.finalize();
// stop the thread we started
mImageLoader.stopThread();
}
public int getCount() {
return mDirectory.listFiles().length;
}
public Object getItem(int aPosition) {
String lPath = null;
File []lFiles = mDirectory.listFiles();
if(aPosition < lFiles.length){
lPath = mDirectory.listFiles()[aPosition].getAbsolutePath();
}
return lPath;
}
public long getItemId(int arg0) {
// TODO Auto-generated method stub
return 0;
}
public View getView(final int aPosition, View aConvertView, ViewGroup parent) {
final ViewSwitcher lViewSwitcher;
String lPath = (String)getItem(aPosition);
// logic for conserving resources see google video on making your ui fast
// and responsive
if (null == aConvertView) {
lViewSwitcher = new ViewSwitcher(mContext);
lViewSwitcher.setPadding(8, 8, 8, 8);
ProgressBar lProgress = new ProgressBar(mContext);
lProgress.setLayoutParams(new ViewSwitcher.LayoutParams(80, 80));
lViewSwitcher.addView(lProgress);
ImageView lImage = new ImageView(mContext);
lImage.setLayoutParams(new ViewSwitcher.LayoutParams(100, 100));
lViewSwitcher.addView(lImage);
// attach the onclick listener
lViewSwitcher.setOnClickListener(mItemClickListener);
} else {
lViewSwitcher = (ViewSwitcher) aConvertView;
}
ViewTagInformation lTagHolder = (ViewTagInformation) lViewSwitcher
.getTag();
if (lTagHolder == null ||
!lTagHolder.aImagePath.equals(lPath)) {
// The Tagholder is null meaning this is a first time load
// or this view is being recycled with a different image
// Create a ViewTag to store information for later
ViewTagInformation lNewTag = new ViewTagInformation();
lNewTag.aImagePath = lPath;
lViewSwitcher.setTag(lNewTag);
// Grab the image view
// Have the progress bar display
// Then queue the image loading
ImageView lImageView = (ImageView) lViewSwitcher.getChildAt(1);
lViewSwitcher.setDisplayedChild(PROGRESSBARINDEX);
mImageLoader.queueImageLoad(lPath, lImageView, lViewSwitcher);
}
return lViewSwitcher;
}
public void handleImageLoaded(
final ViewSwitcher aViewSwitcher,
final ImageView aImageView,
final Bitmap aBitmap) {
// The enqueue the following in the UI thread
mHandler.post(new Runnable() {
public void run() {
// set the bitmap in the ImageView
aImageView.setImageBitmap(aBitmap);
// explicitly tell the view switcher to show the second view
aViewSwitcher.setDisplayedChild(IMAGEVIEWINDEX);
}
});
}
}
/**
* View holder pattern as described in google sample code
* we may want to add more attributes to this if the path was
* say being stored in a sqlite database
* #author bacaj
*/
class ViewTagInformation {
String aImagePath;
}
Related
I have a gridView in my app containing images. Images are loaded from json over the web. I want that when a user click on any image in the gridView a new activity will open container the image clicked by the user. The images are loaded from links defined in json. I tried but didn't get desired result.
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.GridView;
import com.dragedy.dream.adapter.MyArrayAdapter;
import com.dragedy.dream.model.MyDataModel;
import com.dragedy.dream.parser.JSONParser;
import com.dragedy.dream.utils.InternetConnection;
import com.dragedy.dream.utils.Keys;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
public class memechoose extends AppCompatActivity {
private GridView gridView;
private ArrayList<MyDataModel> list;
private MyArrayAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_memechoose);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
/**
* Array List for Binding Data from JSON to this List
*/
list = new ArrayList<>();
/**
* Binding that List to Adapter
*/
adapter = new MyArrayAdapter(this, list);
/**
* Getting List and Setting List Adapter
*/
gridView = (GridView) findViewById(R.id.gridView);
gridView.setAdapter(adapter);
gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent i= new Intent(memechoose.this, MemeEditorActivity.class);
i.putExtra("image_path", list.get(position).getImage());
startActivity(i);
}
});
/**
* Just to know onClick and Printing Hello Toast in Center.
*/
if (InternetConnection.checkConnection(getApplicationContext())) {
new GetDataTask().execute();
}
}
/**
* Creating Get Data Task for Getting Data From Web
*/
class GetDataTask extends AsyncTask<Void, Void, Void> {
ProgressDialog dialog;
#Override
protected void onPreExecute() {
super.onPreExecute();
/**
* Progress Dialog for User Interaction
*/
dialog = new ProgressDialog(memechoose.this);
dialog.setTitle("Hey Wait Please...");
dialog.setMessage("I am getting your JSON");
dialog.show();
}
#Nullable
#Override
protected Void doInBackground(Void... params) {
/**
* Getting JSON Object from Web Using okHttp
*/
JSONObject jsonObject = JSONParser.getDataFromWeb();
try {
/**
* Check Whether Its NULL???
*/
if (jsonObject != null) {
/**
* Check Length...
*/
if(jsonObject.length() > 0) {
/**
* Getting Array named "contacts" From MAIN Json Object
*/
JSONArray array = jsonObject.getJSONArray(Keys.KEY_MEME);
/**
* Check Length of Array...
*/
int lenArray = array.length();
if(lenArray > 0) {
for(int jIndex = 0; jIndex < lenArray; jIndex++) {
/**
* Creating Every time New Object
* and
* Adding into List
*/
MyDataModel model = new MyDataModel();
/**
* Getting Inner Object from contacts array...
* and
* From that We will get Name of that Contact
*
*/
JSONObject innerObject = array.getJSONObject(jIndex);
String image = innerObject.getString(Keys.KEY_MEME_PIC);
/**
* Getting Object from Object "phone"
*/
model.setImage(image);
/**
* Adding name and phone concatenation in List...
*/
list.add(model);
}
}
}
} else {
}
} catch (JSONException je) {
Log.i(JSONParser.TAG, "" + je.getLocalizedMessage());
}
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
dialog.dismiss();
/**
* Checking if List size if more than zero then
* Update ListView
*/
if(list.size() > 0) {
adapter.notifyDataSetChanged();
} //else {
// Snackbar.make(findViewById(R.id.parentLayout), "No Data Found", Snackbar.LENGTH_LONG).show();
// }
}
}
}
and the activity in which i want to display the images is as follows:
public class MemeEditorActivity extends AppCompatActivity {
private Toolbar toolbar;
private MemeEditorActivity selfRef;
private SharedPreferences setting;
private LinearLayout linlaHeaderProgress;
private float memeEditorLayoutWidth;
private float memeEditorLayoutHeight;
private LinearLayout tutorial;
private LinearLayout memeEditorLayout;
private MemeEditorView memeEditorView;
private ImageView forwardButtonImageView;
private Bitmap memeBitmap;
private File cacheImage_forPassing;
private File myDir;
private String dataDir;
private boolean firsttimes;
private boolean tutorialPreference;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_meme_editor);
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(false);
selfRef = this;
// Transparent bar on android 4.4 or above
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.KITKAT)
{
Window window = getWindow();
// Translucent status bar
window.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS,
WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
// Translucent navigation bar
window.setFlags(
WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION,
WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
}
// Initialize progress bar
linlaHeaderProgress = (LinearLayout)findViewById(R.id.linlaHeaderProgress);
linlaHeaderProgress.bringToFront();
// Initialize tutorial
setting = PreferenceManager
.getDefaultSharedPreferences(MemeEditorActivity.this);
SharedPreferences prefre = getSharedPreferences("Meme_Pref", Context.MODE_PRIVATE);
firsttimes = prefre.getBoolean("Meme_Pref", true);
tutorialPreference = setting.getBoolean("Tutor_Preference", false);
SharedPreferences.Editor firstTimeEditor = prefre.edit();
// See if tutorial is needed to be shown
tutorial = (LinearLayout)findViewById(R.id.meme_editor_tutorial);
tutorial.setEnabled(false);
tutorial.setOnClickListener(new View.OnClickListener()
{
# Override
public void onClick(View view)
{
tutorial.setVisibility(View.GONE);
tutorial.setEnabled(false);
}
});
if(firsttimes)
{
tutorial.setVisibility(View.VISIBLE);
tutorial.bringToFront();
tutorial.setEnabled(true);
firstTimeEditor.putBoolean("Meme_Pref", false);
firstTimeEditor.commit();
}
else if(tutorialPreference)
{
tutorial.setVisibility(View.VISIBLE);
tutorial.bringToFront();
tutorial.setEnabled(true);
tutorialPreference = setting.getBoolean("Tutor_Preference", false);
}
else
{
tutorial.setVisibility(View.GONE);
tutorial.setEnabled(false);
}
// Get the data directory for the app
PackageManager m = getPackageManager();
dataDir = getPackageName();
try
{
PackageInfo p = m.getPackageInfo(dataDir, 0);
dataDir = p.applicationInfo.dataDir;
myDir = new File(dataDir+"/cache");
if(!myDir.exists())
myDir.mkdirs();
if(myDir.setWritable(true))
Log.i("meme", "myDir is writable");
else
Log.i("meme", "myDir is not writable");
}catch(PackageManager.NameNotFoundException e)
{
Log.w("yourtag", "Error Package name not found ", e);
}
// Get the intent and get the image path to be the meme image
Intent shareIntent = getIntent();
String imagePath = shareIntent.getStringExtra("image_path");
// Create the SandboxView
setting = PreferenceManager
.getDefaultSharedPreferences(MemeEditorActivity.this);
// final int memeSize = Integer.valueOf(setting.getString("image_size","720"));
final int memeSize = setting.getInt("image_size", 720);
Log.i("meme", "memeSize = "+memeSize);
memeEditorLayout = (LinearLayout)findViewById(R.id.memeEditorLayout);
memeEditorLayout.setGravity(Gravity.CENTER);
try
{
Log.i("imagePath", imagePath);
Bitmap bitmap = BitmapFactory.decodeFile(imagePath);
memeEditorView = new MemeEditorView(this, bitmap);
memeEditorView.setLayoutParams(new ViewGroup.LayoutParams(memeSize, memeSize));
// Scale the sand box and add it into the layout
ViewTreeObserver viewTreeObserver = memeEditorLayout
.getViewTreeObserver();
// For getting the width and height of a dynamic layout during
// onCreate
viewTreeObserver
.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener()
{
#RequiresApi(api = Build.VERSION_CODES.HONEYCOMB)
# Override
public void onGlobalLayout()
{
memeEditorLayout.getViewTreeObserver()
.removeGlobalOnLayoutListener(this);
memeEditorLayoutWidth = memeEditorLayout.getHeight();
memeEditorLayoutHeight = memeEditorLayout.getWidth();
float scalingFactor = memeEditorLayoutWidth/(float)memeSize;
Log.i("memeEditorLayoutWidth", Float.toString(memeEditorLayoutWidth));
Log.i("ScaleFactor", Float.toString(scalingFactor));
memeEditorView.setScaleX(scalingFactor);
memeEditorView.setScaleY(scalingFactor);
}
});
memeEditorLayout.addView(memeEditorView);
// Set save button on click method
forwardButtonImageView = (ImageView)findViewById(R.id.forwardButtonImage);
forwardButtonImageView.setOnClickListener(new View.OnClickListener()
{
# Override
public void onClick(View arg0)
{
forwardButtonImageView.setEnabled(false);
Forward forward = new Forward();
forward.execute();
}
});
}catch(OutOfMemoryError e)
{
Toast.makeText(selfRef, "Your device is out of memory.", Toast.LENGTH_LONG).show();
finish();
}catch(Exception e)
{
Log.i("Meme Editor Activity", e.toString());
Toast.makeText(selfRef, "Ops, something went wrong.", Toast.LENGTH_LONG).show();
finish();
}
}
// Delete a files
private void deleteFile(File file)
{
if(file!=null)
{
Log.i("deleteFile", file.toString()+((file.exists())?" is Exist.":"is not exist!!!!"));
// Check if the file exist
if(file.exists())
// Clear the file inside if it is a directory
if(file.isDirectory())
{
String[] children = file.list();
for(int i = 0;i<children.length;i++)
{
File f = new File(file, children[i]);
if(f.delete())
Log.i("deleteFile", f.getAbsolutePath()+" is deleted....");
else
Log.i("deleteFile", f.getAbsolutePath()+" is not deleted!!!!");
}
}
}
}
# Override
protected void onPause()
{
// Hide the progress bar
linlaHeaderProgress.setVisibility(View.GONE);
forwardButtonImageView.setEnabled(true);
super.onPause();
}
# Override
protected void onResume()
{
super.onResume();
memeEditorView.setEnabled(true);
memeEditorView.resume();
}
# Override
protected void onDestroy()
{
// Try to delete cache if possible
// deleteFile(myDir);
// bp_release();
//memeEditorView.destroyDrawingCache();
super.onDestroy();
}
# Override
public boolean onCreateOptionsMenu(Menu menu)
{
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.meme_editor, menu);
return true;
}
# Override
public boolean onOptionsItemSelected(MenuItem item)
{
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
switch(item.getItemId())
{
case R.id.reset_sandbox:
memeEditorView.reset();
return true;
case R.id.action_settings:
Intent intent = new Intent(selfRef, MainActivity.class);
startActivity(intent);
return true;
case android.R.id.home:
// When the action bar icon on the top right is clicked, finish this
// activity
this.finish();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
// save image to a specific places
private void saveImage()
{
// Create the file path and file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String fname = timeStamp+".png";
cacheImage_forPassing = new File(myDir, fname);
// Remove duplicates
if(cacheImage_forPassing.exists())
cacheImage_forPassing.delete();
// Try save the bitmap
try
{
FileOutputStream out = new FileOutputStream(cacheImage_forPassing);
memeBitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
out.flush();
out.close();
Log.i("memeCacheLocation", cacheImage_forPassing.toString());
}catch(Exception e)
{
e.printStackTrace();
}
}
// Async task for onClick
class Forward extends AsyncTask<Object,Object,Object>
{
// Before forwarding
# Override
protected void onPreExecute()
{
super.onPreExecute();
linlaHeaderProgress.setVisibility(View.VISIBLE);
linlaHeaderProgress.bringToFront();
memeEditorView.pause();
memeEditorView.invalidate();
}
// Forwarding
# Override
protected String doInBackground(Object ... arg0)
{
Intent forward = new Intent(selfRef, MainActivity.class);
memeEditorView.setDrawingCacheEnabled(true);
memeEditorView.buildDrawingCache();
memeBitmap = Bitmap.createBitmap(memeEditorView.getDrawingCache());
saveImage();
forward.putExtra("cs4295.memcreator.memeImageCache",
cacheImage_forPassing.getPath());
startActivity(forward);
memeEditorView.setDrawingCacheEnabled(false);
return "DONE";
}
// After forwarding
# Override
protected void onPostExecute(Object result)
{
linlaHeaderProgress.setVisibility(View.GONE);
super.onPostExecute(result);
}
}
// Clear the Bitmap from memory
private void bp_release()
{
if(memeBitmap!=null&&!memeBitmap.isRecycled())
{
memeBitmap.recycle();
memeBitmap = null;
}
}
}
#AC-OpenSource E/BitmapFactory: Unable to decode stream:
java.io.FileNotFoundException:
/http:/static2.businessinsider.com/image/56e3189152bcd0320c8b5cf7-480/sammy-griner-success-kid-meme.jpg:
open failed: ENOENT (No such file or directory)
You have a slash before http
Hi I am new in android and in my app I have a lot of images in my ArrayList that 's
why I want to swipe those images automatically for every 3 seconds with help of Timetasker and this process is continuously need to repeating up to we close app. Can some body help me please
MainActivity:-
public class MainActivity extends AppCompatActivity {
ViewPager viewPager;
Integer[] imageId = {R.drawable.image1, R.drawable.image2, R.drawable.image3, R.drawable.image4};
String[] imagesName = {"image1","image2","image3","image4"};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_layout);
viewPager = (ViewPager) findViewById(R.id.viewPager);
PagerAdapter adapter = new CustomAdapter(MainActivity.this,imageId,imagesName);
viewPager.setAdapter(adapter);
}
}
CustomAdapter:-
public class CustomAdapter extends PagerAdapter{
private Activity activity;
private Integer[] imagesArray;
private String[] namesArray;
public CustomAdapter(Activity activity,Integer[] imagesArray,String[] namesArray){
this.activity = activity;
this.imagesArray = imagesArray;
this.namesArray = namesArray;
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
LayoutInflater inflater = ((Activity)activity).getLayoutInflater();
View viewItem = inflater.inflate(R.layout.image_item, container, false);
ImageView imageView = (ImageView) viewItem.findViewById(R.id.imageView);
imageView.setImageResource(imagesArray[position]);
TextView textView1 = (TextView) viewItem.findViewById(R.id.textview);
textView1.setText(namesArray[position]);
((ViewPager)container).addView(viewItem);
return viewItem;
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return imagesArray.length;
}
#Override
public boolean isViewFromObject(View view, Object object) {
// TODO Auto-generated method stub
return view == ((View)object);
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
// TODO Auto-generated method stub
((ViewPager) container).removeView((View) object);
}
}
Your question is already answered here
Add this in your MainActivity.java
//...
int currentPage = 0;
Timer timer;
final long DELAY_MS = 500;//delay in milliseconds before task is to be executed
final long PERIOD_MS = 3000; // time in milliseconds between successive task executions.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_layout);
viewPager = (ViewPager) findViewById(R.id.viewPager);
PagerAdapter adapter = new CustomAdapter(MainActivity.this,imageId,imagesName);
viewPager.setAdapter(adapter);
/*After setting the adapter use the timer */
final Handler handler = new Handler();
final Runnable Update = new Runnable() {
public void run() {
if (currentPage == NUM_PAGES-1) {
currentPage = 0;
}
viewPager.setCurrentItem(currentPage++, true);
}
};
timer = new Timer(); // This will create a new Thread
timer.schedule(new TimerTask() { // task to be scheduled
#Override
public void run() {
handler.post(Update);
}
}, DELAY_MS, PERIOD_MS);
}
Here is the code for the automatic scroll the viewpager item:
public class MainActivity extends AppCompatActivity {
AutoScrollViewPager viewPager;
Integer[] imageId = {R.drawable.commitementlogo, R.drawable.like, R.drawable.like_select, R.drawable.plus};
String[] imagesName = {"image1","image2","image3","image4"};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewPager= (AutoScrollViewPager) findViewById(R.id.viewpager);
viewPager.startAutoScroll();
viewPager.setInterval(3000);
viewPager.setCycle(true);
viewPager.setStopScrollWhenTouch(true);
PagerAdapter adapter = new CustomAdapter(MainActivity.this,imageId,imagesName);
viewPager.setAdapter(adapter);
}
}
Here AutoscrollViewpager class:
public class AutoScrollViewPager extends ViewPager {
public static final int DEFAULT_INTERVAL = 1500;
public static final int LEFT = 0;
public static final int RIGHT = 1;
/** do nothing when sliding at the last or first item **/
public static final int SLIDE_BORDER_MODE_NONE = 0;
/** cycle when sliding at the last or first item **/
public static final int SLIDE_BORDER_MODE_CYCLE = 1;
/** deliver event to parent when sliding at the last or first item **/
public static final int SLIDE_BORDER_MODE_TO_PARENT = 2;
/** auto scroll time in milliseconds, default is {#link #DEFAULT_INTERVAL} **/
private long interval = DEFAULT_INTERVAL;
/** auto scroll direction, default is {#link #RIGHT} **/
private int direction = RIGHT;
/** whether automatic cycle when auto scroll reaching the last or first item, default is true **/
private boolean isCycle = true;
/** whether stop auto scroll when touching, default is true **/
private boolean stopScrollWhenTouch = true;
/** how to process when sliding at the last or first item, default is {#link #SLIDE_BORDER_MODE_NONE} **/
private int slideBorderMode = SLIDE_BORDER_MODE_NONE;
/** whether animating when auto scroll at the last or first item **/
private boolean isBorderAnimation = true;
/** scroll factor for auto scroll animation, default is 1.0 **/
private double autoScrollFactor = 1.0;
/** scroll factor for swipe scroll animation, default is 1.0 **/
private double swipeScrollFactor = 1.0;
private Handler handler;
private boolean isAutoScroll = false;
private boolean isStopByTouch = false;
private float touchX = 0f, downX = 0f;
private CustomDurationScroller scroller = null;
public static final int SCROLL_WHAT = 0;
public AutoScrollViewPager(Context paramContext) {
super(paramContext);
init();
}
public AutoScrollViewPager(Context paramContext, AttributeSet paramAttributeSet) {
super(paramContext, paramAttributeSet);
init();
}
private void init() {
handler = new MyHandler(this);
setViewPagerScroller();
}
/**
* start auto scroll, first scroll delay time is {#link #getInterval()}
*/
public void startAutoScroll() {
isAutoScroll = true;
sendScrollMessage((long)(interval + scroller.getDuration() / autoScrollFactor * swipeScrollFactor));
}
/**
* start auto scroll
*
* #param delayTimeInMills first scroll delay time
*/
public void startAutoScroll(int delayTimeInMills) {
isAutoScroll = true;
sendScrollMessage(delayTimeInMills);
}
/**
* stop auto scroll
*/
public void stopAutoScroll() {
isAutoScroll = false;
handler.removeMessages(SCROLL_WHAT);
}
/**
* set the factor by which the duration of sliding animation will change while swiping
*/
public void setSwipeScrollDurationFactor(double scrollFactor) {
swipeScrollFactor = scrollFactor;
}
/**
* set the factor by which the duration of sliding animation will change while auto scrolling
*/
public void setAutoScrollDurationFactor(double scrollFactor) {
autoScrollFactor = scrollFactor;
}
private void sendScrollMessage(long delayTimeInMills) {
/** remove messages before, keeps one message is running at most **/
handler.removeMessages(SCROLL_WHAT);
handler.sendEmptyMessageDelayed(SCROLL_WHAT, delayTimeInMills);
}
/**
* set ViewPager scroller to change animation duration when sliding
*/
private void setViewPagerScroller() {
try {
Field scrollerField = ViewPager.class.getDeclaredField("mScroller");
scrollerField.setAccessible(true);
Field interpolatorField = ViewPager.class.getDeclaredField("sInterpolator");
interpolatorField.setAccessible(true);
scroller = new CustomDurationScroller(getContext(), (Interpolator)interpolatorField.get(null));
scrollerField.set(this, scroller);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* scroll only once
*/
public void scrollOnce() {
PagerAdapter adapter = getAdapter();
int currentItem = getCurrentItem();
int totalCount;
if (adapter == null || (totalCount = adapter.getCount()) <= 1) {
return;
}
int nextItem = (direction == LEFT) ? --currentItem : ++currentItem;
if (nextItem < 0) {
if (isCycle) {
setCurrentItem(totalCount - 1, isBorderAnimation);
}
} else if (nextItem == totalCount) {
if (isCycle) {
setCurrentItem(0, isBorderAnimation);
}
} else {
setCurrentItem(nextItem, true);
}
}
/**
* <ul>
* if stopScrollWhenTouch is true
* <li>if event is down, stop auto scroll.</li>
* <li>if event is up, start auto scroll again.</li>
* </ul>
*/
#Override
public boolean dispatchTouchEvent(MotionEvent ev) {
int action = ev.getActionMasked();
if (stopScrollWhenTouch) {
if ((action == MotionEvent.ACTION_DOWN) && isAutoScroll) {
isStopByTouch = true;
stopAutoScroll();
} else if (ev.getAction() == MotionEvent.ACTION_UP && isStopByTouch) {
startAutoScroll();
}
}
if (slideBorderMode == SLIDE_BORDER_MODE_TO_PARENT || slideBorderMode == SLIDE_BORDER_MODE_CYCLE) {
touchX = ev.getX();
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
downX = touchX;
}
int currentItem = getCurrentItem();
PagerAdapter adapter = getAdapter();
int pageCount = adapter == null ? 0 : adapter.getCount();
/**
* current index is first one and slide to right or current index is last one and slide to left.<br/>
* if slide border mode is to parent, then requestDisallowInterceptTouchEvent false.<br/>
* else scroll to last one when current item is first one, scroll to first one when current item is last
* one.
*/
if ((currentItem == 0 && downX <= touchX) || (currentItem == pageCount - 1 && downX >= touchX)) {
if (slideBorderMode == SLIDE_BORDER_MODE_TO_PARENT) {
getParent().requestDisallowInterceptTouchEvent(false);
} else {
if (pageCount > 1) {
setCurrentItem(pageCount - currentItem - 1, isBorderAnimation);
}
getParent().requestDisallowInterceptTouchEvent(true);
}
return super.dispatchTouchEvent(ev);
}
}
getParent().requestDisallowInterceptTouchEvent(true);
return super.dispatchTouchEvent(ev);
}
private static class MyHandler extends Handler {
private final WeakReference<AutoScrollViewPager> autoScrollViewPager;
public MyHandler(AutoScrollViewPager autoScrollViewPager) {
this.autoScrollViewPager = new WeakReference<AutoScrollViewPager>(autoScrollViewPager);
}
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case SCROLL_WHAT:
AutoScrollViewPager pager = this.autoScrollViewPager.get();
if (pager != null) {
pager.scroller.setScrollDurationFactor(pager.autoScrollFactor);
pager.scrollOnce();
pager.scroller.setScrollDurationFactor(pager.swipeScrollFactor);
pager.sendScrollMessage(pager.interval + pager.scroller.getDuration());
}
default:
break;
}
}
}
/**
* get auto scroll time in milliseconds, default is {#link #DEFAULT_INTERVAL}
*
* #return the interval
*/
public long getInterval() {
return interval;
}
/**
* set auto scroll time in milliseconds, default is {#link #DEFAULT_INTERVAL}
*
* #param interval the interval to set
*/
public void setInterval(long interval) {
this.interval = interval;
}
/**
* get auto scroll direction
*
* #return {#link #LEFT} or {#link #RIGHT}, default is {#link #RIGHT}
*/
public int getDirection() {
return (direction == LEFT) ? LEFT : RIGHT;
}
/**
* set auto scroll direction
*
* #param direction {#link #LEFT} or {#link #RIGHT}, default is {#link #RIGHT}
*/
public void setDirection(int direction) {
this.direction = direction;
}
/**
* whether automatic cycle when auto scroll reaching the last or first item, default is true
*
* #return the isCycle
*/
public boolean isCycle() {
return isCycle;
}
/**
* set whether automatic cycle when auto scroll reaching the last or first item, default is true
*
* #param isCycle the isCycle to set
*/
public void setCycle(boolean isCycle) {
this.isCycle = isCycle;
}
/**
* whether stop auto scroll when touching, default is true
*
* #return the stopScrollWhenTouch
*/
public boolean isStopScrollWhenTouch() {
return stopScrollWhenTouch;
}
/**
* set whether stop auto scroll when touching, default is true
*
* #param stopScrollWhenTouch
*/
public void setStopScrollWhenTouch(boolean stopScrollWhenTouch) {
this.stopScrollWhenTouch = stopScrollWhenTouch;
}
/**
* get how to process when sliding at the last or first item
*
* #return the slideBorderMode {#link #SLIDE_BORDER_MODE_NONE}, {#link #SLIDE_BORDER_MODE_TO_PARENT},
* {#link #SLIDE_BORDER_MODE_CYCLE}, default is {#link #SLIDE_BORDER_MODE_NONE}
*/
public int getSlideBorderMode() {
return slideBorderMode;
}
/**
* set how to process when sliding at the last or first item
*
* #param slideBorderMode {#link #SLIDE_BORDER_MODE_NONE}, {#link #SLIDE_BORDER_MODE_TO_PARENT},
* {#link #SLIDE_BORDER_MODE_CYCLE}, default is {#link #SLIDE_BORDER_MODE_NONE}
*/
public void setSlideBorderMode(int slideBorderMode) {
this.slideBorderMode = slideBorderMode;
}
/**
* whether animating when auto scroll at the last or first item, default is true
*
* #return
*/
public boolean isBorderAnimation() {
return isBorderAnimation;
}
/**
* set whether animating when auto scroll at the last or first item, default is true
*
* #param isBorderAnimation
*/
public void setBorderAnimation(boolean isBorderAnimation) {
this.isBorderAnimation = isBorderAnimation;
}
}
here CustomDurationScroller class:
public class CustomDurationScroller extends Scroller {
private double scrollFactor = 1;
public CustomDurationScroller(Context context) {
super(context);
}
public CustomDurationScroller(Context context, Interpolator interpolator) {
super(context, interpolator);
}
public void setScrollDurationFactor(double scrollFactor) {
this.scrollFactor = scrollFactor;
}
#Override
public void startScroll(int startX, int startY, int dx, int dy, int duration) {
super.startScroll(startX, startY, dx, dy, (int)(duration * scrollFactor));
}
}
and set the adapter same as you previously set.
Here is the total code using TimerTask:
public class MainActivity extends AppCompatActivity {
ViewPager viewPager;
Integer[] imageId = {R.drawable.image1, R.drawable.image2, R.drawable.image3, R.drawable.image4};
String[] imagesName = {"image1","image2","image3","image4"};
Timer timer;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_layout);
viewPager = (ViewPager) findViewById(R.id.viewPager);
PagerAdapter adapter = new CustomAdapter(MainActivity.this,imageId,imagesName);
viewPager.setAdapter(adapter);
TimerTask timerTask = new TimerTask() {
#Override
public void run() {
viewPager.post(new Runnable(){
#Override
public void run() {
viewPager.setCurrentItem((viewPager.getCurrentItem()+1)%imageId.length);
}
});
}
};
timer = new Timer();
timer.schedule(timerTask, 3000, 3000);
}
#Override
protected void onDestroy() {
timer.cancel();
super.onDestroy();
}
}
Create handler in activity, then schedule a task. I think Handler is enough for this small task. Don't go for timer.
Runnable timeCounter = new Runnable() {
#Override
public void run() {
if((currentIndex+1)>imageId.length() ){
currentIndex=0;
}else{
currentIndex++;
}
ViewPager.setCurrentItem(currentIndex);
handler.postDelayed(timeCounter, 3*1000);
}
};
handler.postDelayed(timeCounter, 3*1000);
then in onDestroy() or where ever you want to stop
handler.removeCallbacks(timeCounter);
Another version of the answer:-
private int currentPage = -1;
// start auto scroll of viewpager
final Handler handler = new Handler();
final Runnable Update = new Runnable() {
public void run() {
viewPager.setCurrentItem(++currentPage, true);
// go to initial page i.e. position 0
if (currentPage == NUM_PAGES -1) {
currentPage = -1;
// ++currentPage will make currentPage = 0
}
}
};
timer = new Timer(); // This will create a new Thread
timer.schedule(new TimerTask() { // task to be scheduled
#Override
public void run() {
handler.post(Update);
}
}, 500, 1500);
a simple edit to #L. Swifter's code snippet for the ones wondering about variables, I wrapped it all in a method which you can add to your activity after setting the adapter
private void automateViewPagerSwiping() {
final long DELAY_MS = 500;//delay in milliseconds before task is to be executed
final long PERIOD_MS = 3000; // time in milliseconds between successive task executions.
final Handler handler = new Handler();
final Runnable update = new Runnable() {
public void run() {
if (viewPager.getCurrentItem() == adapter.getCount() - 1) { //adapter is your custom ViewPager's adapter
viewPager.setCurrentItem(0);
}
else {
viewPager.setCurrentItem(viewPager.getCurrentItem() + 1, true);
}
}
};
timer = new Timer(); // This will create a new Thread
timer.schedule(new TimerTask() { // task to be scheduled
#Override
public void run() {
handler.post(update);
}
}, DELAY_MS, PERIOD_MS);
}
For a simple solution to show a series of images automatically try the ViewFlipper in your xml file. Not suitable for all purposes, but I found it to be a useful solution to something I was putting together.
<ViewFlipper
android:id="#+id/viewflipper"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:autoStart="true"
android:flipInterval="2000" >
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/picture1" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/picture2" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/picture3" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/picture4" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/picture5" />
Auto swipe ViewPager in Kotlin, simple and easy code.(if you have only 2 page)
val handler = Handler()
val update = Runnable {
viewPager.setCurrentItem(currentPage % 2, true);
currentPage++
}
var timer = Timer()// This will create a new Thread
timer!!.schedule(object : TimerTask() {
override fun run() {
handler.post(update)
}
}, 500(DELAY_MS), 3000(PERIOD_MS))
try this code:
In MainActivity -
int currentIndex=0; //for tracking current item
Create and set your TimerTask as per your requirement then in run() of TimerTask:
public void run() {
if((currentIndex+1)>imageId.length() ){
currentIndex=0;
}else{
currentIndex++;
}
ViewPager.setCurrentItem(currentIndex);
}
int ci=0;
java.util.Timer timer;
timer=new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
viewPager.post(new Runnable() {
#Override
public void run() {
Log.d("viewPager",""+ci);
viewPager.setCurrentItem(ci%7);
ci++;
}
});
}
},1000,5000);
it updates every 5seconds(5000)
You can use android TabLayout for indicators, ViewPager for slide screen and TimerTask to slide automatic
please check this link for step by step guideline and demo
CLICK HERE
Try this in your onCreate() method
final Handler handler = new Handler();
Timer timer = new Timer();
final Runnable runnable = new Runnable() {
public void run() {
int currentPage=viewPager.getCurrentItem();
//return to first page, if current page is last page
if (currentPage == titleNames.length-1) {
currentPage = -1;
}
viewPager.setCurrentItem(++currentPage, true);
}
};
timer.schedule(new TimerTask() {
#Override
public void run() {
handler.post(runnable);
}
},DELAY,PERRIOD)
using Kotlin coroutine
val totalPages = 3
CoroutineScope(Dispatchers.Main).launch {
while (isActive) {
delay(1500)
if (viewPager.currentItem + 1 > totalPages-1) {
viewPager.currentItem = 0
} else {
viewPager.currentItem++
}
}
}
Try to use ViewFlipper instead of viewpager
Layout xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<ViewFlipper
android:id="#+id/imageFrames"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#android:drawable/screen_background_dark" >
</ViewFlipper>
<Button
android:id="#+id/slideShowBtn"
android:layout_width="200dp"
android:layout_height="wrap_content"
Activity
public class SlideShowActivity extends Activity {
ViewFlipper imageFrame;
Button slideShowBtn;
Handler handler;
Runnable runnable;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.photo_slideshow_main);
imageFrame = (ViewFlipper) findViewById(R.id.imageFrames);
//get sd card path for images
File parentFolder = new
File(Environment.getExternalStorageDirectory()
.getAbsolutePath()
+ "/images");
addFlipperImages(imageFrame, parentFolder);
handler = new Handler();
imageFrame.setOnClickListener(SlideShowActivity.this);
slideShowBtn = (Button) findViewById(R.id.slideShowBtn);
slideShowBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
runnable = new Runnable() {
#Override
public void run() {
handler.postDelayed(runnable, 3000);
imageFrame.showNext();
}
};
handler.postDelayed(runnable, 500);
}
});
}
private void addFlipperImages(ViewFlipper flipper, File parent) {
int imageCount = parent.listFiles().length;
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.FILL_PARENT,
RelativeLayout.LayoutParams.FILL_PARENT);
for (int count = 0; count < imageCount - 1; count++) {
ImageView imageView = new ImageView(this);
Bitmap imbm = BitmapFactory.decodeFile(parent.listFiles()[count]
.getAbsolutePath());
imageView.setImageBitmap(imbm);
imageView.setLayoutParams(params);
flipper.addView(imageView);
}
}
}
#Override
public void onClick(View view) {
}
}
I am using QRCodeReaderView https://github.com/dlazaro66/QRCodeReaderView for implementing my own QR Code Scanner and it works well but the camera still starts slow (3-4 seconds) and I came up with the idea to pre start previewing the camera before using (keeping the camera open when the focus is on the fragment that has the button to start scanning so it could be opened right away when needed) and I tried everything but it seems like I don't understand the concept and it still starts slow.
Here is the code for the QRCodeReaderView:
import com.google.zxing.BinaryBitmap;
import com.google.zxing.ChecksumException;
import com.google.zxing.FormatException;
import com.google.zxing.NotFoundException;
import com.google.zxing.PlanarYUVLuminanceSource;
import com.google.zxing.Result;
import com.google.zxing.ResultPoint;
import com.google.zxing.client.android.camera.open.CameraManager;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.QRCodeReader;
import java.io.IOException;
public class QRCodeReaderView extends SurfaceView implements SurfaceHolder.Callback, Camera.PreviewCallback {
public interface OnQRCodeReadListener {
public void onQRCodeRead(String text, PointF[] points);
public void cameraNotFound();
public void QRCodeNotFoundOnCamImage();
}
private OnQRCodeReadListener mOnQRCodeReadListener;
private static final String TAG = QRCodeReaderView.class.getName();
private QRCodeReader mQRCodeReader;
private int mPreviewWidth;
private int mPreviewHeight;
private SurfaceHolder mHolder;
private CameraManager mCameraManager;
public QRCodeReaderView(Context context) {
super(context);
init();
}
public QRCodeReaderView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public void setOnQRCodeReadListener(OnQRCodeReadListener onQRCodeReadListener) {
mOnQRCodeReadListener = onQRCodeReadListener;
}
public CameraManager getCameraManager() {
return mCameraManager;
}
#SuppressWarnings("deprecation")
private void init() {
if (checkCameraHardware(getContext())) {
mCameraManager = new CameraManager(getContext());
mHolder = this.getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); // Need to set this flag despite it's deprecated
} else {
Log.e(TAG, "Error: Camera not found");
if (mOnQRCodeReadListener != null) {
mOnQRCodeReadListener.cameraNotFound();
}
}
}
/**
* *************************************************
* SurfaceHolder.Callback,Camera.PreviewCallback
* **************************************************
*/
#Override
public void surfaceCreated(SurfaceHolder holder) {
try {
// Indicate camera, our View dimensions
mCameraManager.openDriver(holder, this.getWidth(), this.getHeight());
} catch (IOException e) {
Log.w(TAG, "Can not openDriver: " + e.getMessage());
mCameraManager.closeDriver();
}
try {
mQRCodeReader = new QRCodeReader();
mCameraManager.startPreview();
} catch (Exception e) {
Log.e(TAG, "Exception: " + e.getMessage());
mCameraManager.closeDriver();
}
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
Log.d(TAG, "surfaceDestroyed");
mCameraManager.getCamera().setPreviewCallback(null);
mCameraManager.getCamera().stopPreview();
mCameraManager.getCamera().release();
mCameraManager.closeDriver();
}
// Called when camera take a frame
#Override
public void onPreviewFrame(byte[] data, Camera camera) {
PlanarYUVLuminanceSource source = mCameraManager.buildLuminanceSource(data, mPreviewWidth, mPreviewHeight);
HybridBinarizer hybBin = new HybridBinarizer(source);
BinaryBitmap bitmap = new BinaryBitmap(hybBin);
try {
Result result = mQRCodeReader.decode(bitmap);
// Notify we found a QRCode
if (mOnQRCodeReadListener != null) {
// Transform resultPoints to View coordinates
PointF[] transformedPoints = transformToViewCoordinates(result.getResultPoints());
mOnQRCodeReadListener.onQRCodeRead(result.getText(), transformedPoints);
}
} catch (ChecksumException e) {
Log.d(TAG, "ChecksumException");
e.printStackTrace();
} catch (NotFoundException e) {
// Notify QR not found
if (mOnQRCodeReadListener != null) {
mOnQRCodeReadListener.QRCodeNotFoundOnCamImage();
}
} catch (FormatException e) {
Log.d(TAG, "FormatException");
e.printStackTrace();
} finally {
mQRCodeReader.reset();
}
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
Log.d(TAG, "surfaceChanged");
if (mHolder.getSurface() == null) {
Log.e(TAG, "Error: preview surface does not exist");
return;
}
//preview_width = width;
//preview_height = height;
mPreviewWidth = mCameraManager.getPreviewSize().x;
mPreviewHeight = mCameraManager.getPreviewSize().y;
mCameraManager.stopPreview();
mCameraManager.getCamera().setPreviewCallback(this);
mCameraManager.getCamera().setDisplayOrientation(90); // Portrait mode
mCameraManager.startPreview();
}
/**
* Transform result to surfaceView coordinates
* <p/>
* This method is needed because coordinates are given in landscape camera coordinates.
* Now is working but transform operations aren't very explained
* <p/>
* TODO re-write this method explaining each single value
*
* #return a new PointF array with transformed points
*/
private PointF[] transformToViewCoordinates(ResultPoint[] resultPoints) {
PointF[] transformedPoints = new PointF[resultPoints.length];
int index = 0;
if (resultPoints != null) {
float previewX = mCameraManager.getPreviewSize().x;
float previewY = mCameraManager.getPreviewSize().y;
float scaleX = this.getWidth() / previewY;
float scaleY = this.getHeight() / previewX;
for (ResultPoint point : resultPoints) {
PointF tmppoint = new PointF((previewY - point.getY()) * scaleX, point.getX() * scaleY);
transformedPoints[index] = tmppoint;
index++;
}
}
return transformedPoints;
}
/**
* Check if this device has a camera
*/
private boolean checkCameraHardware(Context context) {
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
// this device has a camera
return true;
} else if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT)) {
// this device has a front camera
return true;
} else if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY)) {
// this device has any camera
return true;
} else {
// no camera on this device
return false;
}
}
}
and here is my fragment that uses it:
package com.breadwallet.presenter.fragments;
import com.breadwallet.R;
import com.breadwallet.presenter.activities.ScanResultActivity;
import com.breadwallet.tools.animation.SpringAnimator;
import com.breadwallet.tools.qrcode.QRCodeReaderView;
public class MainFragmentDecoder extends Fragment implements QRCodeReaderView.OnQRCodeReadListener {
public static final String TAG = "MainFragmentDecoder";
private boolean accessGranted = true;
private TextView myTextView;
private static QRCodeReaderView mydecoderview;
private ImageView camera_guide_image;
private Intent intent;
public static MainFragmentDecoder mainFragmentDecoder;
private RelativeLayout layout;
public MainFragmentDecoder() {
mainFragmentDecoder = this;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_decoder, container, false);
intent = new Intent(getActivity(), ScanResultActivity.class);
myTextView = (TextView) rootView.findViewById(R.id.exampleTextView);
camera_guide_image = (ImageView) rootView.findViewById(R.id.camera_guide_image);
SpringAnimator.showExpandCameraGuide(camera_guide_image);
// Inflate the layout for this fragment
return rootView;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
layout = (RelativeLayout) getView().findViewById(R.id.fragment_decoder_layout);
mydecoderview = new QRCodeReaderView(getActivity().getApplicationContext());
mydecoderview.setOnQRCodeReadListener(mainFragmentDecoder);
if (mydecoderview != null)
mydecoderview.getCameraManager().startPreview();
}
/**
* Called when a QR is decoded
* "text" : the text encoded in QR
* "points" : points where QR control points are placed
*/
#Override
public void onQRCodeRead(String text, PointF[] points) {
synchronized (this) {
if (accessGranted) {
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
accessGranted = true;
}
}, 300);
accessGranted = false;
// Log.e(TAG, "Activity STARTED!!!!!");
intent.putExtra("result", text);
startActivity(intent);
}
}
}
// Called when your device have no camera
#Override
public void cameraNotFound() {
Log.d(TAG, "No Camera found!");
}
// Called when there's no QR codes in the camera preview image
#Override
public void QRCodeNotFoundOnCamImage() {
// Log.d(TAG, "No QR Code found!");
}
#Override
public void onResume() {
super.onResume();
new CameraOpenerTask().execute();
}
#Override
public void onPause() {
super.onPause();
Log.e(TAG, "In onPause");
mydecoderview.getCameraManager().stopPreview();
layout.removeView(mydecoderview);
}
private class CameraOpenerTask extends AsyncTask {
#Override
protected Object doInBackground(Object[] params) {
return null;
}
#Override
protected void onPostExecute(Object o) {
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
layout.addView(mydecoderview, 0);
}
}, 1300);
Log.e(TAG, "The camera started");
}
}
public void stopCamera() {
if (mydecoderview != null) {
mydecoderview.getCameraManager().stopPreview();
}
mydecoderview = null;
}
}
I tried:
camera.StartPreview() earlier than using it.
pre-create the mydecoderview and then simply make it visible when
pressing the button but it still takes 3-4 seconds to start it.
You could try photo app in CyanogenMod (11 version) firmware, maybe this is just that you're searching for?
Download from somewhere it source and add its to your code.
I am making a slot machine app and using kankan's wheel for the same. I want to modify the library such that when the rotation stops the item it will point shoud be the one that I set . I have done this but there is a glitch that shows that we have changed the actual image to the one that we want . How to achieve this?
Update:
I have researched a lot on this and if I am right , android scroll is based on duration and distance not items . From kankan's wheel library I can get current item .Now , I am trying to stop the animation as well as scroll , as soon as a certain duration has been reached and the item is the one that I want (through index) . But this is not working .Please help!!
GameActivity
public class GameActivity extends Activity {
float mDeviceDensity;
String mUuid, mTitle, mContent, mReward;
ImageButton play;
SlotMachineAdapter slotAdapter;
private List<HashMap<String, Object>> slotImages = new ArrayList<HashMap<String, Object>>();
ArrayList<String> imagesWinId = new ArrayList<String>();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_filler_up_game);
DisplayMetrics display = getResources().getDisplayMetrics();
mDeviceDensity = display.density;
slotAdapter = new SlotMachineAdapter(this);
getPassedData();
setSoundPlayer(R.raw.clicks,true);
initWheel(R.id.slot_1, false, 0);
initWheel(R.id.slot_2, false, 1);
initWheel(R.id.slot_3, true, 2);
play = (ImageButton) findViewById(R.id.btn_mix);
play.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
shuffle(R.id.slot_1, 5000);
shuffle(R.id.slot_2, 7000);
shuffle(R.id.slot_3, 9000);
}
});
}
protected ImageLoader imageLoader;
ArrayList<SlotItem> arrListSlotItems;
private void getPassedData() {
try {
mUuid = getIntent().getStringExtra(getString(R.string.FILLER_UP_UUID));
imageLoader = ImageLoader.getInstance();
Uuid slotImagesExtra = (Uuid) (getIntent()
.getSerializableExtra(getString(R.string.FILLER_UP_IMAGES)));
arrListSlotItems = slotImagesExtra.getArrSlotItemArray();
for (int i = 0; i < arrListSlotItems.size(); i++)
downloadSlotImages(arrListSlotItems.get(i).getSlotId(), arrListSlotItems.get(i).getImageUrl());
} catch (Exception e) {
e.printStackTrace();
}
}
// Wheel scrolled flag
private boolean wheelScrolled = false;
// Wheel scrolled listener
OnWheelScrollListener scrolledListener = new OnWheelScrollListener() {
public void onScrollingStarted(WheelView wheel) {
wheelScrolled = true;
}
public void onScrollingFinished(WheelView wheel) {
wheelScrolled = false;
setStatus(wheel.getId(), getWheel(wheel.getId()).getWinningIndex());
}
};
// Wheel changed listener
private OnWheelChangedListener changedListener = new OnWheelChangedListener() {
public void onChanged(WheelView wheel, int oldValue, int newValue) {
if (!wheelScrolled) {
}
}
};
/**
* Updates status
*/
private void updateStatus() {
myThread();
}
public void myThread(){
Thread th=new Thread(){
#Override
public void run(){
try
{
Thread.sleep(2000);
GameActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
showAlertDialogWithSingleButton(GameActivity.this, mTitle, mContent, success);
}
});
}catch (InterruptedException e) {
// TODO: handle exception
}
}
};
th.start();
}
android.content.DialogInterface.OnClickListener success = new android.content.DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
if (mContent != null && mContent.contains("again"))
startHomeActivity();
else
startNewsActivity();
}
};
private void startHomeActivity() {
}
private void startNewsActivity() {
}
android.content.DialogInterface.OnClickListener fail = new android.content.DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
//
}
};
public void showAlertDialogWithSingleButton(final Activity ctx, final String title, final String message,
DialogInterface.OnClickListener onClickListener) {
// show dialog
}
private void initWheel(int id, boolean monitorScroll, int itemIndex) {
Random randomGenerator = new Random();
int index = randomGenerator.nextInt(arrListSlotItems.size());
WheelView wheel = getWheel(id);
wheel.setViewAdapter(slotAdapter);
wheel.setCurrentItem((index ));
wheel.setVisibleItems(1);
wheel.setWinningIndex(itemIndex);
wheel.addChangingListener(changedListener);
wheel.addScrollingListener(scrolledListener);
wheel.setCyclic(true);
wheel.setEnabled(false);
}
private WheelView getWheel(int id) {
return (WheelView) findViewById(id);
}
private void setStatus(int id, int item) {
int index = 0;
for (int i = 0; i < arrListSlotItems.size(); i++) {
SlotItem d = arrListSlotItems.get(i);
if (d.getSlotId() != 0 && d.getSlotId() == Integer.parseInt(imagesWinId.get(item)))
index = arrListSlotItems.indexOf(d);
}
getWheel(id).setCurrentItem(index, true);
if (id == R.id.slot_3) {
if(player.isPlaying())
{
stopBackgroundAudio();
}
updateStatus();
}
}
private void shuffle(int id, int duration) {
WheelView wheel = getWheel(id);
wheel.scroll(450 + (int) (Math.random() * 50), duration);
}
private class SlotMachineAdapter extends AbstractWheelAdapter {
final int IMAGE_WIDTH = getImageWidth(mDeviceDensity);
final int IMAGE_HEIGHT = getImageHeight(mDeviceDensity);
private Context context;
/**
* Constructor
*/
public SlotMachineAdapter(Context context) {
this.context = context;
}
/**
* Loads image from resources
*/
private Bitmap loadImage(Bitmap bitmap) {
Bitmap scaled = Bitmap.createScaledBitmap(bitmap, IMAGE_WIDTH, IMAGE_HEIGHT, true);
return scaled;
}
#Override
public int getItemsCount() {
return slotImages.size();
}
// Layout params for image view
final LayoutParams params = new LayoutParams(IMAGE_WIDTH, IMAGE_HEIGHT);
#Override
public View getItem(int index, View cachedView, ViewGroup parent) {
ImageView img;
if (cachedView != null) {
img = (ImageView) cachedView;
} else {
img = new ImageView(context);
}
img.setPadding(0, 5, 0, 5);
img.setLayoutParams(params);
#SuppressWarnings("unchecked")
SoftReference<Bitmap> bitmapRef = (SoftReference<Bitmap>) slotImages.get(index).get("image");
Bitmap bitmap = bitmapRef.get();
if (bitmap == null) {
bitmap = loadImage(bitmap);
}
img.setImageBitmap(bitmap);
return img;
}
}
private int getImageWidth(float density) {
}
private int getImageHeight(float density) {
}
private void downloadSlotImages(final int id, String slotObj) {
//downloading slot images from server
}
}
This is the code. Through this code, when slot stops I want it to scroll some more untill it reaches the image position that I receaved from server. I can do this .But this is providing a lil glitch . Is there any way to stop scrolling when the image is reached as soon as certain duration is reached.
P.S. If you need anymore detail I can provide you.
P.P.S. Screenshots wont give you any detailed insight about the issue.
After days of searching I finally did it.All I had to do was set interpolater as LinearInterpolater and While setting setCurrentItem set animation as true.
I have developed an app capable of detecting BLE signals and others parameters. I use a BaseAdapter to develop the ListView for showing each item. The problem is that I want to save those data in a xml file when the scan has finished (after a period of time I have established) but I don´t know how to do it.
In this class I do the scan of BLE and is where I want to initiate the process of saving the List when it has passed the time of scanning:
public class ScanBleActivity extends ScanBaseActivity {
private BluetoothAdapter mBluetoothAdapter;
private boolean mScanning;
private Handler mHandler = new Handler();
//private List<BluetoothDevice> mydata;
// Stops scanning after 10 seconds.
private static final long SCAN_PERIOD = 20000;
/* (non-Javadoc)
* #see com.zishao.bletest.ScanBaseActivity#initScanBluetooth()
*/
protected void initScanBluetooth() {
BluetoothManager manager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = manager.getAdapter();
startScanLen(true);
}
#Override
protected void onDestroy() {
super.onDestroy();
if (mScanning) {
startScanLen(false);
}
}
/**
*
* #param enable
*/
private void startScanLen(final boolean enable) {
if (enable) {
// Stops scanning after a pre-defined scan period.
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
mScanning = false;
mBluetoothAdapter.stopLeScan(mLeScanCallback);
try {
savedata(true);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}, SCAN_PERIOD);
mScanning = true;
mBluetoothAdapter.startLeScan(mLeScanCallback);
} else {
mScanning = false;
mBluetoothAdapter.stopLeScan(mLeScanCallback);
}
}
And here is my Adapter:
public class LeDeviceListAdapter extends BaseAdapter {
public List<BluetoothDevice> data;
private Activity context;
private final HashMap<BluetoothDevice, Integer> rssiMap = new HashMap<BluetoothDevice, Integer>();
public LeDeviceListAdapter(Activity context, List<BluetoothDevice> data) {
this.data = data;
this.context = context;
}
//public static List<BluetoothDevice> getAllData() {
// return data;
//}
public synchronized void addDevice(BluetoothDevice device, int rssi) {
if(!data.contains(device) ){
data.add(device);
}
rssiMap.put(device, rssi);
}
#Override
public int getCount() {
return data.size();
}
#Override
public Object getItem(int position) {
return data.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (null == convertView) {
LayoutInflater mInflater =
(LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = mInflater.inflate(R.layout.leaf_devices_list_item, null);
convertView.setTag(new DeviceView(convertView));
}
DeviceView view = (DeviceView) convertView.getTag();
view.init((BluetoothDevice) getItem(position));
return convertView;
}
public class DeviceView {
private TextView title;
private TextView status;
private TextView type;
private TextView address;
private TextView rssivalue;
public DeviceView(View view) {
title = (TextView) view.findViewById(R.id.device_name);
status = (TextView) view.findViewById(R.id.device_status_txt);
type = (TextView) view.findViewById(R.id.device_type_txt);
address = (TextView) view.findViewById(R.id.device_address_txt);
rssivalue = (TextView) view.findViewById(id.signal_intensity_txt);
}
public void init(BluetoothDevice device) {
title.setText(device.getName());
address.setText(device.getAddress());
setType(device.getType());
setStatus(device.getBondState());
rssivalue.setText(""+rssiMap.get(device)+" dBm");
}
public void setType(int status) {
switch(status) {
case BluetoothDevice.DEVICE_TYPE_CLASSIC:
type.setText("Bluetooth Signal");
break;
case BluetoothDevice.DEVICE_TYPE_LE:
type.setText("BLE Signal");
break;
case BluetoothDevice.DEVICE_TYPE_DUAL:
type.setText("Dual Mode - BR/EDR/LE");
break;
case BluetoothDevice.DEVICE_TYPE_UNKNOWN:
type.setText("Device Unknown");
break;
}
}
public void setStatus(int s) {
switch(s) {
case BluetoothDevice.BOND_NONE:
status.setText("Not Bonded");
break;
case BluetoothDevice.BOND_BONDED:
status.setText("Bonded");
break;
case BluetoothDevice.BOND_BONDING:
status.setText("Bonding");
break;
}
}
}
I want to save the title, address, type, status and rssivalue (shown in the code above) of each BLE signal that has been found during the scan to be saved in a xml file. I have provided only a part of the project but if it is necessarly I will edit and put the code that is missing.
Does anyone know how to do it?? Please help!!!!!
New code: This corresponds to the class ScanBaseActivity:
abstract public class ScanBaseActivity extends ListActivity {
protected LeDeviceListAdapter mLeDeviceListAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_devices_scan);
mLeDeviceListAdapter = new LeDeviceListAdapter(this, new ArrayList<BluetoothDevice>());
this.setListAdapter(mLeDeviceListAdapter);
initScanBluetooth();
}
/**
* Start Scan Bluetooth
*
*/
abstract protected void initScanBluetooth();
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
BluetoothDevice device = (BluetoothDevice) mLeDeviceListAdapter.getItem(position);
ParcelUuid[] uuids = device.getUuids();
String uuidString = "Getting UUID's from " + device.getName() + ";UUID:";
if (null != uuids && uuids.length > 0) {
uuidString += uuids[0].getUuid().toString();
} else {
uuidString += "empty";
}
Toast.makeText(this, uuidString, Toast.LENGTH_LONG).show();
}
/**
* #param device
*/
protected synchronized void addDevice(final BluetoothDevice device, final int rssi) {
runOnUiThread(new Runnable() {
#Override
public void run() {
mLeDeviceListAdapter.addDevice(device, rssi);
mLeDeviceListAdapter.notifyDataSetChanged();
}
});
}
protected void savedata(boolean enable) throws FileNotFoundException{
String filename = "file.txt";
FileOutputStream fos;
Bundle extras = getIntent().getExtras();
long timestamp = extras.getLong("currentTime");
try {
fos= openFileOutput(filename, Context.MODE_PRIVATE);
ObjectOutputStream out = new ObjectOutputStream(fos);
out.write((int) timestamp);
out.writeObject(mLeDeviceListAdapter);
out.write(null);
out.close();
Toast.makeText(this, R.string.list_saved, Toast.LENGTH_SHORT).show();
savedata(false);
} catch (FileNotFoundException e){
e.printStackTrace();
} catch (IOException e){
e.printStackTrace();
}
}
}
New!!: I have edited ScanBaseActivity and ScanBleActivity to introduce the xml saving but when I run the app, when the scan stops it causes an error (moment when the list has to be saved in the sml file). Does anyone know how to solve it or correct it??!!!
OK, first, you need to re-shape how you are dealing with your adapter, after that, everything should fall into place.
so for that, I'm going to outsource to vogella, the cardinal of good android design patterns
http://www.vogella.com/tutorials/AndroidListView/article.html
you could read up through section 3, eat some copypasta and come back here, but every extra line you grok is a good thing =]
Now you have an activity that has a list of data, and an adapter that takes that list and--somewhat dumbly in comparison to your code--applies it to a view of some sort. When you want to update that data, you do so by modifying the List object in the activity by your method somewhere that gets a list of Bluetoothdevices--and I'd take that process off thread with an AsyncTask.
Since you are passing a List to the adapter, you can wait until you've populated the data in your activity, then do an adapter.notifyDataSetChanged. You do not want to adapter.add
then you have a nice List of your data in the activity; you don't need to worry if it's the right list, because--given the update pattern--it's the only list!
then follow the link Merleverde posted to serialize that data into an xml, maybe in a utility class, but in your activity is fine.
edit:
here is a perfectly good adapter, this is part of the larger pattern that displays dynamically changing data:
public class AnchorListAdapter extends ArrayAdapter<String>
{
private final List<String> anchorNames;
public AnchorListAdapter(Context context, int textviewId, List<String> anchors){
super(context, textviewId, anchors);
anchorNames = anchors;
}
#Override
public String getItem( int i ) {
return anchorNames.get(i).toString();
}
}
Well, it's not that you are going to be saving it from the adapter, it's that the adater is going to be 'adapting' a data set that you will put into preferences.
as a feild:
private SharedPreferences saveHash;
in onCreate:
saveHash = getSharedPreferences( getString( R.string.save_hash ), MODE_PRIVATE );
then later:
public void onFinishedLoading(){
super.onPause();
SharedPreferences.Editor editor = saveHash.edit();
editor.clear();
for( String s: myData){
editor.putString(x, s);
}
editor.commit();
}
edit: realized you want to make a hash from a list; what do you want as the key?