I try to implement a timer using Work Manager.
"Timer button was hit" is appear in logcat, but nothing comes from worker. What I do wrong?
This is my ViewModel class:
public class MainViewModel extends ViewModel {
public static final String LOG_TAG = "MainActivity";
private final WorkManager workManager;
public MainViewModel(WorkManager workManager) {
this.workManager = workManager;
}
public void count() {
Log.d(LOG_TAG, "Timer button was hit!");
OneTimeWorkRequest request = new OneTimeWorkRequest.Builder(MainWorker.class).build();
workManager.beginUniqueWork("count-work", ExistingWorkPolicy.APPEND, request).enqueue();
}
}
This is my worker. Nothing appear in logcat from here. I don't know why.
public class MainWorker extends Worker {
public MainWorker(#NonNull Context context, #NonNull WorkerParameters workerParams) {
super(context, workerParams);
Log.d(MainViewModel.LOG_TAG, "Created");
}
#NonNull
#Override
public Result doWork() {
Log.d(MainViewModel.LOG_TAG, "Work start");
return Result.success();
}
}
This is my activity:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MainViewModel viewModel = new MainViewModel(WorkManager.getInstance(this));
ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
binding.setMainViewModel(viewModel);
}
}
ViewModels are not initialized the way you did. If you have to pass something to ViewModel constructor, you should probably consider using ViewModelProvider.Factory().
You can make your own ViewModelProvider.Factory()
Refer this, https://medium.com/koderlabs/viewmodel-with-viewmodelprovider-factory-the-creator-of-viewmodel-8fabfec1aa4f#:~:text=And%20it%20is%20because%20you,it%20will%20create%20your%20ViewModel.
Related
I have two classes corresponding to two activities in my code.
What I would like, is that the functions in the class of the activity B is launched in the activity A, but without showing the activity : I would just like the code to be executed...
How can I launch the functions of the activity B in background from the activity A?
I read to use Services, but I don't know at all how to use them, I don't see so many reading about it. I don't know if it is the good way.
I tried this with no success: startService(new Intent(this, HereMap.class));
Activity A:
public class LoginActivity extends AppCompatActivity {
#Override
protected void onResume(){
...
//Code to execute the activity B in background
Intent activityB= new Intent(this, HereMap.class);
activityB.onDownloadButtonClicked(); //=> here is the execution but doesn't work...
}
#Override
protected void onCreate(Bundle savedInstanceState) {
...
}
Activity B:
public class HereMap extends AppCompatActivity {
...
private MapLoader.Listener mapLoaderHandler = new MapLoader.Listener() {
#Override
public void onProgress(int progress) {
Log.i(TAG, "Progress " + progress + "%");
downloadProgressBar.setProgress(progress);
}
#Override
public void onInstallationSize(long diskSize, long networkSize) {
Log.i(TAG, "Map data require " + diskSize);
}
#Override
public void onGetMapPackagesComplete(MapPackage rootMapPackage,
MapLoader.ResultCode resultCode) {
if (resultCode == MapLoader.ResultCode.OPERATION_SUCCESSFUL) {
Log.i(TAG, "Map packages received successful: " + rootMapPackage.getTitle());
currentInstalledMaps = new ArrayList<>(1);
populateInstalledMaps(rootMapPackage);
} else {
Log.e(TAG, "Can't retrieve map packages: " + resultCode.name());
Toast.makeText(HereMap.this,
"Error: " + resultCode.name(), Toast.LENGTH_SHORT).show();
return;
}
...
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Init map
setContentView(R.layout.activity_here_map);
mapFragment = (AndroidXMapFragment) getSupportFragmentManager().findFragmentById(R.id.mapfragment);
...
public void onDownloadButtonClicked() {
Log.d(TAG, "Downloading new map data...");
List<Integer> downloadList = new ArrayList<>(1);
downloadList.add(120214); //Id:120002 Berlin Id:120214, Name: Andalucia, Size:231504 Cherche l'id avec l'application iOS map-downloader-ios-swift
downloadProgressBar.setProgress(0);
downloadProgressBar.setVisibility(View.VISIBLE);
MapLoader.getInstance().installMapPackages(downloadList);
}
If you have some function you want to use in multiple Activities, you can put it in its own class and instantiate that class in whatever place you need to call its methods. The created class should not extend Activity or Fragment if it isn't actually an Activity or Fragment (this will cause all sorts of bugs). If it needs access to a Context or other Android component, you could pass those in at construction or to the methods that need it.
If you need your helper class to interact with its hosting activity (e.g. show or hide views, send data to views, etc) you can define interfaces on the helper or pass the views in directly.
If you define interfaces on your helper class you can use those to "call back" to whatever activity is hosting it (e.g. to show a progress bar). If you don't want to use an interface you could just pass the view to the helper class too, but the interface approach is sometimes more flexible.
Here are examples of both approaches:
Using an Interface
public class MapHelper {
public interface ProgressBarHolder {
void showBar();
}
private ProgressBarHolder progress;
MapHelper(ProgressBarHolder prog) {
progress = prog;
}
public void onDownloadButtonClicked() {
List<Integer> downloadList = new ArrayList<>(1);
downloadList.add(120214);
progress.showBar();
MapLoader.getInstance().installMapPackages(downloadList);
}
}
then you can call it from any Activity, like this
public class MyActivity extends AppCompatActivity
implements MapHelper.ProgressBarHolder
{
private MapHelper helper = new MapHelper(this);
private ProgressBar bar;
#Override
public void showBar() {
// show a progress bar, MapHelper will call this
// when it needs the current activity to show a progress bar
bar.setProgress(0);
bar.setVisibility(View.VISIBLE);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// set up stuff
bar = findViewById(R.id.progress);
bar.setVisibility(View.GONE);
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
helper.onDownloadButtonClicked();
}
});
}
}
Passing in Views
public class MapHelper {
private ProgressBar progress;
MapHelper(ProgressBar prog) {
progress = prog;
}
public void onDownloadButtonClicked() {
List<Integer> downloadList = new ArrayList<>(1);
downloadList.add(120214);
progress.setProgress(0);
progress.setVisibility(View.VISIBLE);
MapLoader.getInstance().installMapPackages(downloadList);
}
}
then you can call it from any Activity, like this
public class MyActivity extends AppCompatActivity {
private MapHelper helper;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// set up stuff
ProgressBar bar = findViewByid(R.id.progress);
bar.setVisibility(View.GONE);
// Wait to create the helper until you have the views
helper = new MapHelper(bar);
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
helper.onDownloadButtonClicked();
}
});
}
}
I have an Activity which creates a class that does some work. What is the typical Android method of having this class report back to the Activity in order to update the UI?
My activity, which creates the class:
public class MainActivity extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MyClass obj = new MyClass(this);
obj.DoWork();
}
}
The class that does the work, and wants to report back some
public class MyClass(Context context) {
private Context context;
public void DoWork() {
//Do some work with a countdown timer
//Report back some values
}
}
You can create your own interface like this:
public class MainActivity extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MyClass obj = new MyClass(this);
obj.setOnWorkDoneListener(new MyClass.OnWorkDoneListener(){
#Override
public void onDone(Values values) {
//Work done, use values
updateUI(values);
}
});
obj.DoWork();
}
}
public class MyClass(Context context) {
private Context context;
public interface OnWorkDoneListener{
void onDone(Values values);
}
private OnWorkDoneListener listener;
public void setOnWorkDoneListener(OnWorkDoneListener listener){
this.listener = listener;
}
public void DoWork() {
//Do some work with a countdown timer
when(workEnded) listener.onDone(backValues);
}
}
I am trying to use a fix from this GitHub issue, but when using the solution in my code, this is not available. How can I pass this to the function?
´´´java
public class MainActivity extends ReactActivity {
#Override
protected String getMainComponentName() {
return "fleeting";
}
private ReactContext mReactContext;
private PowerManager.WakeLock sCpuWakeLock;
private Activity activity;
private static final String TAG = "MainActivity";
public void onReactContextInitialized(ReactContext context) {
Log.d(TAG, "Here's your valid ReactContext");
mReactContext = context;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
getReactInstanceManager().addReactInstanceEventListener(this); // Throws error, can´t find "this"
Replace you first line with below code. You were not implemented the ReactInstanceEventListener interface.
public class MainActivity extends ReactActivity implements ReactInstanceManager.ReactInstanceEventListener{
Then add this method inside your mainActivity.
#Override
public void onReactContextInitialized(ReactContext context) {
Log.d(TAG, "Here's your valid ReactContext");
}
I am developing an Android app and thus, I have a MainActivity class. Inside of that MainActivity class, I have a method, let's call it doSomething():
public class MainActivity extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void doSomething(){
// bla bla bla
}
}
I also have a different class (with different layout) that is called OtherActivity. I want to use the doSomething method inside it:
public class OtherActivity extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.other_activity_layout);
// Let's use doSomething()
}
}
I tried this:
public class OtherActivity extends AppCompatActivity {
MainActivity main;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.other_activity_layout);
// Let's use doSomething()
MainActivity main = new MainActivity();
main.doSomething();
}
}
But it does not work. I also tried to make OtherActivity to extend the MainActivity, doing the following:
public class OtherActivity extends MainActivity{
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.other_activity_layout);
// Let's use doSomething()
super.doSomething();
}
}
But it does not allow me to initialize the layout...
How can I do?
Thanks in advance.
To communicate between to Activity Broadcast is the best way, and for the same application, we can use local broadcast using LocalBroadcastManager.
First, we should register one broadcast in MainActivity,
public class MainActivity1 extends AppCompatActivity {
public static final String INTENT_FILTER = "do_some_action";
public static final String INTENT_BUNDLE_VALUE = "value1";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main1);
LocalBroadcastManager.getInstance(this).registerReceiver(
mChangeListener, new IntentFilter(INTENT_FILTER));
}
#Override
protected void onDestroy() {
super.onDestroy();
LocalBroadcastManager.getInstance(this).unregisterReceiver(mChangeListener);
}
private BroadcastReceiver mChangeListener = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intentData) {
// you can do anything here
if (intentData != null && intentData.hasExtra(INTENT_BUNDLE_VALUE)) {
String value = intentData.getStringExtra(INTENT_BUNDLE_VALUE);
doSomeAction(value);
}
}
};
private void doSomeAction(String value) {
}
}
Then to do some action in MainActivity from OtherActivity, we can send Local broadcast from OtherActivity it will reach the receiver of Which we register in MainActivity,
public class OtherActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_other);
// You can call MainActivity to do some actions
Intent intent = new Intent(MainActivity1.INTENT_FILTER);
intent.putExtra(MainActivity1.INTENT_BUNDLE_VALUE, "Any string or any value");
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
}
Done!!!.
Something like this should do the trick, I'm going to make a static navigator to handle your navigation logic. If you are opposed to static methods you could also make them on your Application object to make it easier to manage dependencies, I'm just making it static for simplicity.
//Making this fully static for simplicity, this is fine for a small app
//you can make it a singleton on the application class for more flexibility
public class Navigator {
//static member vars that determine navigation
// pass in Context if needed for navigation purposes
public static void doSomething(Context context){
// bla bla bla
}
}
public class MainActivity extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity_layout);
}
private void doSomething() {
Navigator.doSomething(this);
}
}
public class OtherActivity extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.other_activity_layout);
}
private void doSomething() {
Navigator.doSomething(this);
}
}
I extended to Application class with my own data class. It is used to store global objects in my app and make them accessible by all Acitivites. I would like this class, when initialized on application run, to download data from the internet via AsyncTask. How can I show/hide a ProgressDialog within AsyncTask, which requires me to pass the correct Context/Activity to it?
public class DataSource extends Application{
private int userid;
private Object[] orders;
//initialize
#Override
public void onCreate() {
// Pull data from the internet and store it in orders
super.onCreate();
}
public void beginDataLoad(Activity callingActivity) {
// HOW DO I PASS THE CORRECT ACTIVITY TO MY NEW downloadData OBJECT?
downloadData task = new downloadData(callingActivity);
task.execute(new String[] { "http://www.myurl.com" });
}
private class downloadData extends AsyncTask<String, Void, String>{
private ProgressDialog progressDialog;
private MainActivity activity;
public downloadData(MainActivity activity) {
this.activity = activity;
this.progressDialog = new ProgressDialog(activity);
}
protected void onPreExecute() {
progressDialog.setMessage("Downloading events...");
progressDialog.show();
}
protected String doInBackgroun(String... params) {
// Do AsyncTask download functions in background...
}
protected void onPostExecute() {
progressDialog.dismiss();
//Callback function in MainActivity to indicate data is loaded
activity.dataIsLoaded();
}
}
}
I ended up calling the datasource load from my MainActivity this way.
public class MainActivity extends Activity {
//onclick function...
myDataSource = (DataSource)getApplicationContext();
myDataSource.beginDataLoad(MainActivity.this);
//Callback for AsyncTask to call when its completed
public void dataIsLoaded() {
//Do stuff once data has been loaded
}
}