I am trying to call an intent from a handler and I don't know how to do it. I have tried many different ways but it does't seem to be working. I want to start the PrimeNumbersActivity when the progress dialog reaches its max.
public class MyHandler extends Handler {
ProgressDialog progressDialog;
Context context;
public MyHandler(ProgressDialog progressDialog) {
this.progressDialog = progressDialog;
}
public MyHandler(Context context){
this.context = context;
}
#Override
public void handleMessage(Message msg) {
findPrimeNumber(Integer.parseInt(msg.obj.toString()));
}
public void findPrimeNumber(int number){
ArrayList<Integer> primeNumbers = new ArrayList<>();
boolean isPrimeNumber;
PrimeNumbers primeNumbers1 = new PrimeNumbers();
for(int i = 2; i <= number; i++){
isPrimeNumber = true;
for(int j = 1; j <= i; j++){
try {
sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(j != 1 && j != i){
if(i%j == 0){
isPrimeNumber = false;
break;
}
}
}
if(isPrimeNumber){
primeNumbers.add(i);
primeNumbers1.primeNumbers.add(i);
}
progressDialog.setProgress(i*100/number);
if(progressDialog.getProgress() == progressDialog.getMax()){
progressDialog.dismiss();
Intent intent = new Intent(context.getApplicationContext(),PrimeNumbersActivity.class);
context.startActivity(intent);
}
}
for (int i :
primeNumbers) {
Log.d(TAG, i + "");
}
}
}
the PrimeNumbersActivity
public class PrimeNumbersActivity extends AppCompatActivity {
private PrimeNumbers primeNumbers = new PrimeNumbers();
private ListView listView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_prime_numbers);
listView = findViewById(R.id.listView);
if(primeNumbers.primeNumbers.isEmpty()){
Toast.makeText(getApplicationContext(),"Pas de nombres premiers",Toast.LENGTH_SHORT).show();
}else{
ArrayAdapter<Integer> arrayAdapter = new ArrayAdapter<Integer>(getApplicationContext(),android.R.layout.simple_list_item_1,primeNumbers.primeNumbers);
listView.setAdapter(arrayAdapter);
}
}
}
MainActivity
public class MainActivity extends AppCompatActivity {
public static final int number = 20;
public Button button;
public EditText editText;
public ProgressDialog progressDialog;
public AlertDialog.Builder alertDialog;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
progressDialog = new ProgressDialog(MainActivity.this);
progressDialog.setMax(100);
progressDialog.setMessage("Please wait...");
progressDialog.setTitle("Finding prime numbers");
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
final MyThread thread = new MyThread(progressDialog);
thread.setName("MyThread");
thread.start();
button = (Button) findViewById(R.id.afficherNombrePremier);
editText = (EditText) findViewById(R.id.editText);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(editText.getText().toString().isEmpty()){
alertDialog = new AlertDialog.Builder(MainActivity.this);
alertDialog.setTitle("Warning");
alertDialog.setMessage("Veuillez saisir un nombre entier dans la zone de texte");
alertDialog.show();
}
else{
progressDialog.show();
Message message = Message.obtain();
message.obj = editText.getText().toString();
thread.mHandler.sendMessage(message);
}
}
});
}
}
Error:
04-24 00:45:15.457 4625-4712/com.example.mohammed.tdservicesex1 E/AndroidRuntime: FATAL EXCEPTION: MyThread
Process: com.example.mohammed.tdservicesex1, PID: 4625
java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.Context android.content.Context.getApplicationContext()' on a null object reference
at com.example.mohammed.tdservicesex1.MyHandler.findPrimeNumber(MyHandler.java:65)
at com.example.mohammed.tdservicesex1.MyHandler.handleMessage(MyHandler.java:31)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at com.example.mohammed.tdservicesex1.MyThread.run(MyThread.java:22)
Thread:
public class MyThread extends Thread {
private static final String TAG = MyThread.class.getSimpleName();
public MyHandler mHandler;
ProgressDialog progressDialog;
public MyThread(ProgressDialog progressDialog) {
this.progressDialog = progressDialog;
}
#Override
public void run() {
Looper.prepare();
mHandler = new MyHandler(progressDialog);
Looper.loop();
}
}
The error is happened because you haven't set any context with your constructor in your MyHandler class. Your constructors is like the following:
public class MyHandler extends Handler {
...
public MyHandler(ProgressDialog progressDialog) {
this.progressDialog = progressDialog;
}
public MyHandler(Context context){
this.context = context;
}
...
}
you can see that you have 2 different constructors. In your code, you're only using the first constructor, you never assign the context with your second constructor. This is a common error when you're using multiple constructor for a class.
To solve the problem, you need to change your constructor so that it needs two parameters: ProgressDialog and Context. Change the constructor to something like this:
public class MyHandler extends Handler {
...
public MyHandler(ProgressDialog progressDialog, Context context) {
this.progressDialog = progressDialog;
this.context = context;
}
...
}
I believe you cannot start an activity using the application context (in a straightforward manner). You either have to
Use activity context
Use application context but add this flag FLAG_ACTIVITY_NEW_TASK
Be warned that FLAG_ACTIVITYNEW_TASK will start a new task in the history stack
Try something like this:
Intent intent = new Intent(context.getApplicationContext(),PrimeNumbersActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
Make sure you declared PrimeNumbersActivity in Android Manifest
This should work:
Intent intent = new Intent(context,PrimeNumbersActivity.class);
context.startActivity(intent);
If #2 does not work. It means this condition is always false:
if(progressDialog.getProgress() == progressDialog.getMax())
Related
I want to bring up a progress dialog when the user loads up the twitter feed and when the twitter feed has loaded the progress dialog disappears.
This is the TwitterAsyncTask class:
public class TwitterAsyncTask extends AsyncTask<Object, Void, ArrayList<TwitterTweet>> {
ListActivity callerActivity;
private ProgressDialog pd;
final static String TWITTER_API_KEY = "ddd";
final static String TWITTER_API_SECRET ="fffff";
Context cnt;
#Override
protected void onPreExecute() {
super.onPreExecute();
pd = new ProgressDialog(cnt.getApplicationContext());
pd.setMessage("loading");
pd.show();
}
#Override
protected ArrayList<TwitterTweet> doInBackground(Object... params) {
ArrayList<TwitterTweet> twitterTweets = null;
callerActivity = (ListActivity) params[1];
if (params.length > 0) {
TwitterAPI twitterAPI = new TwitterAPI(TWITTER_API_KEY,TWITTER_API_SECRET);
twitterTweets = twitterAPI.getTwitterTweets(params[0].toString());
}
return twitterTweets;
}
#Override
protected void onPostExecute(ArrayList<TwitterTweet> twitterTweets) {
ArrayAdapter<TwitterTweet> adapter =
new ArrayAdapter<TwitterTweet>(callerActivity, R.layout.twitter_tweets_list,
R.id.listTextView, twitterTweets);
callerActivity.setListAdapter(adapter);
ListView lv = callerActivity.getListView();
lv.setDividerHeight(0);
lv.setBackgroundColor(callerActivity.getResources().getColor(R.color.white));
if (pd != null)
{
pd.dismiss();
}
}
}
And here is the class that calls the TwitterAsyncTask class:
public class MainActivity extends ListActivity {
final static String twitterScreenName = "CFABUK";
final static String TAG = "MainActivity";
private AsyncTask<Object, Void, ArrayList<TwitterTweet>> tat;
boolean done;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
done = false;
AndroidNetworkUtility androidNetworkUtility = new AndroidNetworkUtility();
if (androidNetworkUtility.isConnected(this)) {
new TwitterAsyncTask().execute(twitterScreenName, this);
} else {
Log.v(TAG, "Network not Available!");
}
}
public void timerDelayRemoveDialog(long time, final ProgressDialog d) {
new Handler().postDelayed(new Runnable() {
public void run() {
d.dismiss();
}
}, time);
}
}
the error seems to appear for the line pd = new ProgressDialog(cnt.getApplicationContext());...What should I put for this? thanks
Just add Constructor in your AsyncTask like
Context mContext;
public TwitterAsyncTask(Context mContext){
this.mContext=mContext;
}
And from your activity
Context mContext=this;
new TwitterAsyncTask(mContext).execute(twitterScreenName, this);
Instead of cnt.getApplicationContext() replace it with YourClassName.this
Embed your Async task in your activity, and replace your Context cnt by YourActivity.class... And please include some log.
So I am completely new to Andorid programming and can't seem to get a ProgressDialog to show on a ListActivity (ScheduleActiviy in my example) when running an AsyncTask from a separate class (GetGames in my example). I am attempting to use separate class for code re-usability. When I previously had the AsyncTask as an embedded class it seemed to work. I have posted what I believe to be all the relevant code. Any help would be great. Thanks!
ScheduleActivity.java
public class ScheduleActivity extends ListActivity
{
private final String PDIALOG_MSG = "Loading schedule...";
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.schedule);
ArrayList<HashMap<String, String>> gamesList = null;
try
{
// Loading information in Background Threads
gamesList = new GetGames(ScheduleActivity.this, PDIALOG_MSG).execute().get();
GetGames.java
public class GetGames extends AsyncTask<Void, Void, ArrayList<HashMap<String, String>>>
{
private Context context;
private ProgressDialog pDialog;
private String pDialogMsg;
public GetGames(Context ctx, String dialogMsg)
{
context = ctx;
pDialogMsg = dialogMsg;
}
#Override
public void onPreExecute()
{
super.onPreExecute();
pDialog = new ProgressDialog(context);
pDialog.setMessage(pDialogMsg);
pDialog.setIndeterminate(false);
pDialog.setCancelable(false);
pDialog.show();
}
#Override
public void onPostExecute(ArrayList<HashMap<String, String>> rtnList)
{
pDialog.dismiss();
}
Your ProgressDialog should probably be controlled on the Activity level instead of the AsyncTask level. Theoretically I don't see why how you're doing it wouldn't work, but I can show you a method which definitely works (it's what I do) and it organizes things a bit differently:
//In AsyncTask
#Override
protected void onPreExecute() {
showProgressDialog(R.string.importing_pages);
}
#Override
public void onPostExecute(Boolean b) {
hideProgressDialog();
}
//In Activity
public void showProgressDialog(int msgResId) {
showProgressDialog(getString(msgResId));
}
public void showProgressDialog(String msg) {
mProgressDialog = ProgressDialogHelper.buildDialog(this, msg);
mProgressDialog.show();
}
public void hideProgressDialog() {
if(mProgressDialog != null)
mProgressDialog.dismiss();
}
//My progress dialog helper class:
public class ProgressDialogHelper {
/**
* Creates a generic progress dialog with the specified message
*
* #param activity the activity which hosts the dialog. This must be an activity, not a context.
* #param msgResId the resId for the message to display
* #return a progress dialog
*/
public static ProgressDialog buildDialog(Activity activity, int msgResId) {
return buildDialog(activity, activity.getApplicationContext().getString(msgResId));
}
/**
* Creates a generic progress dialog with the specified message
*
* #param activity the activity which hosts the dialog. This must be an activity, not a context.
* #param msg the message to display
* #return a progress dialog
*/
public static ProgressDialog buildDialog(Activity activity, String msg) {
ProgressDialog dialog;
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
dialog = new ProgressDialog(new ContextThemeWrapper(activity, android.R.style.Theme_Holo_Dialog));
else
dialog = new ProgressDialog(activity);
dialog.setMessage(msg);
dialog.setCancelable(false);
return dialog;
}
}
You don't have to make a helper class if you don't want to, it's just how I organized it. The main idea here is that the progress dialog should be owned by the Activity instead of the AsyncTask.
Also, the context used must be the activity's, not getApplicationContext(). It looks like you have that part right though.
You can display Progress Dialogs using AsyncTasks. That's not a problem. I do it all the time. What may be the problem is the doInBackground() method. What do you have there?
I also generally nest the AsyncTasks within the Activity class, so that it can call other Activity class methods in the onPostExecute() method. Otherwise, in order for it to communicate back with your Activity you'll have to use something like a handler or static references.
public class TestActivity extends Activity {
private AsyncTask<Void, Void, ArrayList<String>> bgLoader;
private ArrayList<String> listOfStuff;
private TextView textView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
listOfStuff = new ArrayList<String>();
textView = (TextView) findViewById(R.id.textView);
textView.setText("Your list has " + listOfStuff.size() + " items in it!");
bgLoader = new MyAsyncTask(this, "Waiting...").execute();
}
private void resumeDoingStuff() {
try {
listOfStuff = bgLoader.get();
textView.setText("Your list has " + listOfStuff.size() + " items in it!");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
public class MyAsyncTask extends AsyncTask<Void, Void, ArrayList<String>> {
private ProgressDialog progressDialog;
private String message;
private Context ctx;
public MyAsyncTask(Context context, String message) {
this.ctx = context;
this.message = message;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
progressDialog = new ProgressDialog(ctx);
progressDialog.setMessage(message);
progressDialog.setIndeterminate(false);
progressDialog.setCancelable(false);
progressDialog.show();
}
#Override
protected ArrayList<String> doInBackground(Void... params) {
ArrayList<String> retList = new ArrayList<String>();
for (int i = 0; i < 10; i++) {
try {
retList.add("TEST STRING " + i);
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return retList;
}
#Override
protected void onPostExecute(ArrayList<String> result) {
progressDialog.dismiss();
resumeDoingStuff();
}
}
}
I have 2 activities, 1 for main and other for custom progressBar dialog, I want to start this custom progressBar activity as dialog on button click from main activity, as it starts it's ok but I need to update the progressBar values continuesly, as it comes changing... I tried to create some methods in progressBar activity also tried to access progressBar object as Static way but in both cases it throws exception of NULL POINTER. Currently I am starting activity as
startActivity(new Intent(context, ProgressBar.class));
Any help?
MAIN ACTIVITY
public class UnicornActivity extends Activity implements
android.view.View.OnClickListener {
Button btnStart;
ProgressDialog prog = new ProgressDialog();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnStart = (Button) findViewById(R.id.btnStart);
btnStart.setOnClickListener(this);
}
#Override
public void onClick(View arg0) {
startActivity(new Intent(getApplicationContext(), ProgressDialog.class));
ProgressDialog.setMax(1000);
ProgressDialog.setMessage("it's gonna be fun");
new Thread(new Runnable() {
#Override
public void run() {
for (int i = 0; i < 1000; i++) {
ProgressDialog.setProg(i);
}
}
}).start();
}
}
PROGRESSBAR ACITIVITY
public class ProgressDialog extends Activity{
static TextView to, till, message;
static ProgressBar progress;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
System.out.println("Inside activity");
to = (TextView) findViewById(R.id.txtTo);
till = (TextView) findViewById(R.id.txtTill);
message = (TextView) findViewById(R.id.txtMessage);
progress = (ProgressBar) findViewById(R.id.progress);
}
public static void setProg(int val) { //NULL POINTER EXCEPTION
to.setText(val + "");
progress.setProgress(val);
}
public static void setMax(int val) { //NULL POINTER EXCEPTION
till.setText(val + "");
progress.setMax(val);
}
public static void setMessage(String msg) { //EXCEPTION
message.setText(msg);
}
}
any reason you have ProgressDialog as an activity?
create a class that extends AsyncTask, make the progress dialog a member, onProgressUpdate call SetProgress.
I have two major classes in my project. The first is for creating the connection between the client and the server. The second is for switching between activities.
first:
public class MyActivity extends Activity{
private ListView mList;
private ArrayList<String> arrayList;
private MyCustomAdapter mAdapter;
public TCPClient mTcpClient;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
boolean flag = getIntent().getBooleanExtra("flag",false);
arrayList = new ArrayList<String>();
final EditText editText = (EditText) findViewById(R.id.editText);
Button send = (Button)findViewById(R.id.send_button);
Button menu = (Button)findViewById(R.id.button1);
if (flag == true)
{
//relate the listView from java to the one created in xml
mList = (ListView)findViewById(R.id.list);
mAdapter = new MyCustomAdapter(this, arrayList);
mList.setAdapter(mAdapter);
new connectTask().execute("");
Intent myIntent = new Intent(MyActivity.this,Menu.class);
startActivity(myIntent);
}
send.setOnClickListener(new View.OnClickListener() {
// #Override
public void onClick(View view) {
String message = editText.getText().toString();
//clean the listView to 1 item
if (message.equals("clean"))
{
arrayList.removeAll(arrayList);
mList.removeAllViewsInLayout();
}
//add the text in the arrayList
arrayList.add("c: " + message);
//sends the message to the server
if (mTcpClient != null) {
mTcpClient.sendMessage(message);
}
//refresh the list
mAdapter.notifyDataSetChanged();
editText.setText("");
}
});
//change Activity to live screen mode (live)
menu.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Intent myIntent = new Intent(MyActivity.this, Menu.class);
startActivity(myIntent);
}
});
}
public class connectTask extends AsyncTask<String,String,TCPClient> {
#Override
protected TCPClient doInBackground(String... message) {
//we create a TCPClient object and
mTcpClient = new TCPClient(new TCPClient.OnMessageReceived() {
// #Override
//print the message as an Item
public void messageReceived(String message) {
//this method calls the onProgressUpdate
publishProgress(message);
}
});
mTcpClient.run();
return null;
}
#Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
//in the arrayList we add the messaged received from server
arrayList.add(values[0]);
// notify the adapter that the data set has changed. This means that new message received
// from server was added to the list
mAdapter.notifyDataSetChanged();
}
}
}
the object TCPClient mTcpClient is the major factor in my app. I use it communicate with the server. In addition, even if I switch between activities it is still running properly so I still get info from server even though I am not in that activity.
second:
public class Menu extends Activity
{
public MyActivity myActivity;
public TCPClient mtcp;
protected void onCreate(Bundle savedInstanceState, MyActivity myActivity)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.menu);
ImageView action = (ImageView) findViewById(R.id.imageView1);
action.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event)
{
// here I would like to use mTcpClient object mentioned in the first class
return false;
}
});
}
Basically what I need is a help on how to create in the second class reference to the object mTcpClient that is described in the first class.
You are doing it wrong. If you want to use TcpClient class regardless of context it should NOT be related to first Activity. What you should do is to use singleton pattern:
class TcpClient {
protected static TcpClient mInstance = null;
public TcpClient() {
// your init code...
}
public static TcpClient getInstance() {
if( mInstance == null ) {
mInstance = new TcpClient();
}
return mInstance;
}
...
}
and then, whenever you want to use TcpClient you just do:
TcpClient client = TcpClient.getInstance();
During onCreate(), I'm downloading resources from the web, which takes time. I'd like to display a message on the screen to advise the user. I tried toast, but nothing shows up. Is there another way to print something to the screen?
i think onCreate() work like a constructor for a class and you can not load any visual when it is not finished yet.
so i advice you to use another activity with your message and then call your activity in it.
You have to create a splash screen , that's the way it's called.
It's a mediator Activity that is handling such actions.
Example:
public class SplashScreen extends BaseActivity {
public ProgressDialog ProgressBar = null;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
HideTitle();
setContentView(R.layout.splash);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
if (!IsConnected()) {
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
finish();
}
}, 4000);
} else {
ProgressBar = ProgressDialog.show(this, "", "Loading...", false, false);
SplashScreenDelay splashScreenDelay = new SplashScreenDelay(this, this);
splashScreenDelay.execute(10);
}
}
here is the class that does the loading and after that sends to the main
public class SplashScreenDelay extends AsyncTask<Integer, Integer, List<RssItem>> {
private Context _context;
private SplashScreen _activity;
public SplashScreenDelay(SplashScreen activity, Context context) {
_context = context;
_activity = activity;
}
#Override
protected List<RssItem> doInBackground(Integer... params) {
return RssParsingService.getListOfItems();
}
#Override
protected void onPostExecute(List<RssItem> result) {
Intent intent = new Intent(_context, Viewport.class);
_context.startActivity(intent);
if (_activity.ProgressBar != null) {
_activity.ProgressBar.dismiss();
}
}
}