Sharing data between an activity and a class - android

I have an activity MyActivity that holds a service class MyService.
I would like the service to send String data to the activity, and then create a button using this data.
Following this post I created a static method in the activity.
The problem of course is that i can't use this in a static context.
public class MyActivity extends Activity {
private MyService myService;
public void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.main);
myService = new MyService();
}
public static void connectMethod (String buttonName) {
Button btn = new Button(this); // error
btn.setId(i);
final int buttonID = btn.getId();
btn.setText(buttonName + buttonID);
}
}
public class MyService {
...
private void showButton (String data) {
MyActivity.connectedMethod(data);
}
}

Two possible solutions to avoid your error:
public static void connectMethod (Context context, String buttonName) {
Button btn = new Button(context);
btn.setId(i);
final int buttonID = btn.getId();
btn.setText(buttonName + buttonID);
}
// ...
public class MyService {
private Context context;
public MyService(Context context) {
this.context = context;
}
...
private void showButton (String data) {
MyActivity.connectedMethod(context, data);
}
}
Or create a static class field : private static Context context;
public static void connectMethod (String buttonName) {
Button btn = new Button(context);
btn.setId(i);
final int buttonID = btn.getId();
btn.setText(buttonName + buttonID);
}

Related

How to correctly implement android Lifecycle with the architecture component

I'm new to architecture component, I have created a ViewModel class and implemented LifecycleObserver as per the architecture component, inside the ViewModel class i have a overriden run() method of runnable interface and call it recursively with delay by the help of handler class, inside this value images array changes and wrapped by the live data.
MainActivity observe the changes of the images array and as the value changes, ImageView binds the value of images array.Main activity is also the lifecycle owner.
Now i want to implement Lifecycle observer, so that when i pause my application run() method should also pause and when i resume the application it start from where i pause.
I tried it by creating pause and resume method in the handler, but it didn't work.
Help me with this.
MainActivity Class
private ImageViewModel imageViewModel;
private ImageView imageView;
private ProgressBar progressBar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
showDialogueBox();
}
private void showDialogueBox() {
final Dialog dialog = new Dialog(MainActivity.this);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(R.layout.dialogue_box);
dialog.setTitle("custom");
Button button =(Button)dialog.findViewById(R.id.button1);
button.setEnabled(true);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
imageViewModel = ViewModelProviders.of(MainActivity.this).get(ImageViewModel.class);
subscribe();
dialog.cancel();
}
});
dialog.show();
}
private void subscribe() {
final Observer<Integer> imageTimeObserver = new Observer<Integer>() {
#Override
public void onChanged(#Nullable Integer integer) {
imageView = findViewById(R.id.imageView);
imageView.setImageResource(integer);
getLifecycle().addObserver(new BrainalyseComponent(MainActivity.this,getApplicationContext(),imageViewModel));
}
};
final Observer<Integer> progressbarTimeObserver = new Observer<Integer>() {
#Override
public void onChanged(#Nullable Integer integer) {
progressBar = findViewById(R.id.progressBar);
progressBar.setProgress(integer);
}
};
imageViewModel.getImage().observe(this,imageTimeObserver);
imageViewModel.getProgressbarStatus().observe(this,progressbarTimeObserver);
}
ViewModel class
private int imagesIndex;
private int delay;
public Handler handler;
private MutableLiveData<Integer> imageLiveData = new MutableLiveData<>();
private MutableLiveData<Integer> progressbarLiveData = new MutableLiveData<>();
private int progressBarStatus;
private HashMap<Integer,Integer> imagesAndDelay;
private int images[] =
{
R.drawable.food_1,
R.drawable.food_2,
R.drawable.food_3,
R.drawable.food_4,
R.drawable.food_5,
R.drawable.food_6,
R.drawable.food_7,
R.drawable.food_8,
R.drawable.food_9,
R.drawable.food_10
};
public ImageViewModel(){
imagesIndex = 0;
progressBarStatus = 0;
delay = 2;//to be changed as delay will be discussed
handler = new Handler();
imagesAndDelay = new HashMap<>();
shuffleImages();
runnable.run();
}
private void shuffleImages() {
Random random = new Random();
for (int i = 0; i < images.length; i++) {
int j = random.nextInt(images.length);
int temp = images[i];
images[i] = images[j];
images[j] = temp;
}
}
public Runnable runnable = new Runnable() {
#Override
public void run() {
if (imagesIndex<images.length){
progressBarStatus += 100/images.length;
progressbarLiveData.postValue(progressBarStatus);
imageLiveData.postValue(images[imagesIndex]);
imagesAndDelay.put(images[imagesIndex],delay);
imagesIndex++;
delay += 2;
}else {
stopTask();
return;
}
handler.postDelayed(runnable,2000);
}
};
public Thread newThread = new Thread(){
public void run(){
if (imagesIndex<images.length){
progressBarStatus += 100/images.length;
progressbarLiveData.postValue(progressBarStatus);
imageLiveData.postValue(images[imagesIndex]);
imagesAndDelay.put(images[imagesIndex],delay);
imagesIndex++;
delay += 2;
}else {
stopTask();
return;
}
try {
sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
run();
}
}
};
public LiveData<Integer> getImage(){
return imageLiveData;
}
public LiveData<Integer> getProgressbarStatus(){
return progressbarLiveData;
}
private void stopTask() {
delay = 2;
progressBarStatus = 0;
imagesIndex = 0;
Utility.setImagesAndDelay(imagesAndDelay);
handler.removeCallbacks(runnable);
}
LifecycleObsever
private Context mContext;
private static final String LOG_TAG = BrainalyseComponent.class.getSimpleName();
private ImageView imageView;
private ProgressBar progressBar;
private Integer integer;
LifecycleOwner lifecycleOwner;
private ImageViewModel imageViewModel;
public BrainalyseComponent(LifecycleOwner lifecycleOwner, Context context, ImageViewModel imageViewModel) {
this.mContext = context;
this.imageView = imageView;
this.imageViewModel = imageViewModel;
this.integer = integer;
this.progressBar = progressBar;
this.lifecycleOwner = lifecycleOwner;
}
#OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
public void onResume(){
Log.d(LOG_TAG,"on resume of app");
}
#OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
public void onPause(){
}
You're missing listener and you'll need to remove it at some point (from onDestroy for example)
public BrainalyseComponent(LifecycleOwner lifecycleOwner, Context context, ImageViewModel imageViewModel) {
this.mContext = context;
this.imageView = imageView;
this.imageViewModel = imageViewModel;
this.integer = integer;
this.progressBar = progressBar;
this.lifecycleOwner = lifecycleOwner;
lifecycleOwner.getLifecycle().addObserver(this);
}
#OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
public void onDestroy(){
lifecycleOwner.getLifecycle().removeObserver(this);
}

Access TextView and Progressbar in Recyclerview from IntentService

I am having a recyclerview which has a TextView (progresstxt) and a Progressbar (downloadprogress) as part of the inflated items.
I need to know how I can access the TextView and Progressbar in the SimpleAdapter from the IntentService so I can update their values?
I am trying to achieve this with a BroadcastReceiver but it doesn`t work, the TextView and Progressbar are not being updated.
Thank you in advance.
I access the TextView and Progressbar through onBindViewHolder.
public class SimpleAdapter extends RecyclerView.Adapter<SimpleAdapter.SimpleViewHolder> implements FollowRedirectsCallback {
private final Context mContext;
private String recievedStr;
private int receivedProg;
private MyBroadcastReceiver myBroadcastReceiver;
private MyBroadcastReceiver_Update myBroadcastReceiver_Update;
public static class SimpleViewHolder extends RecyclerView.ViewHolder {
public final TextView title, progresstxt;
public ProgressBar downloadprogress;
public SimpleViewHolder(View view) {
super(view);
title = (TextView) view.findViewById(R.id.simple_text);
progresstxt = (TextView) view.findViewById(R.id.progress_text);
downloadprogress = (ProgressBar) view.findViewById(R.id.progressdownload);
}
...
public class MyBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
recievedStr = intent.getStringExtra(MoService.EXTRA_KEY_UPDATE);
//progresstxt.setText(result); ?
//how to access the TextView in onBindViewHolder?
}
}
public class MyBroadcastReceiver_Update extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
receivedProg = intent.getIntExtra(MoService.EXTRA_KEY_UPDATE_PROGRESS, 0);
//downloadprogress.setProgress(update); ?
//how to access the Progressbar in onBindViewHolder?
}
}
...
#Override
public void onBindViewHolder(final SimpleViewHolder holder, final int position) {
//
myBroadcastReceiver = new MyBroadcastReceiver();
myBroadcastReceiver_Update = new MyBroadcastReceiver_Update();
//register BroadcastReceiver
IntentFilter intentFilter = new IntentFilter(MoService.ACTION_MyIntentService);
intentFilter.addCategory(Intent.CATEGORY_DEFAULT);
mContext.registerReceiver(myBroadcastReceiver, intentFilter);
IntentFilter intentFilter_update = new IntentFilter(MoService.ACTION_MyUpdate);
intentFilter_update.addCategory(Intent.CATEGORY_DEFAULT);
mContext.registerReceiver(myBroadcastReceiver_Update, intentFilter_update);
//
holder.progresstxt.setText(recievedStr);
holder.downloadprogress.setProgress(receivedProg);
holder.progresstxt.setVisibility(View.VISIBLE);
holder.downloadprogress.setVisibility(View.VISIBLE);
//
}
mContext.unregisterReceiver(myBroadcastReceiver);
mContext.unregisterReceiver(myBroadcastReceiver_Update);
}
Through a IntentService (MoService) several file operations are done and I want to access/update the TextView and Progressbar from this IntentService.
public class MoService extends IntentService {
public static final String ACTION_MyIntentService = "com.sample.RESPONSE";
public static final String ACTION_MyUpdate = "com.sample.UPDATE";
public static final String EXTRA_KEY_UPDATE = "EXTRA_UPDATE";
public static final String EXTRA_KEY_UPDATE_PROGRESS = "EXTRA_UPDATE_PROGRESS";
String message;
int mProgress;
..
public MoService() {
super("MyService");
}
#Override
public void onCreate() {
context = this;
super.onCreate();
}
#Override
protected void onHandleIntent(Intent intent) {
//
Intent intentUpdate = new Intent();
intentUpdate.setAction(ACTION_MyUpdate);
intentUpdate.addCategory(Intent.CATEGORY_DEFAULT);
intentUpdate.putExtra(EXTRA_KEY_UPDATE, message);
sendBroadcast(intentUpdate);
//
}
class MyDownloadDownloadStatusListener implements DownloadStatusListener {
#Override
public void onDownloadComplete(DownloadRequest request) {
message = "Status: completed...";
mProgress = 0;
progresstxt.setVisibility(View.GONE);
downloadprogress.setVisibility(View.GONE);
..
}
}
There are a couple of issues with the code. You should not create a new Receiver in your onBindViewHolder method.
There should be a single receiver which updates the Item list used by your adapter and call notifyDataSetChanged on the adapter.
Hope it helps

Get score value from serializable class to activity

I am developing a game in which I've a serializable class that has a score parameter and it is set to 0 initially.
Now what I want that when the score is greater than 1 then the score value is passed to my main activity and some toast is shown in the main activity
This is my code for serializable class:
public class Game implements Serializable{
private static final long serialVersionUID = 8326065952389292265L;
private int score = 0;
Here is my score increase and when it is greater than 1 then the score value should be passed to main activity
if(bird.GetX()+bW > px1 && bird.GetX() < px2)
{
if(birdY1>=minY && birdY2<=maxY)
{
}
else
{
if(!boom)
SoundManager.playSound(5, 1);
boom = true;
bird.SetState(0);
}
score = (i+1);
if (score>1)
{
}
}
I am confused how to send this score value to my main activity and then how to get it in main activity. Can anyone help me some little code that how it is done? Any help will be appreciated
Here is my MainActivity code:
public class MainActivity extends Activity {
private static final String TAG = MainActivity.class.getSimpleName();
private SurfaceView mainGameView;
static Bitmap bitmap;
static Canvas canvas;
private GameLogic gameLogic;
private Game gamescore;
private ArrayList<String> wordsDictionary;
private Context context;
private MyTask mt;
private boolean dictionaryLoaded;
private ImageView image;
private Activity activity;
Intent playbackServiceIntent;
#TargetApi(Build.VERSION_CODES.GINGERBREAD)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
activity = this;
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
requestWindowFeature(Window.FEATURE_NO_TITLE);
SoundManager.getInstance();
SoundManager.initSounds(this);
SoundManager.loadSounds();
SoundManager.playSound(1, 1);
if(true)
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
else
getWindow().setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN, WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);
context = this;
gameLogic = new GameLogic(context, getResources());
dictionaryLoaded = false;
SharedPreferences sPref = getPreferences(MODE_PRIVATE);
String data1 = sPref.getString("data1", "");
mainGameView = new MainGameView(this, gameLogic);
final RelativeLayout layout = new RelativeLayout(context);
layout.addView(mainGameView);
Runnable runnable = new Runnable() {
#Override
public void run() {
}
};
new Thread(runnable).start();
if(true)
{
setContentView(layout);
}
}
public static void setScore(int s) {
score=s;
}
public static int getScore()
{
return score;
}
Now you can use as in your main Activity :
int scr=Game.getScore();
above code will return the score
Create one interface
public interface GameScoreListener{
void onScoreIncrease(int incrementBy);
void onScoreDecrease(int decrementBy)
}
Implement GameScoreListener in MainActivity.
Create GameScoreListener setter and getter in the class where you're changing score. When Score change in any method check GameScoreListener for NPE, then make callback from GameScoreListener.

Android make callback to an Activity from java class

How can i make a callback to an Activity form a Java Class?
Example:
public class TestClass{
String text = "Test";
public TestClass(Context context){
startActivity(new Intent(context, SomeActivity.class));
}
private void sendToSomeActivity(){
//Call some method of SomeActivity and pas text as string
}
}
When sendToSomeActivity() is called, i want to make a callback to the already started SomeActivity and pass some text to the Activity. In SomeActivity i want to use the text.
Note: The TestClass object that i want to use is already created in another class.
How can this be done?
The solution I chose is as follows:
Use BroadcastReceivers to communicate between Java classes and Activities.
Example:
public class SomeActivity extends Activity{
private MyBroadcastReceiver receiver;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
receiver = new MyBroadcastReceiver();
this.registerReceiver(receiver, new IntentFilter(MyBroadcastReceiver.ACTION));
}
#Override
public void onDestroy() {
super.onDestroy();
this.unregisterReceiver(receiver);
}
private class MyBroadcastReceiver extends BroadcastReceiver{
public static final String ACTION = "com.example.ACTION_SOMETHING"
#Override
public void onReceive(Context context, Intent intent) {
String test = intent.getStringExtra("dataToPass");
}
}
}
public class TestClass{
private String test = "TEST";
private Context context;
public TestClass(Context context){
this.context = context;
}
private void sendToSomeActivity(){
Intent intent = new Intent();
intent.setAction(SomeActivity.MyBroadcastReceiver.ACTION);
intent.putExtra("dataToPass", test);
context.sendBroadcast(intent);
}
}
Try this..
public class TestClass{
interface Implementable{
public void passData(String text);
}
Implementable imple;
String text = "Test";
public TestClass(Context context){
startActivity(new Intent(context, SomeActivity.class));
}
private void sendToSomeActivity(){
if(imple != null){
imple.passData(text);
}
}
public void setListener(Implementable im){
imple = im;
}
}
class SomeActivity implements Implementable{
new TestClass().setListener(this);
#override
public void passData(String text){
//here is your text
}
}
In your java class create an interface like this
public class TestClass{
private MyInterface myInterface;
public interface OnSendSomething {
public void onSending(String sendWhateverYouWant);
}
public void setOnSendListener(MyInterface myInterface) {
this.myInterface = myInterface;
}
}
private void sendToSomeActivity(){
//Call some method of SomeActivity and pas text as string
myInterface.onSending(sendWhateverYouWant);
}
And in your activity do something like this:
TestClass tclass = new TestClass(context);
tclass.setOnSendListener(new OnSendSomething () {
#Override
public void onSending(String sendWhateverYouWant) {
//sendWhateverYouWant is here in activity
}
});
You can also visit these links for better understanding.
How to create our own Listener interface in android?
Observer Design Pattern in Java

starting BroadcastReceiver or IntentService from non-activity class

How to start BroadcastReceiver or IntentService from non-activity class
by start I mean send intent and make run BroadcastService or IntentService
I.e:
I have class:
public class NumberOne{
#Override
public int functionOne(){
int i = 1 + 4;
if(/*something is true*/){
Intent intent = new Intent(this,intetServiceOne.class);
intent.putExtra("id","path");
context.startService(intent);
}
else {/*continue*/
}
return i;
}
//other functions
}
and if a condition in functionOne is true start IntentService
public class IntentServiceClassOne extends IntentService {
public IntentServiceClassOne () {
super("IntentServiceClassOne ");
}
#Override
protected void onHandleIntent(Intent intent) {
String data = intent.getStringExtra("id");
Log.d("dataIs: ", data);
}
//more functions what to do
}
It dont depend if it is IntentService or BroadcastReceiver
Thanks
To start service You need context instance. You can pass it as constructor parameter:
public class NumberOne{
Context context;
public NumberOne(Context context){
this.context = context;
}
public int functionOne(Context context){
int i = 1 + 4;
if(/*something is true*/){
Intent intent = new Intent(this,intetServiceOne.class);
intent.putExtra("id","path");
context.startService(intent);
}
else {/*continue*/
}
return i;
}
//other functions
}
You don't have to pass Activity instance, Context is enough. It can be application context. You can get it by getApplicationContext() method
You can also create static instance in Application object and get it from them:
public class YourApplication extends Application {
public static YourApplication INSTANCE;
public void onCreate(){
super.onCreate();
INSTANCE = this;
}
}
And your class will be look like below.
public class NumberOne{
public int functionOne(Context context){
int i = 1 + 4;
if(/*something is true*/){
Intent intent = new Intent(this,intetServiceOne.class);
intent.putExtra("id","path");
YourApplication.INSTANCE.startService(intent);
}
else {/*continue*/
}
return i;
}
//other functions
}
But is not good solution.
And the last you can create callback listener and set it in your class like below:
public class NumberOne{
//add setter
YourListener yourListener;
public int functionOne(Context context){
int i = 1 + 4;
if(/*something is true*/){
if(yourListener != null){
yourListener.onFunctionOneCall();
}
}
else {/*continue*/
}
return i;
}
//other functions
public interface YourListener{
void onFunctionOneCall();
}
}
And some place where you have context - for example in activity:
numberOneInstance.setYourListener(new YourListener(){
#Override
public void onFunctionOneCall(){
Intent intent = new Intent(this,intetServiceOne.class);
intent.putExtra("id","path");
this.startService(intent);
}
});
or you can set context by setter
public class NumberOne{
Context context;
public setContext(Context context){
this.context = context;
}
public int functionOne(Context context){
int i = 1 + 4;
if(/*something is true*/){
if(context != null){
Intent intent = new Intent(this,intetServiceOne.class);
intent.putExtra("id","path");
context.startService(intent);
}
}
else {/*continue*/
}
return i;
}
//other functions
}

Categories

Resources