I want to show a marker with the image of a profile picture using the Picasso Library.
I can't determine how. The userProfilePicture is the URL of the profile picture of the user, and I am storing on userProfilePictureReceived.
public class GoogleMaps extends Activity implements OnMapReadyCallback {
protected GoogleMap map;
protected String userNameReceived;
protected String userProfilePictureReceived;
protected Bitmap bmp;
protected BitmapDescriptor icon;
protected Canvas canvas1;
protected ImageView icon2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_maps);
MapFragment mapFragment = (MapFragment) getFragmentManager().findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
userNameReceived = MainActivity.userName;//using global variable userName from MainActivity class
userProfilePictureReceived = MainActivity.userProfilePicture;
// icon2 = (ImageView) findViewById(R.id.imageView2);
icon2.draw(canvas1);
Bitmap.Config conf = Bitmap.Config.ARGB_8888;
bmp = Bitmap.createBitmap(80, 80, conf);
canvas1 = new Canvas(bmp);
}
#Override
protected void onRestart() {
super.onRestart();
}
#Override
protected void onStart() {
Picasso.with(GoogleMaps.this)
.load(userProfilePictureReceived)
.resize(100, 100)
.config(Bitmap.Config.ARGB_4444)
// .error(R.drawable.abc_btn_radio_to_on_mtrl_015) // en caso de no tener imagen pone una predeterminada
.transform(new RoundedTransformation(50, 4))
.into(icon2);
icon2.draw(canvas1);
// BitmapDrawable drawable = (BitmapDrawable) icon2.getDrawable();
//userPictureAsGeoPoint = drawable.getBitmap();
//icon = BitmapDescriptorFactory.fromBitmap(userPictureAsGeoPoint);
super.onStart();
}
#Override
protected void onResume() {
super.onResume();
}
#Override
protected void onPause() {
super.onPause();
}
#Override
protected void onStop() {
super.onStop();
}
#Override
protected void onDestroy() {
super.onDestroy();
}
#Override
public void onMapReady(GoogleMap map) {
map.addMarker(new MarkerOptions()
.position(new LatLng(10, 10))
.title(userNameReceived))
.setIcon(BitmapDescriptorFactory.fromBitmap(bmp));
//marker.showInfoWindow
//marker.showInfoWindow
//setVisibility
}
}
Related
I want to show an indeterminate ProgressBar while running the code in my Asynctask, but (if I'm right) because I'm using the .get() function in the MainActivity the UI-thread freezes until the AsyncTask gives response and thus the ProgressBar won't get displayed. How can I make it so that the ProgressBar appears on screen while the UI-thread is waiting for the Asynctask to finish and return some value?
MainActivity
public class MainActivity extends AppCompatActivity {
ProgressBar progressBar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
progressBar = (ProgressBar) findViewById(R.id.progressBar);
}
public void showSpinner(View view){
CustomAsyncTask customAsyncTask = new CustomAsyncTask(this);
customAsyncTask.setProgressBar(progressBar);
try {
String message = customAsyncTask.execute().get();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
Toast.makeText(this,
"Time is up", Toast.LENGTH_LONG).show();
}}
AsyncTask
public class CustomAsyncTask extends android.os.AsyncTask<Void, Void, String> {
Context context;
CustomAsyncTask(Context ctx) {
context = ctx;
}
ProgressBar progressBar;
public void setProgressBar(ProgressBar progressBar) {
this.progressBar = progressBar;
}
#Override
protected String doInBackground(Void... voids) {
SystemClock.sleep(2000);
String message = "hello world";
return message;
}
#Override
protected void onPreExecute() {
progressBar.setVisibility(View.VISIBLE);
}
#Override
protected void onPostExecute(String message) {
progressBar.setVisibility(View.GONE);
}}
Try to run AsyncTask without .get().
You can use interface (see original answer):
Your interface:
public interface OnTaskCompleted{
void onTaskCompleted();
}
Your Activity:
public MainActivity extends AppCompatActivity implements OnTaskCompleted{
//your MainActivity
}
And your AsyncTask:
public class CustomAsyncTask extends android.os.AsyncTask<Void, Void, String> {
private OnTaskCompleted listener;
public CustomAsyncTask(OnTaskCompleted listener){
this.listener=listener;
}
//required methods
protected void onPostExecute(Object o){
//your stuff
listener.onTaskCompleted();
}
}
Another way is add setter for message in MainActivity:
public class MainActivity extends AppCompatActivity {
//...
private String message;
public void setMessage(String message) {
this.message = message;
}
// ...
customAsyncTask.execute();
Then just update message in .onPostExecute() in CustomAsyncTask:
public class CustomAsyncTask extends android.os.AsyncTask<Void, Void, String> {
//...
#Override
protected void onPostExecute(String message) {
progressBar.setVisibility(View.GONE);
MainActivity activity = (MainActivity) context;
activity.setMessage(message);
}
I just updated my project from MvvmCross 3.5.1 stable to 4.2.2. After fixing some other runtime exceptions that popped up after the update, I'm stuck with this one.
I am inflating a layout in an MvxFragment:
_rootView = this.BindingInflate(Resource.Layout.my_layout, null);
This throws a Java.Lang.ClassNotFoundException for Mvx.MvxLinearLayout. With the messages:
Binary XML file line #1: Error inflating class Mvx.MvxLinearLayout
Didn't find class \"Mvx.MvxLinearLayout\" on path: DexPathList[[zip file \"/data/app/com.myapp…
I have already installed the MvvmCross.Binding nuget package.
I the following base activity (which worked fine on 3.5.1):
MvxActionBarActivity
/// <summary>
/// Mvx support for the native ActionBarActivity
/// </summary>
public abstract class MvxActionBarActivity
: MvxActionBarEventSourceActivity
, IMvxAndroidView
{
protected MvxActionBarActivity()
{
BindingContext = new MvxAndroidBindingContext(this, this);
this.AddEventListeners();
}
public object DataContext
{
get { return BindingContext.DataContext; }
set { BindingContext.DataContext = value; }
}
public IMvxViewModel ViewModel
{
get { return DataContext as IMvxViewModel; }
set
{
DataContext = value;
OnViewModelSet();
}
}
public void MvxInternalStartActivityForResult(Intent intent, int requestCode)
{
base.StartActivityForResult(intent, requestCode);
}
public IMvxBindingContext BindingContext { get; set; }
public override void SetContentView(int layoutResId)
{
var view = this.BindingInflate(layoutResId, null);
SetContentView(view);
}
protected virtual void OnViewModelSet()
{
}
MvxActionBarEventSourceActivity
public class MvxActionBarEventSourceActivity : AppCompatActivity
, IMvxEventSourceActivity
{
protected override void OnCreate(Bundle bundle)
{
CreateWillBeCalled.Raise(this, bundle);
base.OnCreate(bundle);
CreateCalled.Raise(this, bundle);
}
protected override void OnDestroy()
{
DestroyCalled.Raise(this);
base.OnDestroy();
}
protected override void OnNewIntent(Intent intent)
{
base.OnNewIntent(intent);
NewIntentCalled.Raise(this, intent);
}
protected override void OnResume()
{
base.OnResume();
ResumeCalled.Raise(this);
}
protected override void OnPause()
{
PauseCalled.Raise(this);
base.OnPause();
}
protected override void OnStart()
{
base.OnStart();
StartCalled.Raise(this);
}
protected override void OnRestart()
{
base.OnRestart();
RestartCalled.Raise(this);
}
protected override void OnStop()
{
StopCalled.Raise(this);
base.OnStop();
}
public override void StartActivityForResult(Intent intent, int requestCode)
{
StartActivityForResultCalled.Raise(this, new MvxStartActivityForResultParameters(intent, requestCode));
base.StartActivityForResult(intent, requestCode);
}
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
ActivityResultCalled.Raise(this, new MvxActivityResultParameters(requestCode, resultCode, data));
base.OnActivityResult(requestCode, resultCode, data);
}
protected override void OnSaveInstanceState(Bundle outState)
{
SaveInstanceStateCalled.Raise(this, outState);
base.OnSaveInstanceState(outState);
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
DisposeCalled.Raise(this);
}
base.Dispose(disposing);
}
public event EventHandler DisposeCalled;
public event EventHandler<MvxValueEventArgs<Bundle>> CreateWillBeCalled;
public event EventHandler<MvxValueEventArgs<Bundle>> CreateCalled;
public event EventHandler DestroyCalled;
public event EventHandler<MvxValueEventArgs<Intent>> NewIntentCalled;
public event EventHandler ResumeCalled;
public event EventHandler PauseCalled;
public event EventHandler StartCalled;
public event EventHandler RestartCalled;
public event EventHandler StopCalled;
public event EventHandler<MvxValueEventArgs<Bundle>> SaveInstanceStateCalled;
public event EventHandler<MvxValueEventArgs<MvxStartActivityForResultParameters>> StartActivityForResultCalled;
public event EventHandler<MvxValueEventArgs<MvxActivityResultParameters>> ActivityResultCalled;
}
Switching my base activity to MvxAppCompatActivity fixed the issue.
I need to update my GUI based on client input. Calling my controller class method, from the background task works. But it can't update the GUI, because it is not the JavaFX application thread..please help.
I tried many of the related Q & A, but I am still confused.
Should I use Platform. runLater or Task ?
Here's my class where I create an instance of controller class
public class FactoryClass {
public static Controller_Gui1 createGUI() {
FXMLLoader fxLoader = new FXMLLoader();
fxLoader.setLocation(MainApp_Gui1.class.getResource("/com/Gui_1.fxml"));
AnchorPane anchorPane = null;
try {
anchorPane = (AnchorPane) fxLoader.load();
} catch (IOException e) {
e.printStackTrace();
}
Controller_Gui1 controller_Gui1 = (Controller_Gui1) fxLoader
.getController();
Scene scene = new Scene(anchorPane);
//System.out.println(scene);
controller_Gui1.setScene(scene);
return controller_Gui1;
}
}
Controller class
#FXML
Button B1 = new Button();
#FXML
public void handleButton1() {
B1.setDisable(true);
}
Application class
public class MainApp_Gui1 extends Application {
Controller_Gui1 cGui;
#Override
public void start(Stage primaryStage) throws Exception {
initScene(primaryStage);
primaryStage.show();
System.out.println("asdasd");
SceneSetting sceneSetting = new SceneSetting();
//handleEvent();
System.out.println("after");
sceneSetting.setSceneAfter();
System.out.println("after2");
}
// creating scene
private void initScene(Stage primaryStage) throws IOException {
primaryStage.setScene(getScene(primaryStage));
}
public Scene getScene(Stage primaryStage) {
Controller_Gui1 cGui;
cGui = FactoryClass.createGUI();
return cGui.getScene();
}
public void ExcessFromOutside() {
Platform.runLater(new Runnable() {
public void run() {
System.out.println(Platform.isFxApplicationThread());
cGui.handleButton1();
}
});
}
public static void main(String[] args) {
launch(args);
}
}
I want to call ExcessFromOutside() method from another thread.
I got a null pointer exception while trying to update the GUI
Here's my application class
public class MainAppGui1 extends Application {
Controller_Gui1 controller_Gui1;
#Override
public void start(Stage primaryStage) throws Exception {
initScene(primaryStage);
primaryStage.show();
}
// creating scene
public void initScene(Stage primaryStage) throws IOException {
FXMLLoader fxLoader = new FXMLLoader();
fxLoader.setLocation(MainApp_Gui1.class.getResource("/com/Gui_1.fxml"));
AnchorPane anchorPane=new AnchorPane();
anchorPane = (AnchorPane) fxLoader.load();
Controller_Gui1 controller_Gui1 = (Controller_Gui1) fxLoader.getController();
Scene scene = new Scene(anchorPane);
primaryStage.setScene(scene);
}
#FXML
public void ExcessFromOutside()
{
Platform.runLater(new Runnable() {
#Override
public void run() {
System.out.println("called atleast");
controller_Gui1.handleButton1();
}
});
}
public static void main(String[] args) {
launch(args);
}
}
and this is the class from where i tried to update the GUI
public class Hudai {
public static void main(String args[]) throws InterruptedException
{
new Thread()
{
public void run()
{
MainAppGui1.main(null);
}
}.start();
Thread.sleep(5000);
MainAppGui1 m = new MainAppGui1();
m.ExcessFromOutside();
}
}
To disable your button in a different thread you can use Task's updateValue.
Task<Boolean> task = new Task<Boolean>() {
#Override
public Boolean call() {
... // The task that this thread needs to do
updateValue(true);
...
return null;
}
};
button.disableProperty().bind(task.valueProperty());
If you want to use a new thread to call a method, which alters the scene graph, the best chance you have is to use Platform.runLater() in it.
//code inside Thread
...
// code to run on the JavaFX Application thread
Platform.runLater(new Runnable() {
#Override
public void run() {
handleButton1();
}
});
...
You should get a NullPointerException when you run this program.
The problem is, the member of MainApp_Gui1
Controller_Gui1 cGui;
never gets a value.
Remove line "Controller_Gui1 cGui;" from this code:
public Scene getScene(Stage primaryStage) {
// Hudai hudai = new Hudai(primaryStage);
// return hudai.getScene();
Controller_Gui1 cGui;
cGui = FactoryClass.createGUI();
return cGui.getScene();
}
public class MainActivity extends Activity {
TextView statustv = (TextView) findViewById(R.id.status);;
ProgressDialog pd;
String status, url = "http://wvde.state.wv.us/closings/county/monongalia";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new School().execute();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
private class School extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
pd = new ProgressDialog(MainActivity.this);
pd.setTitle("Android Basic JSoup Tutorial");
pd.setMessage("Loading...");
pd.setIndeterminate(false);
pd.show();
}
#Override
protected Void doInBackground(Void... params) {
try {
Document doc = Jsoup.connect(url).get();
Elements table = doc.select("td#content_body");
status = table.select("table").text();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void result) {
statustv.setText(status);
pd.dismiss();
}
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_refresh) {
new School().execute();
return true;
}
return super.onOptionsItemSelected(item);
}
}
How can I have new School().execute(); happen oncreate without getting a nullpointer error because right now when oncreate executes it executes new School().execute(); before it even knows what the asynchtask is. How can i have it execute correctly oncreate?
You can post a runnable to the current thread's handler. The runnable starts the AsyncTask.
Here is an easy example of using handler: https://stackoverflow.com/a/1921759/1843698
Official Doc for Handler: http://developer.android.com/reference/android/os/Handler.html
The handler schedule a task (your runnable) in current thread, and your task will be executed later in the same thread as soon as possible, but it will be executed after onCreate() finishes.
I am trying to pass message using handler to View class; but don't know where I am going wrong. Please correct me. I never used canvas to draw after getting values from Handler.
Thanks in advance!
My log-cat is showing NullPointerException on onDraw method after running this program.And hence line can not be drawn.
public class List extends Activity{
Handler handler=new Handler();
Message msg=new Message();
Bundle bundle=new Bundle();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new TestView(this));
bundle.putFloat("x1", 10);
bundle.putFloat("y1", 10);
bundle.putFloat("x2", 100);
bundle.putFloat("y2", 100);
msg.setData(bundle);
handler.sendMessage(msg);
}
}
class TestView extends View {
Paint p;
float x1;
float y1;
float x2;
float y2;
public TestView(Context context) {
super(context);
Paint p=new Paint();
p.setColor(Color.BLUE);
Handler handler=new Handler(){
#Override
public void handleMessage(Message msg) {
Looper.prepare();
Bundle bundle=msg.getData();
x1=bundle.getFloat("x1");
y1=bundle.getFloat("y1");
x2=bundle.getFloat("x2");
y2=bundle.getFloat("y2");
Looper.loop();
}
};
}
boolean isDrawing=true;
#Override
protected void onDraw(Canvas canvas) {
canvas.drawLine(x1, y1, x2, y2, p);
invalidate();
}
}
Handler is always attached to only one thread and unless and until we don't have thread, it can't work. i.e send or receive data between Main thread and background thread.
The correct program for View class should be as follows:
public class List extends Activity{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new TestView(this));
}
}
class TestView extends View {
Bitmap bitmap=Bitmap.createBitmap(1000, 1000, Config.ARGB_8888);
Canvas canvas=new Canvas(bitmap);
Paint p=new Paint();
Handler handler=new Handler(){
#Override
public void handleMessage(Message msg) {
p.setColor(Color.BLUE);
Bundle bundle=msg.getData();
String name=bundle.getString("Name");
Toast.makeText(getContext(), name, Toast.LENGTH_LONG).show();
}
};
public TestView(Context context) {
super(context);
Paint p=new Paint();
p.setColor(Color.BLUE);
new Thread(){
public void run(){
Message msg=new Message();
Bundle bundle=new Bundle();
Bundle bundle1=new Bundle();
Looper.prepare();
bundle.putString("Name", "Nishant");
bundle1.putString("Name", "Neha");
msg.setData(bundle);
handler.sendMessage(msg);
Message m1=new Message();
m1.setData(bundle1);
handler.sendMessage(m1);
}
}.start();
}
#Override
protected void onDraw(Canvas canvas) {
}
}