Create slideshow without mouselistener - android

I am new in android and I want to create slideshow without any listener, I mean I would like open my app and see just animation with effect. I can't find examples or tutorials, anyone could help me? Thanks

If you want to do anything automatically without user interaction, than you have to use a backgroud thread. In Android you cannot call methods modifying the UI fron a background thread. As you plan on periodically updating the UI, you will be best off with AsynchTash.
private class SwitchImagesTask extends AsyncTask<Integer, Integer, Intehger> {
protected Long doInBackground(Integer... itemCount) {
for (int i = 0; i < itemCount[0]; i++) {
try{Thread.wait(1000);}catch(Exception e) {return -1;}
publishProgress(i);
}
return 1;
}
protected void onProgressUpdate(Integer... progress) {
// Display your image here
}
protected void onPostExecute(Integer result) {
// Say goodby to the user
}
}
If slide show means one image after another, than the easiest way to do this will be to add an ImageView to the layout, and change it's content.

if you call a activity, you can use layout inflator in inner class which extends thread.
public class SlideshowActivity extends Activity {
private static final int[] mSlides = new int[]{R.layout.layout_a , R.layout.layout_b , R.layout.layout_c};
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
new StartSlideShow().start();
}
class StartSlideShow extends Thread
{
#Override
public void run() {
LayoutInflater inflator = SlideshowActivity.this.getLayoutInflater();
for(int inx = 0 ; inx < mSlides.length ; inx++)
{
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
inflator.inflate(mSlides[inx], null);
}
}
}
}

Related

AsyncTask Update Progress without a loop

I have an asynctask and inside doInBackground, I don't have a for/while loop. Instead, I have a different class for it and that class generates a list using a for loop. So how can I update UI with onProgressUpdate?
Here is:
#Override
protected List<MyObject> doInBackground(Void... voids) {
IAppLogic appLogic = new AppLogic(mContext);
List<MyObject> list = appLogic.getApps(ALL_APPS);
return list;
}
MyObject is a custom object and IAppLogic is the interface of the class that gets installed applications.
You can implement this by giving the getApps()-method a callback-parameter. Pseudo code:
interface AppFoundCallback {
public onAppFound(App app, int progress);
}
// in AppLogic.getApps:
public getApps(String filter, AppFoundCallback callback)
for (int i = 0; i < listOfApps.length; i++) {
// Do the work you need to do here.
int progress = (i / listOfApps.length) * 100;
callback.onAppFound(app, progress);
}
}
// in your Task:
class Task extends AsyncTask implements AppFoundCallback {
// Implement the callback
#Override
onAppFound(App app, int progress) {
this.publishProgress(progress);
}
// Setup and register the listener
#Override
protected void doInBackground() {
// Ohter stuff
List<MyObject> list = appLogic.getApps(ALL_APPS, this);
}
// Render progress updates on the UI
#Override
protected void onProgressUpdate(Integer... progress) {
progressView.setProgress(progress[0]);
}
}
Simply put: your code notifies the caller of the getApps()-method every time you find something. This will then be published as a progress-update. The publishProgress()-method is part of AsyncTask and will take care of calling onProgressUpdate() on the UI-Thread, so that you can simply update your views.

wait for AsyncTask to finish

In the OnCreate method, I have invoked 3 AsyncTask which basically fills data for the 3 Spinners. What I need is that I should have the Login button disabled till all 3 tasks finish. How can I achieve that ?
new SpinnerDataFetcher("GetFreeDrivers1",(Spinner)findViewById(R.id.Spinner_1)).execute();
new SpinnerDataFetcher("GetFreeDrivers2",(Spinner)findViewById(R.id.Spinner_2)).execute();
new SpinnerDataFetcher("GetFreeDrivers3",(Spinner)findViewById(R.id.Spinner_3)).execute();
Just increment a number that corresponds on how many AsyncTask are done.
int s = 0;
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
new SpinnerDataFetcher(){
#Override
protected void onPostExecute(....) {
super.onPostExecute(...);
s++;
check();
}
}.execute();
new SpinnerDataFetcher(){
#Override
protected void onPostExecute(....) {
super.onPostExecute(...);
s++;
check();
}
}.execute();
new SpinnerDataFetcher(){
#Override
protected void onPostExecute(....) {
super.onPostExecute(...);
s++;
check();
}
}.execute();
}
public void check(){
if(s >=3){
s= 0;
// enable button here
}
}
Initialize your AsyncTask instance with a reference to the Activity/Fragment that creates it. Then signal back in onPostExecute when its done
e.g.
class Spinner1DataFetcher extends AsyncTask<...> {
public Spinner1DataFetch(YourActivityOrFragment activity) {
_activity = activity;
}
protected void onPostExecute(...) {
_activity.spinner_1_is_done();
}
}
For that you have to Disable Button before calling new Spinner1DateFetcher and call Second from Spinner1DateFetcher method onPostExecute and same as Third Spinner method and in Third Spinner onPostExecute set Button to Enable..
For Disable Button use
Button.setEnabled(false);
and For Enable Button use
Button.setEnabled(true);
Edit :
for the parameter check you have to add Constuctor and check the condition like below way.
private class MyAsyncTask extends AsyncTask<Void, Void, Void> {
public MyAsyncTask(boolean showLoading) {
super();
// do stuff
}
// doInBackground() et al.
}
There are multiple ways how you can achieve this.
The straightforward way to implement this is create a counter which will trigger UI update.
final InterfaceTrigger trigger = new InterfaceTrigger();
new AsyncTask<>() {
#Override
protected void onPostExecute(Object o) {
super.onPostExecute(o);
trigger.finishJob();
if (trigger.isTimeToUpdateUi()) {
// TODO update your UI
}
}
};
public class InterfaceTrigger {
private static final int THRESHOLD = 3;
private int counter;
public synchronized void finishJob() {
counter++;
}
public synchronized boolean isTimeToUpdateUi() {
return counter == THRESHOLD;
}
}
Another way is to use CyclicBarier and ExcutorService mechanism.

All threads get suspended

I am building an app which will continuously get screenshots of my laptop screen and transfer it to my android app but there is some problem within the while loop, when I put a for loop to a limit then my program runs but as it goes till infinity or I replace it with infinite while loop my code suspends all the threads and app crash dueto memory allocation problem, please suggest me to execute my code infinite times so that there are continuous screenshots displayed.
Thank You.
Here is my code
public class ScreenActivity extends AppCompatActivity {
ImageView img;
int width,height;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_screen);
img=(ImageView)findViewById(R.id.imageView);
Display display = getWindowManager().getDefaultDisplay();
width = display.getWidth();
height = display.getHeight();
// while (true)
for (int i=0;i<100;i++)
new GetImg().execute();
}
Bitmap imgscr;
public class GetImg extends AsyncTask<Object,Void,Bitmap> {
#Override
protected Bitmap doInBackground(Object[] params) {
Socket client= null;
try {
client = new Socket("192.168.1.5",6767);
InputStream in=client.getInputStream();
imgscr=Bitmap.createScaledBitmap(BitmapFactory.decodeStream(in), width, height, false);
} catch (Exception e) {
e.printStackTrace();
}
return imgscr;
}
#Override
protected void onPostExecute(Bitmap bm)
{
img.setImageBitmap(bm);
}
}
}
#m0skit0 commented the actual reason of getting the ANR. You're out of your run-time memory when you're creating threads in an infinite loop. I'm pretty confused about your purpose though. I think you need to get the screenshots one after one and if this is the case, you can simply add a listener to the AsyncTask and get the callback when the screenshot is downloaded fully.
So if I've understood correctly, you need to declare an interface like this.
public interface DownloadCompletedListener {
public void onDownloadComplete(String result);
}
Now you need to implement the interface in your Activity like this
public class ScreenActivity extends AppCompatActivity implements DownloadCompletedListener {
private GetImg getImageTask;
private Bitmap imageBitmap;
#Override
public void onDownloadComplete(String result) {
if(result.equals("SUCCESS")) {
// Set the image now
img.setImageBitmap(imageBitmap);
// Start next download here
getImageTask = new GetImg();
getImageTask.mListener = this;
getImageTask.execute();
} else {
// Do something
}
}
}
You need to modify your AsyncTask a bit. You need to declare the DownloadCompletedListener.
public class GetImg extends AsyncTask<Object,Void,Bitmap> {
private DownloadCompletedListener mListener;
#Override
protected Bitmap doInBackground(Object[] params) {
Socket client= null;
try {
client = new Socket("192.168.1.5",6767);
InputStream in=client.getInputStream();
imgscr=Bitmap.createScaledBitmap(BitmapFactory.decodeStream(in), width, height, false);
} catch (Exception e) {
e.printStackTrace();
}
return imgscr;
}
#Override
protected String onPostExecute(Bitmap bm)
{
imageBitmap = bm;
mListener.onDownloadComplete("SUCCESS");
}
}
So your onCreate function will look like this now
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_screen);
img=(ImageView)findViewById(R.id.imageView);
Display display = getWindowManager().getDefaultDisplay();
width = display.getWidth();
height = display.getHeight();
// Start downloading image here. Remove the loop
getImageTask = new GetImg();
getImageTask.mListener = this;
getImageTask.execute();
}

Android Access Activity from Async Class

I want to access activity and set text from async class.
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Button getBtn = (Button) findViewById(R.id.btn_result);
getBtn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
TextView txt_res = (TextView)findViewById(R.id.txt_Result);
new GetText(txt_res).execute(); // Async class
}
});
}
}
//Async Class
public class GetText AsyncTask<Void, Void, Void>{
private TextView txt_res;
public GetText (TextView txt_res) {
this.txt_res = txt_res;
}
#Override
protected Void doInBackground(Void... params) {
try {
String Result = GetTextFromDb();
} catch (Exception e) {
}
return null;
}
#Override
protected void onPostExecute(Void result)
{
try
{
Log.v("Success", "Success"); // I see "Success" at Logcat
txt_res.SetText("Success"); // Textview didn't change
}catch (Exception e) {
Log.v("Error", e.getMessage()); // No error at Logcat
}
}
}
I redefine my question. Textview don't change. Whats my mistake.
I redefine my question again. Textview didn't change at two functions(doInBackground, onPostExecute)
You basically have 2 options. You cannot directly access the main thread from asych obviously, so you must use the proper format.
If the text view needs to be updated after the task finishes, simply do the updating in onPostExecute
If the textview is displaying some intermediate progress, use onProgressUpdate
Edit:
Ok so here is your problem now. With asycn tasks, you must return a value from doInBackground. Change the type to String, and change onPostExecute(String result). Void means you are returning nothing. You will also have to change the second of the three parameters at the top of the async task to string as well.
Also, the method is textview.setText(""); not textview.SetText(""). The latter should not compile

AsyncTask : passing value to an Activity (onCreate method )

Update1
activity:
public Integer _number = 0;
#Override
public void onCreate(Bundle savedInstanceState) {
if (_number >0)
{
Log.d("onSuccessfulExecute", ""+_number);
}
else
{
Log.d("onSuccessfulExecute", "nope empty songs lists");
}
}
public int onSuccessfulExecute(int numberOfSongList) {
_number = numberOfSongList;
if (numberOfSongList >0)
{
Log.d("onSuccessfulExecute", ""+numberOfSongList);
}
else
{
Log.d("onSuccessfulExecute", "nope empty songs lists");
}
return numberOfSongList;
}
end Update1
UPDATE: AsynchTask has its own external class.
How to pass an value from AsyncTask onPostExecute()... to activity
my code does returning value from onPostExecute() and updating on UI but i am looking for a way to set the activity variable (NumberOfSongList) coming from AsynchTask.
AsyncTask class:
#Override
public void onPostExecute(asynctask.Payload payload)
{
AsyncTemplateActivity app = (AsyncTemplateActivity) payload.data[0];
//the below code DOES UPDATE the UI textView control
int answer = ((Integer) payload.result).intValue();
app.taskStatus.setText("Success: answer = "+answer);
//PROBLEM:
//i am trying to populate the value to an variable but does not seems like the way i am doing:
app.NumberOfSongList = payload.answer;
..............
..............
}
Activity:
public Integer NumberOfSongList;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//Several UI Code
new ConnectingTask().execute();
Log.d("onCreate", ""+NumberOfSongList);
}
What about using a setter method? e.g.
private int _number;
public int setNumber(int number) {
_number = number;
}
UPDATE:
Please look at this code. This will do what you're trying to accomplish.
Activity class
public class TestActivity extends Activity {
public int Number;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.test);
Button btnDisplay = (Button) findViewById(R.id.btnDisplay);
btnDisplay.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Toast toast = Toast.makeText(v.getContext(), "Generated number: " + String.valueOf(Number), Toast.LENGTH_LONG);
toast.show();
}
});
new TestTask(this).execute();
}
}
AsyncTask class
public class TestTask extends AsyncTask<Void, Void, Integer> {
private final Context _context;
private final String TAG = "TestTask";
private final Random _rnd;
public TestTask(Context context){
_context = context;
_rnd = new Random();
}
#Override
protected void onPreExecute() {
//TODO: Do task init.
super.onPreExecute();
}
#Override
protected Integer doInBackground(Void... params) {
//Simulate a long-running procedure.
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
Log.e(TAG, e.getMessage());
}
return _rnd.nextInt();
}
#Override
protected void onPostExecute(Integer result) {
TestActivity test = (TestActivity) _context;
test.Number = result;
super.onPostExecute(result);
}
}
Just a word of caution: Be very careful when attempting to hold a reference to an Activity instance in an AsyncTask - I found this out the hard way :). If the user happens to rotate the device while your background task is still running, your activity will be destroyed and recreated thus invalidating the reference being to the Activity.
Create a listener.
Make a new class file. Called it something like MyAsyncListener and make it look like this:
public interface MyAsyncListener() {
onSuccessfulExecute(int numberOfSongList);
}
Make your activity implement MyAsyncListener, ie,
public class myActivity extends Activity implements MyAsyncListener {
Add the listener to the constructor for your AsyncTask and set it to a global var in the Async class. Then call the listener's method in onPostExecute and pass the data.
public class MyCustomAsync extends AsyncTask<Void,Void,Void> {
MyAsyncListener mal;
public MyCustomAsync(MyAsyncListener listener) {
this.mal = listener;
}
#Override
public void onPostExecute(asynctask.Payload payload) {
\\update UI
mal.onSuccessfulExecute(int numberOfSongList);
}
}
Now, whenever your AsyncTask is done, it will call the method onSuccessfulExecute in your Activity class which should look like:
#Override
public void onSuccessfulExecute(int numberOfSongList) {
\\do whatever
}
Good luck.

Categories

Resources