I want my app support 2 language, en and it, so I create a Switch to change the locale in the mainActivity.
The idea is to change Locale and restart the activity passing the new language.
I use API 28 to support more devices.
I tried this but it doesn't work.
Sometimes change the locale but only once.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
activityContext = this.getApplicationContext();
setContentView(R.layout.activity_main);
language = findViewById(R.id.language);
String lan = getIntent().getStringExtra("lan");
if(lan != null) {
if(lan.equals("ita")) {
language.setChecked(true);
lang = "ita";
}else lang = "eng";
}else if(Locale.getDefault().toString().startsWith("it")){
language.setChecked(true);
lang = "ita";
}
buttonPlay.setOnClickListener(view -> enterRoom());
language.setOnCheckedChangeListener((compoundButton, b) -> {
lang = b? "ita" : "eng";
setLocale(lang);
});
}
private void setLocale(String lang){
Locale locale = new Locale(lang.substring(0, 2));
Locale.setDefault(locale);
Resources resources = getResources();
Configuration configuration = resources.getConfiguration();
configuration.setLocale(locale);
getApplicationContext().createConfigurationContext(configuration);
Intent i = getIntent();
i.putExtra("lan",lang);
finish();
startActivity(i);
}
import android.content.Intent;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Bundle;
import android.widget.Button;
import android.widget.Switch;
import androidx.appcompat.app.AppCompatActivity;
import java.util.Locale;
public class MainActivity extends AppCompatActivity {
private Switch languageSwitch;
private String lang;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Get the language preference from the intent or default to the device locale
String lan = getIntent().getStringExtra("lan");
if (lan == null) {
lan = Locale.getDefault().getLanguage();
}
// Set the activity language based on the preference
lang = lan.equals("it") ? "it" : "en";
setLocale(lang);
// Set the activity layout
setContentView(R.layout.activity_main);
// Find views and set up click listeners
languageSwitch = findViewById(R.id.language_switch);
languageSwitch.setChecked(lang.equals("it"));
languageSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> {
lang = isChecked ? "it" : "en";
setLocale(lang);
});
Button playButton = findViewById(R.id.play_button);
playButton.setOnClickListener(v -> enterRoom());
}
private void setLocale(String lang) {
// Update the app's language configuration
Locale locale = new Locale(lang);
Locale.setDefault(locale);
Resources resources = getResources();
Configuration configuration = resources.getConfiguration();
configuration.setLocale(locale);
getBaseContext().getResources().updateConfiguration(configuration, getResources().getDisplayMetrics());
getApplicationContext().getResources().updateConfiguration(configuration, getResources().getDisplayMetrics());
// Restart the activity with the new configuration
Intent intent = new Intent(this, MainActivity.class);
intent.putExtra("lan", lang);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
}
private void enterRoom() {
// Start the room activity with the current language preference
Intent intent = new Intent(this, RoomActivity.class);
intent.putExtra("lan", lang);
startActivity(intent);
}
}
Try this sample code separatly and change it with your code.
After hours of trying, I finally fixed this using updateConfiguration even though it's deprecated
private void setLocale(String lang){
Locale.setDefault(new Locale(lang.substring(0, 2)));
Configuration configuration = new Configuration();
configuration.setLocale(locale);
getResources().updateConfiguration(configuration, getResources().getDisplayMetrics());
Intent i = getIntent();
i.putExtra("lan",locale);
finish();
startActivity(i);
}
Related
I have got a MainActivity which gets the current location on click of a button. In the activity, and the location is stored with three different methods in
SharedPreferences
An online SQL Database
In a text file on the device
I have another class to start a foreground service (ForegroundService.java) which starts with the click of another button in the MainAcivity and stops with a third button.
My plan is to have regular (1 hour interval) location updates using the ForegroundService and a JobService. So if we click on the StartService-button in the MainActivity the foreground service should start and regularly call the methods from the MainActivity: getCurrentGPSPosition (to get the location), and the three methods to store the information.
The MainActivity works fine. The ForegroundService can be started and stopped bud I do not know how to make it call the methods from the MainActivity.
Here is the code -
ForegroundService.java:
import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import androidx.annotation.Nullable;
import androidx.core.app.NotificationCompat;
import static com.example.currentlocation.App.CHANNEL_ID;
public class ForegroundService extends Service {
#Override
public void onCreate() {
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
//String input = intent.getStringExtra("inputExtra");
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this,
0, notificationIntent, 0);
Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("GPS position tracker")
//.setContentText(input)
.setSmallIcon(R.drawable.ic_baseline_gps_fixed_24)
.setContentIntent(pendingIntent)
.build();
startForeground(1, notification);
return START_NOT_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
App.java
import android.app.Application;
import android.app.NotificationChannel;
import android.app.NotificationManager;
public class App extends Application {
public static final String CHANNEL_ID = "CurrentLocationServiceChannel";
#Override
public void onCreate() {
super.onCreate();
createNotificationChannel();
}
private void createNotificationChannel(){
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
NotificationChannel serviceChannel = new NotificationChannel(
CHANNEL_ID,
"Current Location Service Channel",
NotificationManager.IMPORTANCE_DEFAULT
);
NotificationManager manager = getSystemService(NotificationManager.class);
manager.createNotificationChannel(serviceChannel);
}
}
}
In the MainActivity the following parts:
public class MainActivity extends AppCompatActivity {
........
//Backgroundservice
public void startService(View v){
// String input = editTextInput.getText().toString();
Intent serviceIntent = new Intent(this, ForegroundService.class);
// serviceIntent.putExtra("inputExtra", input);
startService(serviceIntent);
}
public void stopService(View v){
Intent serviceIntent = new Intent(this, ForegroundService.class);
stopService(serviceIntent);
}
//Method to store in SQL online
public void OnReg() {.......code....}
//Method to save data in SharedPreferences
public void saveData() {.......code....}
//Method to save data in Internal File
public void saveToFile() {.......code....}
//method for GPS request
getCurrentGPSLocation() {.......code....}
}
Has anybody got an idea how to work that out? Or do you need more details? Thanks for your help!
Don't put those functions in MainActivity. If you need them to be called from both the Activity and a Service, put them in a separate class that can be instantiated as needed. If you can't do that because there's data in MainActivity that both need, rethink your architecture- that data won't be available when the job service fires anyway.
OK, first solution is to make a new class (Functions.java) and using an intent to call this class form the MainActivity and then do the location request there and then give the data back to the MainActivity.
Second step would then be to do the same from the foreground service.
The Problem is, the functions class does not get the data from the method. If I put hard-coded strings into the intent, they are transmitted to the MainActivity, so the intent works. So this is only part of the full solution.
Here's the code:
public class Functions extends AppCompatActivity {
//initialize variable
FusedLocationProviderClient fusedLocationProviderClient;
private double ser_Latitude;
private double ser_Longitude;
private String ser_Accuracy;
private String ser_Altitude;
private String currentDateandTime;
private String ser_Location;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Boolean precision = getIntent().getBooleanExtra("precision", true);
fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(
Functions.this);
getCurrentGPSLocation();
Intent intent = new Intent();
intent.putExtra("latitude", ser_Latitude);
intent.putExtra("longitude", ser_Longitude);
intent.putExtra("accuracy", ser_Accuracy);
intent.putExtra("altitude", ser_Altitude);
intent.putExtra("location", ser_Location);
intent.putExtra("currentDateandTime", currentDateandTime);
setResult(RESULT_OK, intent);
Functions.this.finish();
}
//Force new GPS Location Request
private void getCurrentGPSLocation() {
// get the new location from the fused client
// update the UI - i.e. set all properties in their associated text view items
//Initialize new location request
LocationRequest locationRequest = new LocationRequest()
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
.setInterval(3000)
.setFastestInterval(2000)
.setNumUpdates(1)
;
//Initialize location call back
LocationCallback locationCallback = new LocationCallback() {
#Override
public void onLocationResult(LocationResult locationResult) {
//Initialize location1
Location location1 = locationResult.getLastLocation();
//Set latitude
ser_Latitude = location1.getLatitude();
//Set longitude
ser_Longitude = location1.getLongitude();
//Set Accuracy
double ser_accura1 = location1.getAccuracy();
ser_Accuracy = new DecimalFormat("##.##").format(ser_accura1) + " m";
//Set Altitude
double ser_altit1 = location1.getAltitude();
ser_Altitude = new DecimalFormat("##.##").format(ser_altit1) + " m";
//Get Adress
/* Geocoder geocoder = new Geocoder(getApplicationContext(), Locale.getDefault());
try {
List<Address> listAddresses = geocoder.getFromLocation(ser_Latitude, ser_Longitude, 1);
if (null != listAddresses && listAddresses.size() > 0) {
String _Location1 = listAddresses.get(0).getAddressLine(0);
//Set Location
//ser_Location = String.valueOf(_Location1);
}
} catch (IOException e) {
e.printStackTrace();
}*/
//Set location as hard-coded string for testing
ser_Location = "London";
//Set Update Time
SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy 'um ' HH:mm:ss z");
currentDateandTime = sdf.format(new Date());
}
};
//Request location updates
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
fusedLocationProviderClient.requestLocationUpdates(locationRequest
, locationCallback, Looper.myLooper());
}
}
The new GPS request is triggered as I can see running the app, but no information is delivered from the method getCurrentGPSLocation() to the intent, which I can see because even the hard-coded location string is not delivered.
This needs revision please.
The code is heavily borrowed from https://github.com/hastarin/android-udpsender and where his code is very versatile, I want a simple way to send a udp packet to an Arduino that will unlock a garage door.
Basically page one (MainActivity) has a big "Open" button and a small "Set Params" button. Page two (Main2Activity) is mostly the borrowed code with lots deleted and provides a way to input the IP address, port and the unlock code word. Currently there is "Send" button that sends the assembled udp packet to the client and it works as intended.
The issue is that I really don't want to have to access the second page regularly. I need the "sendData" routine in MainActivity to have access to the stored values for processing.
At this time, pressing the Send button on the MainActivity page results in:
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.os.Bundle.getString(java.lang.String)' on a null object reference
at com.kke.android.opener.MainActivity.sendData(MainActivity.java:47)
at com.kke.android.opener.MainActivity.onClick(MainActivity.java:30)
Which I take to mean that the the variable values are not available to the sendData routine on that page.
MainActivity
package com.kke.android.opener;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.app.Activity;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends Activity implements View.OnClickListener{
private View view;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btnsend = (Button) findViewById(R.id.buttonSend);
Button btnset = (Button) findViewById(R.id.buttonSet);
btnsend.setOnClickListener(this);
btnset.setOnClickListener(this);
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.buttonSend:
sendData(v);
break;
case R.id.buttonSet:
editParams(view);
break;
}
}
public void sendData(View view) {
Context context = getApplicationContext();
/**Load global variable from Main2Activity*/
Bundle bundle = getIntent().getExtras();
String host = bundle.getString("host");
String port = bundle.getString("port");
String dataText = bundle.getString("dataText");
//EditText editText = (EditText) findViewById(R.id.editTextIP);
//String host = editText.getText().toString();
if (!host.matches("\\b(?:\\d{1,3}\\.){3}\\d{1,3}\\b")) {
CharSequence text = "Error: Invalid IP Address";
Toast toast = Toast.makeText(context, text, Toast.LENGTH_SHORT);
toast.show();
return;
}
//editText = (EditText) findViewById(R.id.editTextPort);
//String port = editText.getText().toString();
if (!port.matches("^(6553[0-5]|655[0-2]\\d|65[0-4]\\d\\d|6[0-4]\\d{3}|[1-5]\\d{4}|[1-9]\\d{0,3}|0)$")) {
CharSequence text = "Error: Invalid Port Number";
Toast toast = Toast.makeText(context, text, Toast.LENGTH_SHORT);
toast.show();
return;
}
// editText = (EditText) findViewById(R.id.editTextData);
//String dataText = editText.getText().toString();
if (dataText.length() < 1 ) {
CharSequence text = "Error: Text required to send";
Toast toast = Toast.makeText(context, text, Toast.LENGTH_SHORT);
toast.show();
return;
}
String uriString = "udp://" + host + ":" + port + "/";
uriString += Uri.encode(dataText);
Uri uri = Uri.parse(uriString);
Intent intent = new Intent(Intent.ACTION_SENDTO, uri);
intent.addFlags(Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP);
intent.addCategory(Intent.CATEGORY_DEFAULT);
startActivity(intent);
}
/** Called when the user taps the Set Params button */
public void editParams(View view) {
Intent intent = new Intent(this, Main2Activity.class);
startActivity(intent);
}
}
Main2Activity
package com.kke.android.opener.ui;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Bundle;
import android.text.InputType;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ToggleButton;
import com.kke.android.opener.R;
public class Main2Activity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Restore preferences
SharedPreferences settings = getPreferences(0);
ToggleButton toggleButton = ((ToggleButton) findViewById(R.id.toggleButton));
boolean checked = settings.getBoolean("toggleChecked", false);
toggleButton.setChecked(checked);
toggleButton.setVisibility(View.GONE);
EditText editText = (EditText) findViewById(R.id.editTextIP);
if (checked) {
editText.setInputType(InputType.TYPE_CLASS_TEXT);
}
editText.setText(settings.getString("host", ""), TextView.BufferType.EDITABLE);
editText = (EditText) findViewById(R.id.editTextPort);
if (checked) {
editText.setInputType(InputType.TYPE_CLASS_TEXT);
}
editText.setText(settings.getString("port", ""), TextView.BufferType.EDITABLE);
editText = (EditText) findViewById(R.id.editTextData);
editText.setText(settings.getString("dataText", ""), TextView.BufferType.EDITABLE);
/** Set up global variable to pass to MainActivity */
Intent intent = new Intent(Main2Activity.this, MainActivity.class);
intent.putExtra("host", "host");
intent.putExtra("port", "port");
intent.putExtra("dataText", "dataText");
startActivity(intent);
}
#Override
public void onPause() {
super.onPause();
// Get current values
EditText editText = (EditText) findViewById(R.id.editTextIP);
String host = editText.getText().toString();
editText = (EditText) findViewById(R.id.editTextPort);
String port = editText.getText().toString();
editText = (EditText) findViewById(R.id.editTextData);
String dataText = editText.getText().toString();
// We need an Editor object to make preference changes.
// All objects are from android.context.Context
SharedPreferences settings = getPreferences(0);
SharedPreferences.Editor editor = settings.edit();
editor.putString("host", host);
editor.putString("port", port);
editor.putString("dataText", dataText);
editor.putBoolean("toggleChecked", ((ToggleButton) findViewById(R.id.toggleButton)).isChecked());
// Commit the edits!
editor.commit();
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle item selection
switch (item.getItemId()) {
case R.id.action_send:
this.sendData(null);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
public void sendData(View view) {
Context context = getApplicationContext();
EditText editText = (EditText) findViewById(R.id.editTextIP);
String host = editText.getText().toString();
if (!host.matches("\\b(?:\\d{1,3}\\.){3}\\d{1,3}\\b")) {
CharSequence text = "Error: Invalid IP Address";
Toast toast = Toast.makeText(context, text, Toast.LENGTH_SHORT);
toast.show();
return;
}
editText = (EditText) findViewById(R.id.editTextPort);
String port = editText.getText().toString();
if (!port.matches("^(6553[0-5]|655[0-2]\\d|65[0-4]\\d\\d|6[0-4]\\d{3}|[1-5]\\d{4}|[1-9]\\d{0,3}|0)$")) {
CharSequence text = "Error: Invalid Port Number";
Toast toast = Toast.makeText(context, text, Toast.LENGTH_SHORT);
toast.show();
return;
}
editText = (EditText) findViewById(R.id.editTextData);
String dataText = editText.getText().toString();
if (dataText.length() < 1 ) {
CharSequence text = "Error: Text/Hex required to send";
Toast toast = Toast.makeText(context, text, Toast.LENGTH_SHORT);
toast.show();
return;
}
String uriString = "udp://" + host + ":" + port + "/";
uriString += Uri.encode(dataText);
Uri uri = Uri.parse(uriString);
Intent intent = new Intent(Intent.ACTION_SENDTO, uri);
intent.addFlags(Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP);
intent.addCategory(Intent.CATEGORY_DEFAULT);
startActivity(intent);
}
public void onToggleClicked(View view) {
boolean on = ((ToggleButton) view).isChecked();
EditText editTextIp = (EditText) findViewById(R.id.editTextIP);
EditText editTextPort = (EditText) findViewById(R.id.editTextPort);
if (on) {
editTextIp.setInputType(InputType.TYPE_CLASS_TEXT);
editTextPort.setInputType(InputType.TYPE_CLASS_TEXT);
} else {
editTextIp.setInputType(InputType.TYPE_CLASS_PHONE);
editTextPort.setInputType(InputType.TYPE_CLASS_PHONE);
}
}
}
All suggestions will be appreciated.
Please remember I am very new to this.
Both of your Activities have the exact same layouts... That is probably confusing...
Anyways, you called getIntent().getExtras() when there was no extras to get (that activity just started).
Sample of your code
Bundle bundle = getIntent().getExtras();
String host = bundle.getString("host");
String port = bundle.getString("port");
String dataText = bundle.getString("dataText");
You can simply do this
Bundle extras = getIntent().getExtras();
// TODO: declare some variables here
String host, port, text;
if (extras != null) {
// TODO: assign your variables here
String host = extras.getString("host");
String port = extras.getString("port");
String dataText = extras.getString("dataText");
}
However, don't be surprised if you don't get anything because the intent could still be empty
What is happening is that your MainActivity is probably launched from the Android launcher and not from MainActivity2.
Basically when you click send, you inspect the intent that brought you here (to this activity). Since you came from the launcher, this intent does not have the data that you need to execute the function. Remember that you are setting the data for this intent in your MainActivity2 (on your oncreate method, which is kind of a bad practice in this context).
To fix this, go to the manifest and make your MainActivity2 your launcher activity:
<activity android:name="<YOUR_ACTIVITY_TWO_NAME">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
This will make sure that your Activity2 will be called first, this linking to MainActivity and sending an intent with actual data.
I've been able to successfully create an app (thanks davidgyoung!) that monitors beacons in the background and then subsequently opens the app in the background.
Now I would like my app to first prompt with a notification in the status bar saying something like "I've detected a beacon! Would you like to open out app?". Then the user would click on the notification to open the app or dismiss it and ignore the notification.
I've searched on stack overflow for something like but haven't had much success in finding something relevant to beacons. I did find this page that talks about adding StatusBar notifications but I'm not having much success.
Particularly its in my BeaconReferenceApplication.java and MonitoringActivity.java file. I think I put the code in the correct place (after didEnterRegion) but I have unresolved classes for areas like notificationButton, setLatestEventInfo, etc. Can someone help? Thanks in advance!
BeaconReferenceApplication.java:
import android.app.Application;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.TaskStackBuilder;
import android.content.Context;
import android.content.Intent;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import org.altbeacon.beacon.BeaconManager;
import org.altbeacon.beacon.BeaconParser;
import org.altbeacon.beacon.Identifier;
import org.altbeacon.beacon.Region;
import org.altbeacon.beacon.powersave.BackgroundPowerSaver;
import org.altbeacon.beacon.startup.RegionBootstrap;
import org.altbeacon.beacon.startup.BootstrapNotifier;
public class BeaconReferenceApplication extends Application implements BootstrapNotifier {
private static final String TAG = "BeaconReferenceApp";
private RegionBootstrap regionBootstrap;
private BackgroundPowerSaver backgroundPowerSaver;
private boolean haveDetectedBeaconsSinceBoot = false;
private MonitoringActivity monitoringActivity = null;
public void onCreate() {
super.onCreate();
BeaconManager beaconManager = org.altbeacon.beacon.BeaconManager.getInstanceForApplication(this);
// By default the AndroidBeaconLibrary will only find AltBeacons. If you wish to make it
// find a different type of beacon, you must specify the byte layout for that beacon's
// advertisement with a line like below. The example shows how to find a beacon with the
// same byte layout as AltBeacon but with a beaconTypeCode of 0xaabb. To find the proper
// layout expression for other beacon types, do a web search for "setBeaconLayout"
// including the quotes.
//
beaconManager.getBeaconParsers().clear();
beaconManager.getBeaconParsers().add(new BeaconParser().
setBeaconLayout("s:0-1=feaa,m:2-2=00,p:3-3:-41,i:4-13,i:14-19"));
Log.d(TAG, "setting up background monitoring for beacons and power saving");
// wake up the app when a beacon is seen
Region region = new Region("backgroundRegion", Identifier.parse("2F234454F4911BA9FFA6"), null, null);
regionBootstrap = new RegionBootstrap(this, region);
// simply constructing this class and holding a reference to it in your custom Application
// class will automatically cause the BeaconLibrary to save battery whenever the application
// is not visible. This reduces bluetooth power usage by about 60%
backgroundPowerSaver = new BackgroundPowerSaver(this);
// If you wish to test beacon detection in the Android Emulator, you can use code like this:
// BeaconManager.setBeaconSimulator(new TimedBeaconSimulator() );
// ((TimedBeaconSimulator) BeaconManager.getBeaconSimulator()).createTimedSimulatedBeacons();
}
#Override
public void didEnterRegion(Region arg0) {
// In this example, this class sends a notification to the user whenever a Beacon
// matching a Region (defined above) are first seen.
Log.d(TAG, "did enter region.");
if (!haveDetectedBeaconsSinceBoot) {
Log.d(TAG, "sending notification to StatusBar");
#SuppressWarnings("deprecation")
private void Notify(String notificationTitle, String notificationMessage) {
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
#SuppressWarnings("deprecation")
Notification notification = new Notification(R.mipmap.ic_launcher,
"New Message", System.currentTimeMillis());
Intent notificationIntent = new Intent(this, MonitoringActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
notificationIntent, 0);
notification.setLatestEventInfo(MonitoringActivity.this, notificationTitle,
notificationMessage, pendingIntent);
notificationManager.notify(9999, notification);
}
}
} else {
if (monitoringActivity != null) {
Log.d(TAG, "auto launching MainActivity");
// The very first time since boot that we detect an beacon, we launch the
// MainActivity
Intent intent = new Intent(this, MonitoringActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// Important: make sure to add android:launchMode="singleInstance" in the manifest
// to keep multiple copies of this activity from getting created if the user has
// already manually launched the app.
this.startActivity(intent);
haveDetectedBeaconsSinceBoot = true;
}
}
}
#Override
public void didExitRegion(Region region) {
if (monitoringActivity != null) {
Log.d(TAG,"I no longer see a beacon.");
}
}
#Override
public void didDetermineStateForRegion(int state, Region region) {
if (monitoringActivity != null) {
Log.d(TAG,"I have just switched from seeing/not seeing beacons: " + state);
}
}
private void sendNotification() {
NotificationCompat.Builder builder =
new NotificationCompat.Builder(this)
.setContentTitle("Beacon Reference Application")
.setContentText("An beacon is nearby.")
.setSmallIcon(R.mipmap.ic_launcher);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
stackBuilder.addNextIntent(new Intent(this, MonitoringActivity.class));
PendingIntent resultPendingIntent =
stackBuilder.getPendingIntent(
0,
PendingIntent.FLAG_UPDATE_CURRENT
);
builder.setContentIntent(resultPendingIntent);
NotificationManager notificationManager =
(NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(1, builder.build());
}
public void setMonitoringActivity(MonitoringActivity activity) {
this.monitoringActivity = activity;
}
}
MonitoringActivity.java:
import android.Manifest;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.os.Build;
import android.os.Bundle;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.util.Log;
import android.view.View;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;
import org.altbeacon.beacon.BeaconManager;
public class MonitoringActivity extends Activity {
protected static final String TAG = "MonitoringActivity";
private static final int PERMISSION_REQUEST_COARSE_LOCATION = 1;
private WebView mWebView;
ProgressBar progressBar;
#Override
protected void onCreate(Bundle savedInstanceState) {
Log.d(TAG, "onCreate");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_monitoring);
// code for button notification
Button notificationButton = (Button) findViewById(R.id.notificationButton);
notificationButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Notify("Title: Meeting with Business",
"Msg:Pittsburg 10:00 AM EST ");
}
});
// code for button notification
mWebView = (WebView) findViewById(R.id.activity_main_webview);
progressBar = (ProgressBar) findViewById(R.id.progressBar1);
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
mWebView.loadUrl("http://communionchapelefca.org/edy-home");
mWebView.setWebViewClient(new MyAppWebViewClient());
verifyBluetooth();
Log.d(TAG, "Application just launched");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// Android M Permission check
if (this.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("This app needs location access");
builder.setMessage("Please grant location access so this app can detect beacons in the background.");
builder.setPositiveButton(android.R.string.ok, null);
builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
#TargetApi(23)
#Override
public void onDismiss(DialogInterface dialog) {
requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION},
PERMISSION_REQUEST_COARSE_LOCATION);
}
});
builder.show();
}
}
}
private class HelloWebViewClient extends WebViewClient{
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
// TODO Auto-generated method stub
super.onPageStarted(view, url, favicon);
}
#Override
public boolean shouldOverrideUrlLoading(WebView webView, String url)
{
webView.loadUrl(url);
return true;
}
#Override
public void onPageFinished(WebView view, String url) {
// TODO Auto-generated method stub
super.onPageFinished(view, url);
progressBar.setVisibility(view.GONE);
}
}
#Override
public void onBackPressed() {
if(mWebView.canGoBack()) {
mWebView.goBack();
} else {
super.onBackPressed();
}
}
#Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case PERMISSION_REQUEST_COARSE_LOCATION: {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Log.d(TAG, "coarse location permission granted");
} else {
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Functionality limited");
builder.setMessage("Since location access has not been granted, this app will not be able to discover beacons when in the background.");
builder.setPositiveButton(android.R.string.ok, null);
builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialog) {
}
});
builder.show();
}
return;
}
}
}
public void onRangingClicked(View view) {
Intent myIntent = new Intent(this, RangingActivity.class);
this.startActivity(myIntent);
}
#Override
public void onResume() {
super.onResume();
((BeaconReferenceApplication) this.getApplicationContext()).setMonitoringActivity(this);
}
#Override
public void onPause() {
super.onPause();
((BeaconReferenceApplication) this.getApplicationContext()).setMonitoringActivity(null);
}
private void verifyBluetooth() {
try {
if (!BeaconManager.getInstanceForApplication(this).checkAvailability()) {
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Bluetooth not enabled");
builder.setMessage("Please enable bluetooth in settings and restart this application.");
builder.setPositiveButton(android.R.string.ok, null);
builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialog) {
finish();
System.exit(0);
}
});
builder.show();
}
}
catch (RuntimeException e) {
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Bluetooth LE not available");
builder.setMessage("Sorry, this device does not support Bluetooth LE.");
builder.setPositiveButton(android.R.string.ok, null);
builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialog) {
finish();
System.exit(0);
}
});
builder.show();
}
}
}
So I was able to fix my problem by using the example from the Android Developers website for Notifications. I used their sample code, adapted it to my use, and then even further used .bigText to make my notification look great. Credit goes to them and daviggyoung for getting my app working. Thanks!
I also didnt need to edit my MonitoringActivity.java like I posted earlier.
final BeaconReferenceApplication.java:
import android.app.Application;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.TaskStackBuilder;
import android.content.Context;
import android.content.Intent;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import android.widget.RemoteViews;
import org.altbeacon.beacon.BeaconManager;
import org.altbeacon.beacon.BeaconParser;
import org.altbeacon.beacon.Identifier;
import org.altbeacon.beacon.Region;
import org.altbeacon.beacon.powersave.BackgroundPowerSaver;
import org.altbeacon.beacon.startup.RegionBootstrap;
import org.altbeacon.beacon.startup.BootstrapNotifier;
public class BeaconReferenceApplication extends Application implements BootstrapNotifier {
private static final String TAG = "BeaconReferenceApp";
private RegionBootstrap regionBootstrap;
private BackgroundPowerSaver backgroundPowerSaver;
private boolean haveDetectedBeaconsSinceBoot = false;
private MonitoringActivity monitoringActivity = null;
public void onCreate() {
super.onCreate();
BeaconManager beaconManager = org.altbeacon.beacon.BeaconManager.getInstanceForApplication(this);
// By default the AndroidBeaconLibrary will only find AltBeacons. If you wish to make it
// find a different type of beacon, you must specify the byte layout for that beacon's
// advertisement with a line like below. The example shows how to find a beacon with the
// same byte layout as AltBeacon but with a beaconTypeCode of 0xaabb. To find the proper
// layout expression for other beacon types, do a web search for "setBeaconLayout"
// including the quotes.
//
beaconManager.getBeaconParsers().clear();
beaconManager.getBeaconParsers().add(new BeaconParser().
setBeaconLayout("s:0-1=feaa,m:2-2=00,p:3-3:-41,i:4-13,i:14-19"));
Log.d(TAG, "setting up background monitoring for beacons and power saving");
// wake up the app when a beacon is seen
Region region = new Region("backgroundRegion", Identifier.parse("2F234454F4911BA9FFA6"), null, null);
regionBootstrap = new RegionBootstrap(this, region);
// simply constructing this class and holding a reference to it in your custom Application
// class will automatically cause the BeaconLibrary to save battery whenever the application
// is not visible. This reduces bluetooth power usage by about 60%
backgroundPowerSaver = new BackgroundPowerSaver(this);
// If you wish to test beacon detection in the Android Emulator, you can use code like this:
// BeaconManager.setBeaconSimulator(new TimedBeaconSimulator() );
// ((TimedBeaconSimulator) BeaconManager.getBeaconSimulator()).createTimedSimulatedBeacons();
}
#Override
public void didEnterRegion(Region arg0) {
// In this example, this class sends a notification to the user whenever a Beacon
// matching a Region (defined above) are first seen.
Log.d(TAG, "did enter region.");
if (!haveDetectedBeaconsSinceBoot) {
Log.d(TAG, "sending notification to StatusBar");
//begin code for notification
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.notification_icon)
.setContentTitle("Message from Communion Chapel")
.setContentText("Welcome! Thanks for coming!")
.setStyle(new NotificationCompat.BigTextStyle()
.bigText("We noticed that you're here today, click here to open the app and get today's Sermon Notes and Bulletin."))
.setAutoCancel(true);
;
// Creates an explicit intent for an Activity in your app
Intent resultIntent = new Intent(this, MonitoringActivity.class);
// The stack builder object will contain an artificial back stack for the
// started Activity.
// This ensures that navigating backward from the Activity leads out of
// your application to the Home screen.
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
// Adds the back stack for the Intent (but not the Intent itself)
stackBuilder.addParentStack(MonitoringActivity.class);
// Adds the Intent that starts the Activity to the top of the stack
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent =
stackBuilder.getPendingIntent(
0,
PendingIntent.FLAG_UPDATE_CURRENT
);
mBuilder.setContentIntent(resultPendingIntent);
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// mId allows you to update the notification later on.
mNotificationManager.notify(123, mBuilder.build());
}
}
#Override
public void didExitRegion(Region region) {
if (monitoringActivity != null) {
Log.d(TAG,"I no longer see a beacon.");
}
}
#Override
public void didDetermineStateForRegion(int state, Region region) {
if (monitoringActivity != null) {
Log.d(TAG,"I have just switched from seeing/not seeing beacons: " + state);
}
}
private void sendNotification() {
NotificationCompat.Builder builder =
new NotificationCompat.Builder(this)
.setContentTitle("Beacon Reference Application")
.setContentText("A beacon is nearby.")
.setSmallIcon(R.drawable.app_icon);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
stackBuilder.addNextIntent(new Intent(this, MonitoringActivity.class));
PendingIntent resultPendingIntent =
stackBuilder.getPendingIntent(
0,
PendingIntent.FLAG_UPDATE_CURRENT
);
builder.setContentIntent(resultPendingIntent);
NotificationManager notificationManager =
(NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(1, builder.build());
}
public void setMonitoringActivity(MonitoringActivity activity) {
this.monitoringActivity = activity;
}
}
When i try to add the "Define the Remote Input" code to get voice input, it's giving me error in "reply_label" and "EXTRA_VOICE_REPLY" lines (tried to replace them, still error) :
package com.wear.myapp;
import android.app.Activity;
import android.app.Fragment;
import android.app.PendingIntent;
import android.content.Intent;
import android.os.Bundle;
import android.preview.support.v4.app.NotificationManagerCompat;
import android.preview.support.wearable.notifications.RemoteInput;
import android.support.v4.app.NotificationCompat;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
int notificationId = 001;
// Build intent for notification content
Intent viewIntent = new Intent(this, MainActivity.class);
viewIntent.putExtra("Helllo", "Hello Wear !");
PendingIntent viewPendingIntent =
PendingIntent.getActivity(this, 0, viewIntent, 0);
NotificationCompat.Builder notificationBuilder =
new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("My App")
.setContentText("Hello Wear !")
.setContentIntent(viewPendingIntent);
// Get an instance of the NotificationManager service
NotificationManagerCompat notificationManager =
NotificationManagerCompat.from(this);
// Build the notification and issues it with notification manager.
notificationManager.notify(notificationId, notificationBuilder.build());
if (savedInstanceState == null) {
getFragmentManager().beginTransaction()
.add(R.id.container, new PlaceholderFragment()).commit();
// Key for the string that's delivered in the action's intent
private static final String EXTRA_VOICE_REPLY = "extra_voice_reply";
String replyLabel = getResources().getString(R.string.reply_label);
RemoteInput remoteInput = new RemoteInput.Builder(EXTRA_VOICE_REPLY)
.setLabel(replyLabel)
.build();
}
}
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment {
public PlaceholderFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container,
false);
return rootView;
}
}
}
I again tried to solve it , but not solving, any solution ?
private static final String EXTRA_VOICE_REPLY = "extra_voice_reply"; is a constant declaration and cannot be placed here..
Move it in the line after MainActivity extends Activity, like this:
public class MainActivity extends Activity {
private static final String EXTRA_VOICE_REPLY = "extra_voice_reply";
// ...
You should also really read a basic java tutorial (for basic syntax)
I'm developing an Android Widget for an app, and the problem is I can't set onClickPendingIntent() on a button in a RemoteViewsFactory.
I explain: I created an AppWidgetProvider, which calls an extending of RemoteViewsService which calls an extending of RemoteViewsFactory for complete a ListView in my widget.
The RemoteViewsFactory have to return all items for update or create them and display on the widget. But for each items of the list view, I have 2 types of buttons:
A button which opens gmaps/dialer/sms (It works).
A button which calls an activity in my app and send it in a parameter the ID of the item.
And the problem is the second button, my solution doesn't work.
Here is the problem:
And so, this is the code which doesn't work:
row.setOnClickPendingIntent(R.id.taskButton, onClickPendingIntent);
// Creating an onclick event for the done button
Intent doneIntent = new Intent(mContext, WidgetProvider.class);
doneIntent.putExtra("DONE_TASK", "DOOOOM");
PendingIntent onDoneIntent = PendingIntent.getActivity(mContext, 0, doneIntent, 0);
row.setOnClickPendingIntent(R.id.doneButton, onDoneIntent);
Here is the complete WidgetFactory class:
import java.util.Collections;
import java.util.Comparator;
import java.util.GregorianCalendar;
import java.util.Vector;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.net.Uri;
import android.view.View;
import android.widget.RemoteViews;
import android.widget.RemoteViewsService;
public class WidgetFactory implements RemoteViewsService.RemoteViewsFactory {
private Vector<EventInfo> mAllEvents;
private Context mContext;
public WidgetFactory(Context ctxt, Intent intent) {
// Creating member vars
mContext = ctxt;
updateAllEventsVector();
}
private void updateAllEventsVector() {
SharedInstances sharedInstances = SharedInstances.get();
mAllEvents = new Vector<EventInfo>();
if (sharedInstances != null) {
TaskRequestManager taskManager = sharedInstances
.getTaskRequestManager();
CalendarRequestManager calManager = sharedInstances
.getCalendarRequestManager();
Vector<TaskEvent> tasks = null;
Vector<CalendarEvent> events = null;
if (taskManager != null)
tasks = taskManager.readTasksToday(mContext);
if (calManager != null)
events = calManager.readCalendarEventsToday(mContext);
if (!tasks.isEmpty())
mAllEvents.addAll(tasks);
if (!events.isEmpty())
mAllEvents.addAll(events);
mAllEvents = sortByDate(mAllEvents);
}
}
#SuppressWarnings({ "unchecked", "rawtypes" })
public Vector<EventInfo> sortByDate(Vector<EventInfo> events)
{
Vector<EventInfo> sortedEvents = new Vector<EventInfo>();
for(EventInfo event : events)
{
if ((event.getStartTime()+event.getEventDuration()) > GregorianCalendar.getInstance().getTimeInMillis())
sortedEvents.add(event);
}
Collections.sort(events, new Comparator() {
public int compare(Object arg0, Object arg1)
{
EventInfo event0 = (EventInfo)arg0;
EventInfo event1 = (EventInfo)arg1;
if (event0.getStartTime()+event0.getEventDuration() > event1.getStartTime()+event1.getEventDuration())
return 1;
else if (event0.getStartTime()+event0.getEventDuration() == event1.getStartTime()+event1.getEventDuration())
return 0;
else if (event0.getStartTime()+event0.getEventDuration() < event1.getStartTime()+event1.getEventDuration())
return -1;
return 0;
}
});
return sortedEvents;
}
#Override
public int getCount() {
return mAllEvents.size();
}
#Override
public long getItemId(int arg0) {
return (arg0);
}
#Override
public RemoteViews getLoadingView() {
return null;
}
#Override
public RemoteViews getViewAt(int position) {
// Getting item view
RemoteViews row = new RemoteViews(mContext.getPackageName(),
R.layout.done_task_item);
EventInfo eventInfo = mAllEvents.get(position);
row.setInt(R.id.item_event, "setBackgroundColor", Color.argb(60, Color.red(eventInfo.getColor()), Color.green(eventInfo.getColor()), Color.blue(eventInfo.getColor())));
// Converts startTime and endTime in string
String startTime = TimeCursor.getAdaptativeTime(eventInfo.getStartTime());
String endTime = TimeCursor.getAdaptativeTime((eventInfo
.getEventDuration() + eventInfo.getStartTime()));
//Get title
String title = eventInfo.getTitle();
// Setting data in the view
row.setTextViewText(R.id.titleTask, title);
row.setTextViewText(R.id.periodTask, startTime + " to " + endTime);
//Check type of event
if (eventInfo.isTask()) {
//endDate > GregorianCalendar.getInstance().getTimeInMillis() ) {
//Check if action exists
if (eventInfo.getAction() != null) {
//Get the action title
String action = eventInfo.getAction()
.getTitleText();
//Create a onClickPendingIntent for taskButton
PendingIntent onClickPendingIntent = null;
//Add related button
if (action.equals("Call"))
{
//Set call icon to taskButton
row.setImageViewResource(R.id.taskButton, R.drawable.ic_call_white );
//Get numbers from the contact
Vector<TelOrEmailItem> tel = eventInfo.getContact().getAllPhoneNumbers(mContext.getResources() , mContext, eventInfo.getAction());
// Creating an onclick event for call somebody
Intent callIntent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:"+tel.get(0).getMainText()));
onClickPendingIntent = PendingIntent.getActivity(
mContext, 0, callIntent, 0);
}
else if (action.equals("SMS"))
{
//Set sms icon to taskButton
row.setImageViewResource(R.id.taskButton, R.drawable.ic_sms_white);
//Get numbers from the contact
Vector<TelOrEmailItem> tel = eventInfo.getContact().getAllPhoneNumbers(mContext.getResources() , mContext, eventInfo.getAction());
// Creating an onclick event for call somebody
Intent smsIntent = new Intent(Intent.ACTION_SENDTO, Uri.parse("smsto:"+tel.get(0).getMainText()));
onClickPendingIntent = PendingIntent.getActivity(
mContext, 0, smsIntent, 0);
}
/*else if (action.equals("Chat with"))
row.setImageViewResource(R.id.taskButton, R.drawable.ic_chat_white);*/
else if (action.equals("eMail") || action.equals("Mail") || action.equals("Write to"))
{
//Set email icon to taskButton
row.setImageViewResource(R.id.taskButton, R.drawable.ic_email_white);
//Get numbers from the contact
Vector<TelOrEmailItem> tel = eventInfo.getContact().getAllEMails(mContext, eventInfo.getAction());
//Creating an onclick event for email somebody
Intent emailIntent = new Intent(Intent.ACTION_SEND);
emailIntent.setType("plain/text");
emailIntent.putExtra(Intent.EXTRA_EMAIL,
new String[]{tel.get(0).getMainText()});
onClickPendingIntent = PendingIntent.getActivity(
mContext, 0, emailIntent, 0);
}
/*else if (action.equals("Skype"))
row.setImageViewResource(R.id.taskButton, R.drawable.ic_skype_white);*/
//Assign the intent to the taskButton
row.setOnClickPendingIntent(R.id.taskButton, onClickPendingIntent);
// Creating an onclick event for the done button
Intent doneIntent = new Intent(mContext, WidgetProvider.class);
doneIntent.putExtra("DONE_TASK", "DOOOOM");
PendingIntent onDoneIntent = PendingIntent.getActivity(mContext, 0, doneIntent, 0);
row.setOnClickPendingIntent(R.id.doneButton, onDoneIntent);
}
else
row.setViewVisibility(R.id.taskButton, View.GONE); //hidde the taskButton
return row;
}
//Check if it's an event
else if(eventInfo.isEvent()) {
//hidde task button (Done)
row.setViewVisibility(R.id.doneButton, View.GONE);
CalendarEvent ev = eventInfo.getCalendarEvent();
String location = ev.getEventLocation();
if (location != null && !location.isEmpty())
{
//Set the locate icon on the taskButton
row.setImageViewResource(R.id.taskButton, R.drawable.ic_locate_white);
//Define the place to open the map
Intent mapIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("geo:0,0?q="+location));
PendingIntent onMapIntent = PendingIntent.getActivity(
mContext, 0, mapIntent, 0);
row.setOnClickPendingIntent(R.id.taskButton, onMapIntent);
}
else
row.setViewVisibility(R.id.taskButton, View.GONE);
return row;
}
return null;
}
#Override
public int getViewTypeCount() {
return 1;
}
#Override
public boolean hasStableIds() {
return (true);
}
#Override
public void onCreate() {
}
#Override
public void onDataSetChanged() {
// On data changes, update mTasks
updateAllEventsVector();
}
#Override
public void onDestroy() {
mAllEvents = null;
}
}
And thank you :)
Edit:
Yeaye !
Problem solved or not...
Method onClickPendingIntent() is working now, here is the code :
// Creating an onclick event for the done button
Intent onClickDone = new Intent(mContext, DoneTaskActivity.class);
onClickDone.putExtra("TASK_ID", eventInfo.getTaskEvent().getTaskId());
PendingIntent onClickPendingDone = PendingIntent.getActivity(mContext, 0, onClickDone, 0);
row.setOnClickPendingIntent(R.id.doneButton, onClickPendingDone);
But another problem exists: The DoneTaskActivity doesn't receive the extra declared as TASK_ID. In the onCreate() method of the DoneTaskActivity, the Bundle var in parameter stays to null.
Help :(
When using a list view in a widget you need to use the setOnClickFillInIntent listener. From the official docs;
When using collections (eg. ListView, StackView etc.) in widgets, it
is very costly to set PendingIntents on the individual items, and is
hence not permitted. Instead a single PendingIntent template can be
set on the collection
Inside your RemoteViewsFactory you use it like this;
public RemoteViews getViewAt(int position) {
// position will always range from 0 to getCount() - 1.
// Construct a RemoteViews item based on the app widget item XML file, and set the
// text based on the position.
RemoteViews rv = new RemoteViews(mContext.getPackageName(), R.layout.widget_item);
rv.setTextViewText(R.id.widget_item, mWidgetItems.get(position).text);
// Next, set a fill-intent, which will be used to fill in the pending intent template
// that is set on the collection view in StackWidgetProvider.
Bundle extras = new Bundle();
extras.putInt(StackWidgetProvider.EXTRA_ITEM, position);
Intent fillInIntent = new Intent();
fillInIntent.putExtras(extras);
// Make it possible to distinguish the individual on-click
// action of a given item
rv.setOnClickFillInIntent(R.id.widget_item, fillInIntent);
...
// Return the RemoteViews object.
return rv;
}
You also need to use a standard PendingIntent as individual list items can't set PendingIntents, see docs on AppWidgets.
The first parameter of 'putExtra' must include a package prefix.
If your app's package name is 'com.test', you should put 'com.test.TASK_ID'. Same name on receiving part.
try to add this:
// When intents are compared, the extras are ignored, so we need to embed the extras
// into the data so that the extras will not be ignored.
onClickDone.setData(Uri.parse(onClickDone.toUri(Intent.URI_INTENT_SCHEME)));
before
row.setOnClickPendingIntent(R.id.doneButton, onClickPendingDone);