I'm trying to show a custom dialog in non-activity class for that i need the context of the foreground running activity which I did started from the main activity.
i get this exception when i run
Unable to add window -- token null is not for an application
I did use the context of a service but it not work
Cod of non-activity class
public void Confirmation_dialog_V2(ReportEvent e){
try{
Log.e("Bugreport","Confirmation");
Log.e("Bugreport","event: "+e.getEventDescription());
getRecording_service().stopRecording();
context= getRecording_service().getBaseContext();
context.setTheme(R.style.CustomTheme);
Log.e("Bugreport","get context");
if(context != null) {
Log.e("Bugreport","context not null");
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
Log.e("Bugreport","in run block");
LovelyStandardDialog dialog =new LovelyStandardDialog(context, LovelyStandardDialog.ButtonLayout.VERTICAL);
dialog.setTopColorRes(R.color.indigo);
dialog.setButtonsColorRes(R.color.darkDeepOrange);
dialog.setIcon(R.drawable.ic_assignment_white_36dp);
dialog.setTitle("Confirm_interaction");
dialog.setMessage("Interaction:"+e.getEventDescription());
dialog.setPositiveButton("Confirm", new View.OnClickListener() {
#Override
public void onClick(View view) {
}
});
dialog.setNegativeButton("NO", new View.OnClickListener() {
#Override
public void onClick(View view) {
}
});
dialog.setNeutralButton("Contine", new View.OnClickListener() {
#Override
public void onClick(View view) {
}
});
Log.e("Bugreport","showing");
dialog.show();
}
});
}
}catch (Exception ex){ex.printStackTrace();}
}
so i need the context of the activity in the foreground with I did started from the main activity.
Main activity
Intent App = getPackageManager().getLaunchIntentForPackage(BugReport.getInstance().getPackageName());
App.addCategory(Intent.CATEGORY_LAUNCHER);
App.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
App.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
startActivity(App);
You can use Constructor for this problem.When you declare java class in your MainActivity java class that time Add Context with it.
As per your code you have Added ReportEvent , just Add context with that.like below:
public void Confirmation_dialog_V2(Context context,ReportEvent e){
//your code
}
If you will directly add Context in java class then it will show error in Main Java class where you declare JavaClass.and when you Add context there,error will disappear Automatically.
After it all you can use that context anywhere in that Java class.Thank you:)
public void Confirmation_dialog_V2(ReportEvent e,Context context)
Related
I'm making an Android whack a mole game. I have the main activity which is basically the launcher, when you press the Play button the game activity starts. This works fine as it shows the background image and all molehills but I don't know how to call the method to start the game.
I've tried to call it from inside onCreate() but this ends up "playing the game" itself.
I've tried to call it right after the startActivity(intent) but the app crashes. And also I've tried to create an instance of the game class and call the play() method after the start activity but it doesn't work aswell. I don't know how to start the game method once the game activity is loaded.
I hope I explained well, thank you.
public class MainActivity extends AppCompatActivity {
ImageButton btnStart;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Hide TitleBar
try { this.getSupportActionBar().hide();}
catch (NullPointerException e){}
setContentView(R.layout.activity_main);
btnStart = (ImageButton)findViewById(R.id.btnStart);
btnStart.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(getApplicationContext(), GameView.class);
startActivity(intent);
}
});
}
And this is the code for the game_activity
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Hide TitleBar
try { this.getSupportActionBar().hide();}
catch (NullPointerException e){}
setContentView(R.layout.activity_game_view);
game();
}
The game() method is a typical game loop.
public void game() {
Random random = new Random();
int index;
/*
* Casting array to store all ImageView on the game
*/
imgViewArray[0] = (ImageView)findViewById(R.id.img1);
imgViewArray[1] = (ImageView)findViewById(R.id.img2);
imgViewArray[2] = (ImageView)findViewById(R.id.img3);
imgViewArray[3] = (ImageView)findViewById(R.id.img4);
imgViewArray[4] = (ImageView)findViewById(R.id.img5);
imgViewArray[5] = (ImageView)findViewById(R.id.img6);
imgViewArray[6] = (ImageView)findViewById(R.id.img7);
imgViewArray[7] = (ImageView)findViewById(R.id.img8);
imgViewArray[8] = (ImageView)findViewById(R.id.img9);
imgViewArray[9] = (ImageView)findViewById(R.id.img10);
int j=0;
while (j < 10) {
// Get a random image to animate
index = random.nextInt(10);
switch(index) {
case 0: imgViewArray[0].setImageResource(images[6]);
new java.util.Timer().schedule(
new java.util.TimerTask() {
#Override
public void run() {
imgViewArray[0].setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
imgViewArray[0].setImageResource(images[0]);
}
});
}
},
300 // The code executes after 300ms
);
break;
I think you should put the game() call inside onResume().
There are many ways to solve the problem:
Using EventBus
Send the start game Event from Main Activity and register for the Event in the Game activity.
This is my favorite way to handle the problem. It's because the simplicity and prevent us from tightly coupled code. The major problem with using EventBus is we will lost in the sea of Event if there are too much Event in the the app.
How to do:
First, create the Event. This is just a simple class:
public class StartGameEvent {
}
Second, register for the event in the game activity:
public class GameActivity extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
EventBus.getDefault().register(this);
}
protected void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}
}
Third, subscribe for the event:
public class GameActivity extends Activity {
...
#Subscribe
public void onMessageEvent(StartGameEvent event) {
game();
}
}
Last, send the event from Main activity:
EventBus.getDefault().post(new StartGameEvent());
Using LocalBroadcastManager
You need to create the message and broadcast it in from your Main activity:
Intent intent = new Intent("playEvent");
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
Then, in the game activity, you need to register as receiver:
#Override
public void onCreate(Bundle savedInstanceState) {
// register for the event
LocalBroadcastManager.getInstance(this).registerReceiver(mReceiver,
new IntentFilter("playEvent"));
}
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
game();
}
};
#Override
protected void onDestroy() {
// Unregister here
LocalBroadcastManager.getInstance(this)
.unregisterReceiver(mReceiver);
super.onDestroy();
}
I slightly modifying the code from How to use LocalBroadcastManager? for your case.
Using a static method in Game activity
This is the simplest way but highly discouraged. Because we can't ensure the state of the activity. Do not use this in production code. This is for learning sake only.
You can make the game() method as a static method like this:
public class GameActivity extends Activity {
...
public static void game() {
// game logic.
}
}
Then call the method when you want with:
GameActivity.game();
this is probably simple but i am still a beginner
i have a button in class MainActivity and i want to use the onclick method in another class(another activity) i am aware that it could be easily achieved by making it public static and accessing it as instance but in my case i can not make it public static for some good reason
button xml:
<Button
android:id="#+id/googledrivemain"
android:layout_width="78dp"
android:layout_height="77dp"
android:layout_marginTop="149dp"
android:background="#drawable/google"
android:onClick="onClickOpenFile"
android:paddingTop="6dp"
android:textColor="#fff"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="#+id/imageView3"
app:layout_constraintHorizontal_bias="0.51" />
MainActivity button:
public void onClickCreateFile(View view) {
fileOperation = true;
// create new contents resource
Drive.DriveApi.newDriveContents(mGoogleApiClient)
.setResultCallback(driveContentsCallback);
}
second class button:
btn3.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
MainActivity main = new MainActivity();
use onclick from mainactivity...??
}
});
Do it like this
btn3.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
((MainActivity) getActivity()).onClickCreateFile(v);
}
});
i think it will work.
Simply wrap the code you invoke from the MainActivity.onClickCreateFile() into another class and call it from wherever you want
And never, NEVER, do something like new MainActivity(). Activities are managed by the system
You can create a handler class, something like this:
public static class ClickHandler {
private ClickHandler mInstance;
public static ClickHandler getInstance(){
if(mInstance == null){
mInstance = new ClickHandler();
}
return mInstance;
}
public void onClickCreateFile(View view) {
fileOperation = true;
// create new contents resource
Drive.DriveApi.newDriveContents(mGoogleApiClient)
.setResultCallback(driveContentsCallback);
}
}
Then wherever you need it:
btn3.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ClickHandler.getInstance().onClickCreateFile(view);
}
});
The reason you can't make a click method static is that 1) The android:onClick XML action requires public void and 2) The view that you are clicking belong to the instance of the activity, not the class.
You could make a static method like this.
public static void createDriveContents(GoogleApiClient apiClient, ResultCallback callback) {
Drive.DriveApi.newDriveContents(apiClient)
.setResultCallback(callback);
}
But, then you still need a reference to the GoogleApiClient object.
Since no client is bound to any one Activity, you could move it into a singleton in order to access one client instance from everywhere.
For example,
btn3.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
MainActivity.createDriveContents(
GoogleClientWrapper.getInstance().getClient(), // A GoogleApiClient instance
new ResultCallback() {
// TODO: Implement
});
}
});
If you have access to the GoogleClient in the second class, just pass in the API client object directly.
Or, abstracting up one level, you can instead provide a Context, and re-build the client.
public static void createDriveContents(Context context, ResultCallback callback) {
GoogleApiClient client = new GoogleApiClient.Builder(context);
// TODO: add scopes to client
Drive.DriveApi.newDriveContents(apiClient)
.setResultCallback(callback);
}
With this method, we assume the second class is another activity without it's own GoogleClient
btn3.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
MainActivity.createDriveContents(
SecondClass.this, // A Context instance
new ResultCallback() {
// TODO: Implement
});
}
});
How to get result of background process in any Activity?
I'm working with OTA update. App handle that in background with handler. When update is done I have to show alert dialog to the user. I can show it in SettingsActivity where I start with OTA but user can be in any other Activity.
private void checkIsUpdated() {
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
mDevice.getDevice().read(GattUUID.LS_DEVICE_INFORMATION, GattUUID.LC_FIRMWARE, new
BleDevice.ReadWriteListener() {
#Override
public void onEvent(ReadWriteEvent e) {
if (e.wasSuccess()) {
if (firmwareVersion.equals(e.data_string())) {
showAlertDialog("OTA update failed", "Device is not updated");
} else {
showAlertDialog("OTA update is successful.\nDevice is updated to new " +
"firmware!", "Device is updated");
}
Log.i("OTA", "Read firmware is new success");
} else {
Log.e("OTA", "Read firmware is new success");
}
}
});
}
}, 30000);
}
AlertDialog code
private void showAlertDialog(String message, String title) {
AlertDialog.Builder builder = new AlertDialog.Builder(mContext, R.style.SwipeDialogLight);
builder.setTitle(title)
.setMessage(message)
.setCancelable(false)
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
AlertDialog alert = builder.create();
if (!alert.isShowing()) {
alert.show();
}
}
As #W4R10CK stated, I thought that too. The BroadcastReceiver might not a very good idea. But later, I gave a thought about it and if you call checkIsUpdated function inside a Service and send the Broadcast from it, it might be a feasible solution.
So basically you need a BaseActivity class and in which you need to have a BroadcastReceiver. You need to register it onResume and again unregister it onPause.
And you need to have an abstract method to be overriden in each of your Activity too.
So your BaseActivity may look like this..
public abstract class BaseActivity extends AppCompatActivity {
private final Context context;
public BaseActivity() {
this.context = setContext();
}
protected abstract Context setContext();
#Override
public void onResume() {
super.onResume();
registerBroadcastReceiver();
}
#Override
public void onPause() {
super.onPause();
unRegisterBroadcastReceiver();
}
// Declare your BroadcastReceiver here
private class MyBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
showAlertDialog(context);
}
}
}
As #rogerwar suggested in the comments, the correct approach is a broadcast receiver.
Vogella has a nice tutorial
Since you want to have it in all activities, you can make a base class for all your activities and in this base class you can register the receiver in the onStart and unregister it in the onStop.
I'm using setOnClickListener for listening on the click event on imageButton in two methods, but it's does not fire in my another method,my first listener firing but my second listener does not fire please see my codes :
Class FirstActivity extends BaseActivity
{
#Override
public void onCreate()
{
super.onCreate();
this.methodA();
this.methodB();
}
public void methodA()
{
ImageButton imageButton = (ImageButton) RContextHelper.getActivity().findViewById(R.id.my_location_button);
imageButton.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
//event firing when image button touched
}
});
}
public void methodB()
{
Test test = new Test(this);
test.methodA();
}
}
class Test
{
Context con;
public Test(Context con)
{
this.con = con;
}
public void methodA()
{
ImageButton imageButton = (ImageButton) getActivity().findViewById(R.id.my_location_button);
imageButton.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
//event does not fire when image button touched
}
});
}
protected ActionBarActivity getActivity()
{
return (ActionBarActivity) con;
}
}
As you can guess from the name setOnClickListener sets the new listener and replaces the old one. That is the case with all the set* listeners in Java. If it was addOnClickListener then you could expect that both listeners should be called.
If you want both of them to be called, you can write a composite on click listener and add both of the listeners to it and set the composite listener to the target.
class CompositeListener implements OnEventListener {
private List<OnEventListener> registeredListeners = new ArrayList<OnEventListener>();
public void registerListener (OnEventListener listener) {
registeredListeners.add(listener);
}
public void onEvent(Event e) {
for(OnEventListener listener:registeredListeners) {
listener.onEvent(e);
}
}
}
And then:
CompositeListener composite = new CompositeListener();
composite.registerListener(listener1);
composite.registerListener(listener2);
imageButton.setOnEventListener(composite);
Source
Very confusing to code with two methodA functions. You never call the second one. At least you are not showing code for that. Moreover - as has been said already - there can only be one listener.
I'm trying to figure out how to create an AsyncTask that runs my php API code in the background then alerts my MainActivity once it completes. I've been reading tutorials and trying things for hours now and I'm just frustrated at this point as I can't find anywhere that answers my question.
I create the AsyncTask and it runs successfully and I can log the returned information from my API in the onPostExecute but I cannot figure out how to alert the MainActivity that the task was completed. I do not know what to pass into the creation of the APICall. Every tutorial I read shows that the AsyncTask constructor takes the interface as an argument as shown in my code below, but how do you pass an interface as an argument?
MainActivity.java (implements OnTaskCompleted)
myButton4.setOnClickListener(new OnClickListener(){
public void onClick(View v){
APICall api = new APICall( ???What do I put here?? );
api.execute("users");
}});
....
#Override
public void onTaskCompleted() {
Log.v("Play","Main Activity ON Task completed!");
OnTaskCompleted.java
public interface OnTaskCompleted {
public void onTaskCompleted();
}
APICall.java (extends AsyncTask)
public APICall(OnTaskCompleted listener){
this.listener = listener;
}
....
protected void onPostExecute(JSONObject j)
{
listener.onTaskCompleted();
}
You should pass the reference of your listener to the APICall class:
APICall api = new APICall(MainActivity.this);
Simple you can use anonymous interface instance like this.
myButton4.setOnClickListener(new OnClickListener(){
public void onClick(View v){
APICall api = new APICall(new OnTaskCompleted() {
#Override
public void onTaskCompleted() {
}
});
api.execute("users");
}});
OR you can Implement interface at class level like this
public class MainActivity extends Activity implements MainActivity.OnTaskCompleted {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myButton4.setOnClickListener(new OnClickListener(){
public void onClick(View v){
APICall api = new APICall(MainActivity.this);
api.execute("users");
}});
}
#Override
public void onTaskCompleted() {
// Do your code on task complete
}
}
APICall api = new APICall( ???What do I put here?? );
What do I put here??
The one that implements your listener in this case your MainActivity
APICall api = new APICall(MainActivity.this);